Strategy & Serial

Strategy & Serial #

Secara default Ansible menjalankan setiap task di semua host sebelum pindah ke task berikutnya. Ini disebut strategi linear — aman dan mudah diprediksi, tapi tidak selalu optimal. Untuk deployment yang ingin setiap server berjalan secepat mungkin secara independen, atau untuk rolling deployment yang hanya mengupdate beberapa server sekaligus, kamu perlu memahami cara mengendalikan alur eksekusi paralel ini.

Tiga Strategy Utama #

linear (default):
  Task 1 → semua host selesai → Task 2 → semua host selesai → ...
  Kelebihan: Mudah diprediksi, semua host selalu di tahap yang sama
  Kekurangan: Host yang cepat menunggu host yang lambat

free:
  Setiap host berjalan secepat mungkin, tidak menunggu host lain
  Kelebihan: Lebih cepat secara total jika ada variasi kecepatan host
  Kekurangan: Host bisa di tahap yang berbeda — lebih sulit di-debug

host_pinned:
  Seperti free, tapi setiap 'slot' paralel diselesaikan sebelum lanjut
  Berguna saat kamu ingin membatasi berapa host yang aktif sekaligus
# Menggunakan strategy di level play
- name: Deploy dengan free strategy
  hosts: webservers
  strategy: free      # Setiap host berjalan independen

  tasks:
    - name: Pull kode
      git:
        repo: https://github.com/company/app.git
        dest: /opt/app
        version: "{{ version }}"

    - name: Install dependencies
      pip:
        requirements: /opt/app/requirements.txt
        virtualenv: /opt/app/venv
      # Setiap host langsung lanjut ke task ini setelah pull selesai
      # tanpa menunggu host lain selesai pull

serial: Rolling Deployment #

serial mengontrol berapa banyak host yang diproses sekaligus dalam satu “batch”:

- name: Rolling deployment — 1 server sekaligus
  hosts: webservers
  serial: 1           # Update satu server, tunggu selesai, baru lanjut ke berikutnya

  tasks:
    - name: Deploy kode baru
      git:
        repo: https://github.com/company/app.git
        dest: /opt/app
        version: "{{ version }}"

    - name: Restart aplikasi
      systemd:
        name: myapp
        state: restarted

    - name: Verifikasi health
      uri:
        url: "http://localhost:{{ app_port }}/health"
        status_code: 200
      retries: 6
      delay: 5

serial bisa berupa angka, persentase, atau list untuk ramp-up bertahap:

# Serial sebagai persentase
- hosts: webservers
  serial: "25%"       # Update 25% server sekaligus (misal: 2 dari 8 server)

# Serial sebagai list: canary deployment
- hosts: webservers
  serial:
    - 1               # Batch 1: satu server saja (canary)
    - "10%"           # Batch 2: 10% dari sisa
    - "50%"           # Batch 3: 50% dari sisa
    - "100%"          # Batch 4: semua yang tersisa

Pola list ini sangat berguna untuk canary deployment — deploy ke satu server dulu, verifikasi, baru lanjut ke lebih banyak server.


Pola Canary Deployment #

# playbooks/canary-deploy.yml
---
- name: Canary deployment — tahap 1 (1 server)
  hosts: webservers
  serial: 1
  max_fail_percentage: 0    # Hentikan jika canary gagal

  tasks:
    - name: Deploy ke canary server
      git:
        repo: https://github.com/company/app.git
        dest: /opt/app
        version: "{{ version }}"

    - name: Restart aplikasi
      systemd:
        name: myapp
        state: restarted

    - name: Tunggu dan verifikasi canary
      uri:
        url: "http://localhost:{{ app_port }}/health"
        status_code: 200
      retries: 12
      delay: 10

    - name: Verifikasi error rate canary tidak meningkat
      uri:
        url: "http://prometheus.internal/api/v1/query"
        method: GET
        body_format: form-urlencoded
        body: >-
          query=rate(http_requests_total{status=~"5..",instance="{{ inventory_hostname }}"}[5m])          
      register: error_rate
      failed_when:
        - error_rate.json.data.result | length > 0
        - error_rate.json.data.result[0].value[1] | float > 0.01

- name: Deploy ke sisa server setelah canary OK
  hosts: webservers[1:]   # Semua kecuali server pertama (canary)
  serial: "25%"

  tasks:
    - name: Deploy ke sisa server
      git:
        repo: https://github.com/company/app.git
        dest: /opt/app
        version: "{{ version }}"

    - name: Restart aplikasi
      systemd:
        name: myapp
        state: restarted

throttle: Batasi Konkurensi di Level Task #

serial mengontrol batch di level play. throttle membatasi konkurensi di level task individual — berguna untuk task yang membebani resource eksternal:

- name: Deploy ke semua server
  hosts: webservers
  strategy: free        # Setiap host berjalan secepat mungkin

  tasks:
    - name: Pull kode (bisa paralel sepenuhnya)
      git:
        repo: https://github.com/company/app.git
        dest: /opt/app
        version: "{{ version }}"

    - name: Download artifact dari S3 (batasi 5 download sekaligus)
      aws_s3:
        bucket: my-artifacts
        object: "releases/{{ version }}/app.tar.gz"
        dest: /tmp/app.tar.gz
        mode: get
      throttle: 5       # Maksimal 5 host menjalankan task ini bersamaan
      # Mencegah throttling dari S3 atau membanjiri bandwidth

    - name: Restart aplikasi (bisa paralel sepenuhnya)
      systemd:
        name: myapp
        state: restarted

run_once dengan Serial #

Saat menggunakan serial, task dengan run_once hanya berjalan sekali di batch pertama, bukan di setiap batch:

- name: Rolling deploy dengan migrasi database
  hosts: appservers
  serial: 2

  pre_tasks:
    - name: Jalankan migrasi database (hanya sekali, di awal)
      command: python manage.py migrate
      run_once: true      # Hanya di batch pertama, server pertama
      delegate_to: "{{ groups['appservers'][0] }}"

  tasks:
    - name: Deploy kode ke semua server (per batch)
      git:
        repo: https://github.com/company/app.git
        dest: /opt/app
        version: "{{ version }}"

Ringkasan #

  • linear (default): semua host menyelesaikan satu task sebelum lanjut — mudah diprediksi tapi bisa lambat jika ada variasi kecepatan host.
  • free: setiap host berjalan secepat mungkin tanpa menunggu host lain — lebih cepat, tapi lebih sulit di-debug karena host bisa di tahap berbeda.
  • serial: 1 untuk zero-downtime rolling deployment — update satu server, verifikasi, baru lanjut ke berikutnya.
  • serial sebagai list ([1, "10%", "50%", "100%"]) untuk canary deployment — ramp-up bertahap dengan verifikasi di setiap tahap.
  • throttle untuk membatasi konkurensi di level task individual — berguna saat task membebani resource eksternal (S3, database, API rate limit).
  • max_fail_percentage: 0 bersama serial untuk menghentikan deployment segera jika ada kegagalan — tidak ada batch berikutnya jika batch sebelumnya gagal.

← Sebelumnya: Jinja2 Lanjutan   Berikutnya: AWX & Tower →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact