Ansible: Good Things Come to Those Who Wait
I have been a windows admin for many years. This tenure has much to do with local job opportunities and less so about a staunch love of one side. As a person who attempts to stay current in both worlds, I am currently dabbling with Configuration Management or Desired State Configuration (MS Speak). Because my place of employment doesn't have a decent sized GNU/Linux deployment I am really only able to go it alone in lab environments, but hey, I still enjoy it!
CM is not new, the Chef and Puppet camps have been around for quite some time. I simply never started the journey with either product, thus I won't comment on them, other than to say it was probably because I was too lazy. :)
Fast forward to today and there are several in the CM space. Salt, Ansible, Puppet, Chef, etc.
I did some basic research and landed on Ansible. There isn't a ton of thought that went into this conclusion, but as a long time windows admin with a disdain for agents... well you get my point. To be fair to myself, that was not the only criteria. I love the design choices made by the Ansible team, Jinja2, YAML, SSH, few dependencies, and to top it off the documentation is first rate.
I am less than a week into this adventure and have found Ansible to be a breeze to configure. Did I mention there are almost zero dependencies on the client and master machines? The first step is to indoctrinate new machines, ie creating a user account for Ansible, fixing sudoers, sshd.conf, and transporting ssh keys
I have decided to leave all the upfront work in a single YAML playbook (run as root) and setup a more elegant scheme once the machines are commissioned.
Once the machines are ready to rock, I retrieve keys to the known_hosts file on the master node.
The so called indoctrinating is done. I will now create a role that can be assigned to a group of servers. There is a nice tool to generate the appropriate folder structure for a role. The tool is called ansible-galaxy, which additionally can also be used to deploy community YAML playbooks. Cool! For simplicity sake I am strictly using it to create the role based directory structure.
Now that the structure is created we can populate the skeleton with relevant YAML. For example ntp/vars/main.yml
Create some tasks to do actual work. Example ntp/tasks/main.yml
Now I simply need to create a playbook that includes the ntp role.
The following command will deploy and enable ntpd on all my servers!
CM is not new, the Chef and Puppet camps have been around for quite some time. I simply never started the journey with either product, thus I won't comment on them, other than to say it was probably because I was too lazy. :)
Fast forward to today and there are several in the CM space. Salt, Ansible, Puppet, Chef, etc.
I did some basic research and landed on Ansible. There isn't a ton of thought that went into this conclusion, but as a long time windows admin with a disdain for agents... well you get my point. To be fair to myself, that was not the only criteria. I love the design choices made by the Ansible team, Jinja2, YAML, SSH, few dependencies, and to top it off the documentation is first rate.
I am less than a week into this adventure and have found Ansible to be a breeze to configure. Did I mention there are almost zero dependencies on the client and master machines? The first step is to indoctrinate new machines, ie creating a user account for Ansible, fixing sudoers, sshd.conf, and transporting ssh keys
--- - hosts: all remote_user: root tasks: - name: add user ansi user: name=ansi groups=wheel - name: transport ssh keys authorized_key: user=ansi key='{{ lookup('file','~/.ssh/id_rsa.pub') }}' - name: set nopasswd for wheel lineinfile: dest=/etc/sudoers regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD{{':'}} ALL' state=present validate='visudo -cf %s' when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int >= 6 - name: disable ssh root access lineinfile: dest=/etc/ssh/sshd_config regexp="^#PermitRootLogin" line="PermitRootLogin no" state=present when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int >= 6 notify: - restart sshd handlers: - name: restart sshd service: name=sshd state=restarted
I have decided to leave all the upfront work in a single YAML playbook (run as root) and setup a more elegant scheme once the machines are commissioned.
[root@main ~]# su - ansi [ansi@main ~]$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/ansi/.ssh/id_rsa): Created directory '/home/ansi/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/ansi/.ssh/id_rsa. Your public key has been saved in /home/ansi/.ssh/id_rsa.pub. [ansi@main ~]$ ansible-playbook indoctrinate.yml --ask-pass SSH password: PLAY [all] ******************************************************************** GATHERING FACTS *************************************************************** ok: [server4.tui.lan] ok: [server3.tui.lan] ok: [server2.tui.lan] ok: [server1.tui.lan] TASK: [Add user ansi] ********************************************************* changed: [server4.tui.lan] changed: [server2.tui.lan] changed: [server1.tui.lan] changed: [server3.tui.lan] TASK: [transport ssh keys] ************************************* changed: [server1.tui.lan] changed: [server4.tui.lan] changed: [server3.tui.lan] changed: [server2.tui.lan] TASK: [set nopasswd for wheel] ************************************************ changed: [server3.tui.lan] changed: [server2.tui.lan] changed: [server4.tui.lan] changed: [server1.tui.lan] TASK: [disable ssh root access] **************************************************** changed: [server2.tui.lan] changed: [server3.tui.lan] changed: [server1.tui.lan] changed: [server4.tui.lan] NOTIFIED: [restart sshd] ****************************************************** changed: [server4.tui.lan] changed: [server2.tui.lan] changed: [server1.tui.lan] changed: [server3.tui.lan] PLAY RECAP ******************************************************************** server1.tui.lan : ok=6 changed=5 unreachable=0 failed=0 server2.tui.lan : ok=6 changed=5 unreachable=0 failed=0 server3.tui.lan : ok=6 changed=5 unreachable=0 failed=0 server4.tui.lan : ok=6 changed=5 unreachable=0 failed=0
Once the machines are ready to rock, I retrieve keys to the known_hosts file on the master node.
[ansi@main ~]$ ssh-keyscan server{1..4}.tui.lan >> ~/.ssh/known_hosts
The so called indoctrinating is done. I will now create a role that can be assigned to a group of servers. There is a nice tool to generate the appropriate folder structure for a role. The tool is called ansible-galaxy, which additionally can also be used to deploy community YAML playbooks. Cool! For simplicity sake I am strictly using it to create the role based directory structure.
[ansi@main roles]$ ansible-galaxy init ntp ntp was created successfully [ansi@main roles]$ ls -R ntp ntp: defaults files handlers meta README.md tasks templates vars ntp/defaults: main.yml ntp/files: ntp/handlers: main.yml ntp/meta: main.yml ntp/tasks: main.yml ntp/templates: ntp/vars: main.yml
Now that the structure is created we can populate the skeleton with relevant YAML. For example ntp/vars/main.yml
--- # vars file for ntp ntp_servers: - 0.pool.ntp.org - 1.pool.ntp.org - 2.pool.ntp.org - 3.pool.ntp.org
Create some tasks to do actual work. Example ntp/tasks/main.yml
--- # tasks file for ntp - name: install ntp sudo: true yum: pkg=ntp state=installed when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int >= 6 - name: configure ntp sudo: true template: src=ntp.conf.j2 dest=/etc/ntp.conf notify: - restart ntpd when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int >= 6 - name: start and enable ntpd service sudo: true service: name=ntpd state=running enabled=yes when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int >= 6
Now I simply need to create a playbook that includes the ntp role.
--- # file: servers.yml - hosts: servers roles: - ntp
The following command will deploy and enable ntpd on all my servers!
[ansi@main playbooks]$ ansible-playbook servers.yml PLAY [all] ******************************************************************** GATHERING FACTS *************************************************************** ok: [server1.tui.lan] ok: [server3.tui.lan] ok: [server2.tui.lan] ok: [server4.tui.lan] TASK: [ntp | be sure ntp is installed] **************************************** ok: [server1.tui.lan] ok: [server2.tui.lan] ok: [server3.tui.lan] ok: [server4.tui.lan] TASK: [ntp | be sure ntp is configured] *************************************** ok: [server1.tui.lan] ok: [server2.tui.lan] changed: [server3.tui.lan] changed: [server4.tui.lan] TASK: [ntp | be sure ntpd is running and enabled] ***************************** ok: [server2.tui.lan] ok: [server4.tui.lan] ok: [server3.tui.lan] ok: [server1.tui.lan] NOTIFIED: [ntp | restart ntpd] ************************************************ changed: [server3.tui.lan] changed: [server4.tui.lan] PLAY RECAP ******************************************************************** server1.tui.lan : ok=4 changed=0 unreachable=0 failed=0 server2.tui.lan : ok=4 changed=0 unreachable=0 failed=0 server3.tui.lan : ok=5 changed=2 unreachable=0 failed=0 server4.tui.lan : ok=5 changed=2 unreachable=0 failed=0
Comments
Post a Comment