Ansible wait_for Module: รอให้ Service Ready ก่อน Deploy ต่อ

Ansible wait_for module ใช้หยุดรอให้เงื่อนไขบน remote server เป็นจริงก่อนดำเนินการ task ถัดไป ไม่ว่าจะเป็นรอให้ port เปิด, service พร้อม, ไฟล์ปรากฏ, หรือ connection ปิด — เหมาะสำหรับ deployment workflow ที่ต้องการให้ service พร้อมก่อน proceed ต่อ

บทความนี้ครอบคลุม parameters หลัก, การรอ port, การรอ service พร้อมด้วย path และ search string, การตั้ง timeout และ pattern สำหรับ zero-downtime rolling deployment

wait_for Module พื้นฐาน — รอ Port เปิด

ใช้บ่อยที่สุดคือรอให้ port เปิดหลัง start service ใช้ host และ port เพื่อระบุ endpoint ที่ต้องการตรวจสอบ และ timeout กำหนดเวลาสูงสุดที่ยอมรอ (default 300 วินาที)

---
- name: Basic wait_for usage
  hosts: all
  tasks:
    # รอให้ port 80 เปิดบน localhost
    - name: Wait for web server to start
      wait_for:
        host: localhost
        port: 80
        timeout: 60

    # รอ port บน remote host
    - name: Wait for database port
      wait_for:
        host: db.example.com
        port: 5432
        timeout: 120

    # รอ port เฉพาะ interface
    - name: Wait for app on specific interface
      wait_for:
        host: 0.0.0.0
        port: 8080
        timeout: 90

    # รอ port พร้อมกำหนด delay ก่อนเริ่มตรวจ
    - name: Wait for service with initial delay
      wait_for:
        host: localhost
        port: 3306
        delay: 10      # รอ 10 วินาทีก่อนเริ่มตรวจ
        timeout: 120

รอ Port ปิด — หลัง Stop Service

ใช้ state: stopped เพื่อรอให้ port ปิดสนิทก่อนดำเนินการต่อ เช่น รอให้ service เก่าหยุดทำงานก่อน start service ใหม่ หรือรอให้ connection drain ครบ

---
- name: Wait for port to close
  hosts: all
  tasks:
    # รอให้ port ปิดหลัง stop service
    - name: Stop old application
      service:
        name: myapp
        state: stopped

    - name: Wait for port to be released
      wait_for:
        host: localhost
        port: 8080
        state: stopped    # รอให้ port ไม่มีอะไร listen อยู่
        timeout: 60

    # รอ port ทั้งหมดใน list ปิด
    - name: Wait for all app ports to close
      wait_for:
        host: localhost
        port: "{{ item }}"
        state: stopped
        timeout: 30
      loop:
        - 8080
        - 8081
        - 8082

รอไฟล์ปรากฏหรือหายไป

ใช้ path แทน port เพื่อรอไฟล์ เช่น รอไฟล์ lock หายไป, รอ PID file ปรากฏ หรือรอ log file มีเนื้อหาที่ต้องการ

---
- name: Wait for file conditions
  hosts: all
  tasks:
    # รอไฟล์ปรากฏ
    - name: Wait for PID file to appear
      wait_for:
        path: /var/run/myapp.pid
        state: present
        timeout: 60

    # รอไฟล์หายไป (lock file ถูกลบ)
    - name: Wait for lock file to be removed
      wait_for:
        path: /tmp/deploy.lock
        state: absent
        timeout: 300

    # รอไฟล์มีข้อความที่ต้องการ (log ขึ้น "ready")
    - name: Wait for application ready message in log
      wait_for:
        path: /var/log/myapp/app.log
        search_regex: "Application started successfully"
        timeout: 120

    # รอ log ขึ้น "ready" หรือ "error" (ตรวจ error ด้วย)
    - name: Wait for startup or error
      wait_for:
        path: /var/log/myapp/app.log
        search_regex: "(started|FAILED)"
        timeout: 120
      register: startup_result

รอ Connection ได้รับการตอบกลับ

ใช้ state: started (default) ร่วมกับ search_regex เพื่อรอให้ service ตอบกลับด้วยข้อความที่กำหนด — เหมาะสำหรับ service ที่ต้องการตรวจสอบ response จริง ๆ ไม่ใช่แค่ port เปิด

---
- name: Wait for service response
  hosts: all
  tasks:
    # รอ SSH พร้อมหลัง reboot
    - name: Wait for SSH to come back
      wait_for:
        host: "{{ inventory_hostname }}"
        port: 22
        state: started
        delay: 30      # รอ 30 วินาทีให้ reboot เริ่ม
        timeout: 300
      delegate_to: localhost

    # รอ database accept connection
    - name: Wait for MySQL to accept connections
      wait_for:
        host: localhost
        port: 3306
        state: started
        timeout: 120

    # รอ Redis พร้อม
    - name: Wait for Redis
      wait_for:
        host: 127.0.0.1
        port: 6379
        timeout: 60

wait_for_connection — รอ Host กลับมา

wait_for_connection module (ต่างจาก wait_for) ใช้รอให้ Ansible สามารถเชื่อมต่อกลับไปยัง host ได้ เหมาะสำหรับหลัง reboot หรือหลัง provision server ใหม่

---
- name: wait_for_connection usage
  hosts: all
  tasks:
    # reboot แล้วรอกลับมา
    - name: Reboot server
      reboot:
        reboot_timeout: 300

    # หรือใช้ wait_for_connection หลัง reboot manual
    - name: Trigger reboot
      command: shutdown -r +1 "Rebooting for kernel update"
      async: 1
      poll: 0

    - name: Wait for host to come back online
      wait_for_connection:
        delay: 60          # รอ 60 วินาทีก่อนเริ่มลอง
        timeout: 300       # รอสูงสุด 300 วินาที
        sleep: 10          # probe ทุก 10 วินาที
        connect_timeout: 5 # timeout ต่อ attempt

    - name: Continue after reconnect
      debug:
        msg: "Host is back online — continuing deployment"

Pattern: Zero-Downtime Rolling Deployment

ตัวอย่าง Playbook ที่ใช้ wait_for เพื่อรับรองว่า service พร้อมรับ traffic ก่อน proceed ในแต่ละขั้นตอนของ rolling deployment

---
- name: Rolling deployment with wait_for
  hosts: appservers
  serial: 1    # deploy ทีละ server
  vars:
    app_name: myapp
    app_port: 8080
    health_log: "/var/log/{{ app_name }}/startup.log"

  tasks:
    # หยุด service เดิม
    - name: Stop application service
      service:
        name: "{{ app_name }}"
        state: stopped

    # รอ port ปิดก่อน deploy ใหม่
    - name: Wait for old process to release port
      wait_for:
        host: localhost
        port: "{{ app_port }}"
        state: stopped
        timeout: 60

    # deploy version ใหม่
    - name: Deploy new version
      git:
        repo: "{{ app_repo }}"
        dest: "/opt/{{ app_name }}/current"
        version: "{{ deploy_version }}"
        force: true

    # start service ใหม่
    - name: Start application service
      service:
        name: "{{ app_name }}"
        state: started

    # รอ port เปิด
    - name: Wait for application port to open
      wait_for:
        host: localhost
        port: "{{ app_port }}"
        state: started
        timeout: 120

    # รอ log บอกว่า ready
    - name: Wait for application ready signal
      wait_for:
        path: "{{ health_log }}"
        search_regex: "Server started on port {{ app_port }}"
        timeout: 60

    - name: Deployment complete on this server
      debug:
        msg: "{{ app_name }} v{{ deploy_version }} is running on {{ inventory_hostname }}"

สรุป

wait_for module เป็น building block สำคัญสำหรับสร้าง deployment workflow ที่น่าเชื่อถือ รองรับการรอ port เปิด/ปิด, ไฟล์ปรากฏ/หายไป, และ log ขึ้น pattern ที่กำหนด ผ่าน parameters ที่ชัดเจนพร้อม timeout และ delay ที่ควบคุมได้

Pattern ที่ควรจำ: ตั้ง delay ให้เหมาะสมเพื่อหลีกเลี่ยง probe ที่ไม่จำเป็น, ใช้ search_regex ใน log file เพื่อรอ “ready” message จริง ๆ แทนแค่รอ port เปิด, ใช้ state: stopped ก่อน deploy ใหม่เพื่อให้แน่ใจว่า process เก่าหยุดแล้ว และใช้ wait_for_connection แทน wait_for port: 22 สำหรับหลัง reboot เพราะ handle reconnect logic ได้ดีกว่า