DevOps Classroom Series – 05/Aug/2020

Ansible lamp stack contd..

  • Lamp stack playbook for yaml
---
- name: 'Install and configure lamp'
  hosts: ubuntu
  become: yes
  tasks:
    - name: install apache2 and update ubuntu package definitions
      apt:
        name: apache2
        update_cache: yes
        state: present
    - name: enable and start apache2
      service:
        name: apache2
        enabled: yes
        state: started
    - name: install php
      apt:
        name: php
        state: present
    - name: install libapache2-mod-php
      apt:
        name: libapache2-mod-php
        state: present
    - name: install php-mysql
      apt:
        name: php-mysql
        state: present
    - name: install php-cli
      apt:
        name: php-cli
        state: present
    - name: restart apache
      service:
        name: apache2
        state: restarted
  • Lamp stack playbook for centos
---
- name: install lamp stack on Centos
  become: yes
  hosts: centos
  tasks:
    - name: install apache
      yum:
        name: httpd
        state: present
    - name: start and enable apache
      service:
        name: httpd
        enabled: yes
        state: started
    - name: install php
      yum:
        name: php
        state: present
    - name: install php-mysql
      yum:
        name: php-mysql
        state: present
    - name: install php-fpm
      yum:
        name: php-fpm
        state: present
    - name: restart apache
      service:
        name: httpd
        state: restarted

  • For installing php modules we have used the same task with different values. consider the below statement
# repeating statements
print(1)
print(2)
print(3)
print(4)

# using loops
for index in range(1,4):
    print(index)
  • Now we need to find out if the loops are supported by ansible and if yes how? Refer Here for ansible documentation
- name: add several users
  user:
    name: "{{ item }}"
    state: present
    groups: "wheel"
  loop:
     - testuser1
     - testuser2

  • The above example is equivalent to
- name: add testuser1
  user:
    name: testuser1
    state: present
    group: wheel
- name: add testuser2
  user:
    name: testuser2
    state: present
    group: wheel

  • Consider the following lines in centos yaml
- name: install php
    yum:
    name: php
    state: present
- name: install php-mysql
    yum:
    name: php-mysql
    state: present
- name: install php-fpm
    yum:
    name: php-fpm
    state: present
  • These can be replaced with
- name: install php packages
  yum:
    name: "{{ item }}"
    state: present
  loop:
    - php
    - php-mysql
    - php-fpm

  • If the similar concept is applied to ubuntu.yaml
- name: install php packages
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - php
    - libapache2-mod-php
    - php-mysql
    - php-cli


  • By adopting above changes our lamp_centos.yaml will be
---
- name: install lamp stack on Centos
  become: yes
  hosts: centos
  tasks:
    - name: install apache
      yum:
        name: httpd
        state: present
    - name: start and enable apache
      service:
        name: httpd
        enabled: yes
        state: started
    - name: install php packages
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - php
        - php-mysql
        - php-fpm
    - name: restart apache
      service:
        name: httpd
        state: restarted

  • lamp_ubuntu.yaml will be looking as shown below
---
- name: 'Install and configure lamp'
  hosts: ubuntu
  become: yes
  tasks:
    - name: install apache2 and update ubuntu package definitions
      apt:
        name: apache2
        update_cache: yes
        state: present
    - name: enable and start apache2
      service:
        name: apache2
        enabled: yes
        state: started
    - name: install php packages
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - php
        - libapache2-mod-php
        - php-mysql
        - php-cli
    - name: restart apache
      service:
        name: apache2
        state: restarted
  • Now execute these playbooks to verify if they are working or not Preview Preview
  • Do i really need two files, cant i write something like
if node is centos
  execute the centos tasks
else if node is ubuntu 
  execute the ubuntu tasks
  • How to find if the node is ubuntu or centos?
  • Ansible has concept of gathering a facts. Facts are information about nodes. facts can be collected by using a module called as setup. Refer Here
  • Execute the following commands
ansible -i hosts -m setup centos
ansible -i hosts -m setup ubuntu
  • Lets evaluate playbook vs adhoc command
- name: testing
  setup:
    filter: "*distribution*"

ansible -m setup -a "filter=*distribution*" all

Preview

  • So now we have some thing to verify or use as condition in playbook. For centos machine the value of ansible_distribution is "Centos" and for ubuntu node the value is "Ubuntu"
if ansible_distribution == "Centos"
   run centos tasks
else if ansible_distribution == "Ubuntu"
   run ubuntu tasks
  • For ansible conditionals refer here
  • IF the fact name is ansible_something this can be used in playbook as ansible_facts[‘something’]. our key is ansible_distribution so we will be using ansible_facts[‘distribution’]
- name: "shut down Debian flavored systems"
  command: /sbin/shutdown -t now
  when: ansible_facts['os_family'] == "Debian"
  • Our resulting playbook with combined yaml files will be
---
- name: install apache
  hosts: all
  become: yes
  tasks:
    - name: install httpd
      yum:
        name: httpd
        state: present
      when: ansible_facts['distribution'] == "CentOS"
    - name: start and enable httpd
      service:
        name: httpd
        enabled: yes
        state: started
      when: ansible_facts['distribution'] == "CentOS"
    - name: install php packages httpd
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - php
        - php-mysql
        - php-fpm
      when: ansible_facts['distribution'] == "CentOS"
    - name: restart httpd
      service:
        name: httpd
        state: restarted
      when: ansible_facts['distribution'] == "CentOS"
    - name: install apache2 and update ubuntu package definitions
      apt:
        name: apache2
        update_cache: yes
        state: present
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: enable and start apache2
      service:
        name: apache2
        enabled: yes
        state: started
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: install php packages
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - php
        - libapache2-mod-php
        - php-mysql
        - php-cli
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: restart apache
      service:
        name: apache2
        state: restarted
      when: ansible_facts['distribution'] == "Ubuntu"
  • Now lets execute the playbook
ansible-playbook -i hosts lamp.yaml

Preview

  • In ansible there is a generic module called as package.
  • This module when executed on centos will execute yum & when executed on ubuntu machines will execute apt-get, so shall we use this module
---
- name: install apache
  hosts: all
  become: yes
  tasks:
    - name: install httpd
      package:
        name: httpd
        state: present
      when: ansible_facts['distribution'] == "CentOS"
    - name: start and enable httpd
      service:
        name: httpd
        enabled: yes
        state: started
      when: ansible_facts['distribution'] == "CentOS"
    - name: install php packages httpd
      package:
        name: "{{ item }}"
        state: present
      loop:
        - php
        - php-mysql
        - php-fpm
      when: ansible_facts['distribution'] == "CentOS"
    - name: restart httpd
      service:
        name: httpd
        state: restarted
      when: ansible_facts['distribution'] == "CentOS"
    - name: update Ubuntu packages
      apt:
        update_cache: yes
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: install apache2 
      package:
        name: apache2
        state: present
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: enable and start apache2
      service:
        name: apache2
        enabled: yes
        state: started
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: install php packages
      package:
        name: "{{ item }}"
        state: present
      loop:
        - php
        - libapache2-mod-php
        - php-mysql
        - php-cli
      when: ansible_facts['distribution'] == "Ubuntu"
    - name: restart apache
      service:
        name: apache2
        state: restarted
      when: ansible_facts['distribution'] == "Ubuntu"
  • Now executing this will get the same results Preview
  • But in our playbook we use different package task for ubuntu and centos. Cant we use one package task rather than two package tasks?. What is difference in
- name: install httpd
      package:
        name: httpd
        state: present
      when: ansible_facts['distribution'] == "CentOS"
- name: install apache2 
      package:
        name: apache2
        state: present
      when: ansible_facts['distribution'] == "Ubuntu"

  • Lets compare the above statements to
if machine is ubuntu
    print("ubuntu")
else if machine is centos
    print("centos")

or 
def print_message(message):
   print(message)
  • To achieve this we need to use variable message. So lets see if ansible supports variables. Refer Here

Summary

  • Today we have introduced
    • Looping statements using loop
    • conditional statements using when
    • information about nodes using facts and setup module
    • We have discussed about generic os packager module package

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About learningthoughtsadmin