It has been quite a while since the first post in this series: “Getting started with Ansible – Preparations“. If you recap from the initial post Ansible was running on the control host and this simple Ansible command:
ansible postgres-servers -a "/bin/echo 11" -f 5
… was successfully executed against the “postgres-servers” group. So far, so good. Getting Ansible up and running for just this would not be very usefull, so lets see where we might go from here.
When you start to think on what you want to automate you should start to think on how you want to organize your Ansible stuff. The documentation provides some guidelines which might or might not fit your needs. For the scope of this series lets stick to what the documentation is recommeding as one possible way to go. The directory layout on the control host will then be:
[[email protected] ~]$ sudo mkdir /opt/ansible [[email protected] ~]$ sudo chown ansible:ansible /opt/ansible [[email protected] ~]$ touch /opt/ansible/development # the inventory file for the development hosts [[email protected] ~]$ touch /opt/ansible/staging # the inventory file for the staging hosts [[email protected] ~]$ touch /opt/ansible/production # the inventory file for the production hosts [[email protected] ~]$ mkdir /opt/ansible/roles/ [[email protected] ~]$ mkdir /opt/ansible/roles/common # a role valid for "common" stuff [[email protected] ~]$ mkdir /opt/ansible/roles/common/tasks [[email protected] ~]$ mkdir /opt/ansible/roles/common/handlers [[email protected] ~]$ mkdir /opt/ansible/roles/common/templates [[email protected] ~]$ mkdir /opt/ansible/roles/common/files [[email protected] ~]$ mkdir /opt/ansible/roles/common/vars [[email protected] ~]$ mkdir /opt/ansible/roles/common/meta [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver # a role vaild for the PostgreSQL stuff [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver/tasks [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver/handlers [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver/templates [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver/files [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver/vars [[email protected] ~]$ mkdir /opt/ansible/roles/postgresqldbserver/meta
The concept of roles is explained in the documentation and you should definitely read that. We’ll come back to this later.
For now let’s place our two PostgreSQL hosts into the “development” inventory:
[[email protected] ~]$ echo "[postgresql-servers]" >> /opt/ansible/development [[email protected] ~]$ echo "192.168.22.171" >> /opt/ansible/development [[email protected] ~]$ echo "192.168.22.172" >> /opt/ansible/development
Passing our new inventory file to Ansible we should be able to perform the same simple task as in the first post:
[[email protected] ~]$ ansible -i /opt/ansible/development postgresql-servers -a "/bin/echo 11" 192.168.22.172 | SUCCESS | rc=0 >> 11 192.168.22.171 | SUCCESS | rc=0 >> 11
Ok, fine, this still works. When it comes to PostgreSQL one of the first steps when we want to install from source is to install all the operating system packages which are required. How could we do that with Ansible?
The initial step is to tell Ansible where to look for our roles. This is done by specifying the “roles_path” configuration parameter in the ansible.cfg configuration file:
[[email protected] ~]$ cat /etc/ansible/ansible.cfg | grep roles | grep -v "#" roles_path = /opt/ansible/roles
From here on we need to setup our role by creating an initial “site.yml” file:
[[email protected] ansible]$ cat roles/postgresqldbserver/site.yml --- # This playbook deploys a single PostgreSQL instance from the source code - hosts: postgresql-servers become: true become_user: root roles: - postgresqldbserver
You can see from the above that the “postgresql-servers” group is referenced. Additionally notice the “become” and the “become_user” flags. As we’re going to use yum to install the packages we need a way to become root on the target system and this is how you can instruct Ansible to do so.
Time to specify on how we want to install the packages. This is quite easy as well:
[[email protected] ansible]$ cat roles/postgresqldbserver/tasks/main.yml --- - name: Install PostgreSQL dependencies yum: name={{item}} state=present with_items: - gcc - openldap-devel - python-devel - readline-devel - openssl-devel - redhat-lsb - bison - flex - perl-ExtUtils-Embed - zlib-devel - crypto-utils - openssl-devel - pam-devel - libxml2-devel - libxslt-devel - tcl - tcl-devel - openssh-clients - bzip2 - net-tools - wget - screen - ksh
What did we do here? We created our first task. We tell Ansible to use “yum” to install our “items” (which are the packages we want to install). You can check the documentation for more information on the yum module.
Lets see if it works and we can execute our first task on both PostgreSQL nodes:
[[email protected] ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml PLAY [postgresql-servers] ****************************************************** TASK [setup] ******************************************************************* ok: [192.168.22.171] ok: [192.168.22.172] TASK [postgresqldbserver : Install PostgreSQL dependencies] ******************** changed: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh']) changed: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh']) PLAY RECAP ********************************************************************* 192.168.22.171 : ok=2 changed=1 unreachable=0 failed=0 192.168.22.172 : ok=2 changed=1 unreachable=0 failed=0
Cool, we just installed all the dependencies on both nodes with one Ansible command. We additionally want an operating system group for our PostgreSQL deployment so we add the following lines to the playbook:
- name: Add PostgreSQL operating system group group: name=postgressomegroup state=present
Execute the playbook again:
[[email protected] ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml PLAY [postgresql-servers] ****************************************************** TASK [setup] ******************************************************************* ok: [192.168.22.172] ok: [192.168.22.171] TASK [postgresqldbserver : Install PostgreSQL dependencies] ******************** ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh']) ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh']) TASK [postgresqldbserver : Add PostgreSQL operating system group] ************** changed: [192.168.22.171] changed: [192.168.22.172] PLAY RECAP ********************************************************************* 192.168.22.171 : ok=3 changed=1 unreachable=0 failed=0 192.168.22.172 : ok=3 changed=1 unreachable=0 failed=0
We did not change any of the packages but added the group. Lets add the PostgreSQL operating system user by adding these lines to the playbook:
- name: Add PostgreSQL operating system user user: name=postgres comment="PostgreSQL binaries owner" group=postgres
Execute again:
[[email protected] ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml PLAY [postgresql-servers] ****************************************************** TASK [setup] ******************************************************************* ok: [192.168.22.172] ok: [192.168.22.171] TASK [postgresqldbserver : Install PostgreSQL dependencies] ******************** ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh']) ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh']) TASK [postgresqldbserver : Add PostgreSQL operating system group] ************** changed: [192.168.22.171] changed: [192.168.22.172] TASK [postgresqldbserver : Add PostgreSQL operating system user] *************** changed: [192.168.22.171] changed: [192.168.22.172] PLAY RECAP ********************************************************************* 192.168.22.171 : ok=4 changed=2 unreachable=0 failed=0 192.168.22.172 : ok=4 changed=2 unreachable=0 failed=0
Really cool and simple. Just to prove lets connect to one of the nodes and check if the postgres user really is there:
[[email protected] ~] id -a postgres uid=1001(postgres) gid=1001(postgres) groups=1001(postgres) [[email protected] ~]
Perfect. In the next post we’ll install the PostgreSQL binaries.
For you reference this is the playbook as it looks now:
[[email protected] ansible]$ cat roles/postgresqldbserver/tasks/main.yml --- - name: Install PostgreSQL dependencies yum: name={{item}} state=present with_items: - gcc - openldap-devel - python-devel - readline-devel - openssl-devel - redhat-lsb - bison - flex - perl-ExtUtils-Embed - zlib-devel - crypto-utils - openssl-devel - pam-devel - libxml2-devel - libxslt-devel - tcl - tcl-devel - openssh-clients - bzip2 - net-tools - wget - screen - ksh - name: Add PostgreSQL operating system group group: name=postgressomegroup state=present - name: Add PostgreSQL operating system user user: name=postgres comment="PostgreSQL binaries owner" group=postgres