Resource Hooks ใน Argo CD: PreSync, Sync, PostSync สำหรับ Database Migration

Resource Hooks เป็นกลไกที่ทรงพลังใน Argo CD ซึ่งช่วยให้คุณสามารถควบคุมวงจรชีวิต (lifecycle) ของการ Deploy โดยการรัน Custom Tasks ในช่วงเวลาที่เหมาะสม ไม่ว่าจะเป็นการโยกย้ายฐานข้อมูล การตรวจสอบระบบ หรือการส่งการแจ้งเตือน บทความนี้จะอธิบายวิธีใช้ Resource Hooks อย่างมีประสิทธิภาพ

Resource Hooks คืออะไร

Resource Hooks เป็นเครื่องมือที่ช่วยให้คุณสามารถแทรก (intercept) กระบวนการ Sync ของ Argo CD ผ่านการกำหนด Annotations บน Kubernetes Resources ช่วยให้คุณสามารถรัน Jobs หรือ Scripts พิเศษได้ในช่วงเวลาที่กำหนด เช่น ก่อนการ Deploy (PreSync) หรือหลังการ Deploy (PostSync)

ประโยชน์ของ Resource Hooks

  • การโยกย้ายฐานข้อมูลอย่างปลอดภัย (Database Migrations)
  • การตรวจสอบและ Validation ก่อนการ Deploy
  • การส่งการแจ้งเตือนและ Notifications
  • การทำความสะอาดหลังการ Deploy (Cleanup)
  • การ Rollback อัตโนมัติเมื่อเกิดข้อผิดพลาด

ประเภทของ Resource Hooks

Argo CD มี 5 ประเภท Hooks หลัก ซึ่งแต่ละประเภทจะทำงานในช่วงเวลาต่างกัน:

1. PreSync Hook

ทำงานก่อนการ Apply Resources ทั้งหมด เหมาะสำหรับการเตรียมความพร้อม เช่น Backup ฐานข้อมูล หรือรัน Database Migration

2. Sync Hook

ทำงานพร้อมกับการ Apply Resources หลัก เหมาะสำหรับ Tasks ที่ต้องรันควบคู่กับการ Deploy

3. PostSync Hook

ทำงานหลังจาก Sync สำเร็จทั้งหมด เหมาะสำหรับ Health Checks, Smoke Tests และการส่ง Notifications

4. SyncFail Hook

ทำงานเมื่อการ Sync ล้มเหลว เหมาะสำหรับ Rollback หรือการแจ้งเตือนเมื่อเกิดข้อผิดพลาด

5. Skip Hook

ข้ามการ Apply Resource นั้นๆ แต่ยังคง Track อยู่ใน Argo CD มีประโยชน์สำหรับ Resources ที่จัดการโดยระบบอื่น

วิธีกำหนด Resource Hook ด้วย Annotations

Resource Hooks ถูกกำหนดโดยใช้ Annotations บน Kubernetes Resources:

apiVersion: batch/v1
kind: Job
metadata:
  name: my-hook-job
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: hook
        image: myimage:latest
        command: ["/bin/sh", "-c", "echo Running hook..."]
      restartPolicy: Never
  backoffLimit: 3

Annotations หลักที่ต้องรู้จัก:

  • argocd.argoproj.io/hook: ระบุประเภท Hook (PreSync, Sync, PostSync, SyncFail, Skip)
  • argocd.argoproj.io/hook-delete-policy: กำหนดว่าจะลบ Hook Resource เมื่อไหร่
  • argocd.argoproj.io/sync-wave: กำหนดลำดับการรันภายใน Phase เดียวกัน

ตัวอย่าง: PreSync Hook สำหรับ Database Migration

การโยกย้ายฐานข้อมูลเป็นหนึ่งในกรณีการใช้งาน PreSync Hooks ที่พบบ่อยที่สุด เนื่องจากเราต้องเตรียมฐานข้อมูลก่อนที่ Application ใหม่จะเริ่มทำงาน

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration-presync
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      serviceAccountName: db-migration-sa
      containers:
      - name: migrate
        image: postgres:15-alpine
        env:
        - name: PGHOST
          value: postgres.default.svc.cluster.local
        - name: PGDATABASE
          value: myapp
        - name: PGUSER
          valueFrom:
            secretKeyRef:
              name: postgres-creds
              key: username
        - name: PGPASSWORD
          valueFrom:
            secretKeyRef:
              name: postgres-creds
              key: password
        command:
        - /bin/bash
        - -c
        - |
          echo "Backing up database..."
          pg_dump -Fc -f /tmp/backup-$(date +%s).dump

          echo "Running migrations..."
          for script in /migrations/*.sql; do
            echo "Running $script..."
            psql -f "$script"
          done

          echo "Migrations completed successfully"
      restartPolicy: Never
  backoffLimit: 1

ตัวอย่าง: PostSync Hook สำหรับ Health Check และ Notification

PostSync Hooks ใช้สำหรับการตรวจสอบความสมบูรณ์ของระบบหลังจากการ Deploy เสร็จสิ้น:

apiVersion: batch/v1
kind: Job
metadata:
  name: app-health-check
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: health-check
        image: curlimages/curl:latest
        env:
        - name: APP_URL
          value: "http://myapp.default.svc.cluster.local:8080"
        command:
        - /bin/sh
        - -c
        - |
          echo "Waiting for application to be ready..."
          for i in $(seq 1 30); do
            if curl -f -s $APP_URL/health > /dev/null 2>&1; then
              echo "Application is healthy!"
              curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK \
                -H 'Content-Type: application/json' \
                -d '{"text": "Deploy successful! Application is healthy."}'
              exit 0
            fi
            echo "Attempt $i/30: Waiting..."
            sleep 2
          done
          echo "Application did not become healthy"
          exit 1
      restartPolicy: Never
  backoffLimit: 1

ตัวอย่าง: SyncFail Hook สำหรับ Rollback

SyncFail Hooks ช่วยให้คุณสามารถ rollback โดยอัตโนมัติเมื่อการ Deploy ล้มเหลว:

apiVersion: batch/v1
kind: Job
metadata:
  name: automatic-rollback
  annotations:
    argocd.argoproj.io/hook: SyncFail
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      serviceAccountName: deployment-admin
      containers:
      - name: rollback
        image: bitnami/kubectl:latest
        command:
        - /bin/bash
        - -c
        - |
          echo "Deployment failed! Rolling back..."
          kubectl rollout undo deployment/myapp -n default
          kubectl rollout status deployment/myapp -n default --timeout=5m
          echo "Rollback completed"
      restartPolicy: Never
  backoffLimit: 1

Hook Delete Policies

Hook Delete Policies ระบุว่าจะจัดการ Hook Resource อย่างไรหลังจากทำงานเสร็จ:

  • HookSucceeded: ลบ Hook เมื่อทำงานสำเร็จ เหมาะสำหรับ migration jobs ที่ไม่ต้องเก็บ
  • HookFailed: ลบ Hook เมื่อทำงานล้มเหลว
  • BeforeHookCreation: ลบ Hook เก่าก่อนสร้างตัวใหม่ในการ Sync ครั้งถัดไป
metadata:
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation

การใช้ Hook ร่วมกับ Sync Waves

Sync Waves และ Resource Hooks สามารถทำงานร่วมกันเพื่อสร้าง Deployment Pipeline ที่ซับซ้อนได้:

# Wave 0: Backup database (PreSync)
apiVersion: batch/v1
kind: Job
metadata:
  name: db-backup
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/sync-wave: "0"
---
# Wave 1: Run migrations (PreSync)
apiVersion: batch/v1
kind: Job
metadata:
  name: db-migrate
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/sync-wave: "1"
---
# Wave 2: Deploy application (Sync)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  annotations:
    argocd.argoproj.io/sync-wave: "2"

Best Practices สำหรับ Resource Hooks

1. ใช้ Service Accounts ที่เหมาะสม

สร้าง Service Accounts ที่มี RBAC Permissions เฉพาะเจาะจงสำหรับแต่ละ Hook เพื่อลดความเสี่ยงด้านความปลอดภัย

2. ตั้งค่า Timeout ที่เหมาะสม

ใช้ activeDeadlineSeconds เพื่อป้องกัน Hooks ที่ค้างนานเกินไป

spec:
  activeDeadlineSeconds: 600
  template:
    spec:
      containers:
      - name: task
        image: myimage:latest

3. เพิ่ม Logging และ Monitoring

บันทึกข้อมูลทุกขั้นตอนในแต่ละ Hook เพื่อง่ายต่อการ Debug เมื่อเกิดปัญหา

4. ทดสอบ Hooks ใน Staging

ทดสอบ Hooks ใน Development หรือ Staging environment ก่อนใช้งานใน Production เสมอ

5. มี Fallback Plan

เตรียม Manual Rollback Process หากระบบอัตโนมัติล้มเหลว

การใช้งาน Resource Hooks ร่วมกับ ผู้ให้บริการโฮสติ้ง Cloud VPS

เมื่อใช้ Argo CD บน ผู้ให้บริการโฮสติ้ง Cloud VPS คุณจะได้รับประโยชน์จากประสิทธิภาพและความเสถียรของโครงสร้างพื้นฐาน ซึ่งช่วยให้ Hooks ทำงานได้อย่างเชื่อถือได้ Cloud VPS ของ ผู้ให้บริการโฮสติ้ง มีการรักษาความปลอดภัย การ Backup อัตโนมัติ และการสนับสนุน 24/7 ซึ่งเป็นสิ่งสำคัญสำหรับการทำงานของ Hooks ที่สำคัญเช่น Database Migrations

สรุป

Resource Hooks ใน Argo CD เป็นเครื่องมือที่ทรงพลังสำหรับการจัดการวงจรชีวิตของการ Deploy ด้วยการใช้ PreSync, Sync, PostSync, SyncFail และ Skip Hooks อย่างถูกต้อง คุณสามารถสร้าง Deployment Pipeline ที่ปลอดภัยและเสถียรได้ โดยเฉพาะสำหรับงาน Database Migrations และ Critical Deployments บน Kubernetes ที่ทำงานบน ผู้ให้บริการโฮสติ้ง Cloud VPS