14-10-2020 / blog / Jeroen van de Lockand

Ansible Automation - Zero Downtime webserver updates

 

In het eerste blog over dit onderwerp heb je gezien hoe je met Ansible 2 HAProxy loadbalancers met 3 NGINX webservers kunt installeren en configureren met Ansible. Dit noem je ook wel de "Day-1 Operations". Heb je het eerste blog nog niet gelezen? Doe dit dan eerst voordat je verder gaat.

 

In een echte wereld scenario draait er een applicatie op de webservers die bijdraagt aan de organisatie of een bedrijfsproces. In dit blog is dit een simpele website met de tekst "Application-X on ${servernaam}". De applicatie kan nu na de Day-1 Operations in gebruik genomen worden.

 

Vanaf dit punt en totdat de applicatie niet meer nodig is of vervangen wordt, zijn er "Day-2 Operations". Dit betreft alle activiteiten die nodig zijn om de applicatie draaiende te houden en te laten presteren zoals door de business verwacht wordt. Voorbeelden hiervan zijn monitoring, onderhoud, huishouding (bijv. log rotatie) en verbeteren om aan de vraag en verwachting te kunnen blijven voldoen. In dit blog ga ik hier een activiteit van uitlichten namelijk onderhoud en specifiek het installeren van updates zonder downtime op de webservers.

 

Rolling updates

Voor het uitvoeren van de updates maak ik een uitbreiding op de bestaande rollen en playbooks in Git. De code is beschikbaar op de Conclusion Xforce GitLab pagina hier.

 

Het update process ziet er als volgt uit:

- De webserver wordt uit de loadbalancer gehaald

- De updates worden uitgevoerd

- De webserver wordt herstart

- De webserver wordt weer toegevoegd aan de loadbalancer

 

Dit proces herhaalt zich tot alle webserver zijn geüpdatet. Laten we kijken hoe dit in een playbook eruit ziet. Review het het rolling_update.yml playbook.

 

---
- hosts: all

- hosts: webservers
  gather_facts: false
  become: yes
  serial: 1

  pre_tasks:
  - name: disable the server in haproxy
    haproxy: 
      state: disabled 
      host: "{{ inventory_hostname }}" 
      socket: /var/lib/haproxy/stats
      backend: web
      wait: yes
    delegate_to: "{{ item }}"
    with_items: "{{ groups.loadbalancers }}"

  tasks:
    - name: upgrade packages via yum
      yum:
        name: "*"
        state: latest
    
    - name: restart system
      shell: "sleep 3 && reboot"
      async: 1
      poll: 0
      
    - name: wait for the system to reboot
      wait_for_connection:
        connect_timeout: 20
        sleep: 10
        delay: 10
        timeout: 60

  post_tasks:
  - name: wait for webserver to come up
    wait_for: 
      host: "{{ inventory_hostname }}"
      port: 80 
      state: started 
      timeout: 60
      delay: 10

  - name: enable the server in haproxy
    haproxy: 
      state: enabled 
      host: "{{ inventory_hostname }}" 
      socket: /var/lib/haproxy/stats
      backend: web 
      wait: yes
      wait_retries: 10
      wait_interval: 5
    delegate_to: "{{ item }}"
    with_items: "{{ groups.loadbalancers }}"

 

In de pre_task wordt de webserver in HAProxy op maintenance gezet door gebruik te maken van de haproxy module, zodat nieuwe verzoeken op de overige webservers terecht komen tijdens het updaten van de webserver.

 

Vervolgens wordt een task uitgevoerd met de yum module die een package update als deze niet de laatst beschikbare versie is. Na de updates wordt het systeem herstart in deze task wordt een shell module uitgevoerd met de opties async 1 en poll 0. Hiermee voert Ansible de taak uit in een “vuren en vergeten” modus, wat wil zeggen de taak wordt uitgevoerd en Ansilble gaat direct door naar de volgende taak zonder te wachten op een resultaat. Dit is handig want tijdens de herstart kan Ansible geen verbinding maken met het systeem. In de volgende taak laten we daarom Ansible wachten met de wait_for_connection module tot het systeem weer benaderd kan worden voordat het verder gaat.

 

In de post tasks gebruiken we de wait_for module om te controleren dat de webserver weer bereikbaar is en te benaderen is op poort 80. De laatste taak wordt de webserver weer op actief gezet in HAProxy zodat verzoeken weer naar deze webserver worden gestuurd.

 

Weergegeven in afbeeldingen ziet dit er als volgt uit tijdens het updaten.

 

Hiermee zijn we aan het einde gekomen van dit blog. In dit blog heb ik

laten zien hoe de webservers geüpdatet kunnen worden zonder downtime van de applicatie met Ansible.