使用 Argo CD 的 Resource Hooks 來匯入資料庫資料

程式技術
使用 Argo CD 的 Resource Hooks 來匯入資料庫資料

在傻傻的人工備份資料一陣子之後,我才發現可以使用 K8s 的 CronJob 來定期備份資料庫的資料。使用 CronJob 備份的效果讓我相當的滿意,終於擺脫了人工作業!但這次我有了另外一個問題。如何在 K8s 一建立好資料庫資源後,立刻匯入我之前備份的資料呢?

找了一下資料,發現 K8s 並沒有提供像是 Docker Compose 的 depends_on 功能,因為 K8s 是宣告式的,只要寫好我們要的目標資源狀態,K8s 會自動幫我們處理每個資源的建立順序。

雖然 K8s 沒有 depends_on 功能,但好加在 Argo CD 有提供一種叫做 Resource Hooks 的功能,讓你可以在資源建立的不同階段觸發設定好的任務。

使用 Resource Hooks 在不同的階段觸發任務

Argo CD 提供多種 hooks,讓你可以在資源建立的各個階段觸發指定的操作:

  • PreSync: 在資源建立之前執行。
  • Sync:在所有 PreSync 操作與所有資源建立之後執行。
  • Skip:請 Argo CD 忽略這個資源
  • PostSync:在所有 Sync 操作與所有資源建立之後執行
  • SyncFail:當 sync 相關操作失敗時執行

Hooks 常常使用在 K8s 的 Job 資源,例如在部署應用程式前,用 PreSync 操作 Job 先執行資料庫 Schema 的建立。

Helm 也有提供 Hooks 的功能,Argo CD 的 PreSync 正好對應 Helm 的 pre-install

使用 Deletion Policies 刪除 Hooks 建立的資源

為了避免 hooks 建立的資源在完成任務後持續佔用系統資源,Argo CD 提供三種 Deletion Policies 來刪除 hook 資源:

  • BeforeHookCreation:在其他 hook 資源建立之前刪除。
  • HookSucceeded:在 hook 資源執行成功之後刪除。
  • HookFailed:在 hook 資源執行失敗之後刪除。

使用 Hooks 來匯入資料

我想在 MySQL 的 Pod 建立後,立刻執行一個 Job,從 S3 上面下載資料備份,然後將資料匯入 MySQL 中。

apiVersion: batch/v1
kind: Job
metadata:
  name: mysql-migration-job
  namespace: docfunc
  annotations:
    # 在所有資源建立後執行
    argocd.argoproj.io/hook: PostSync
    # 成功之後,將該資源刪除
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: mysql-backup-cronjob
          # 這裡我預先包好一個安裝好 mysql-client 與 aws-cli 的容器
          image: nella0128/aws-mysql-client:0.1.0
          imagePullPolicy: "Always"
          command:
            - "/bin/bash"
            - "-c"
            - |
              # 暫停 30 秒,等待 MySQL 準備好
              sleep 30s
              # 取得 S3 上面最新的資料備份
              OBJECT_KEY=$(aws s3 ls s3://$S3_BUCKET_NAME --recursive | sort | tail -n 1 | awk '{print $4}')
              aws s3 cp s3://$S3_BUCKET_NAME/$OBJECT_KEY /tmp/migration.sql
              # 將資料匯入 MySQL
              cat /tmp/migration.sql | mysql -h $DATABASE_HOST -P $DATABASE_PORT -u $DATABASE_USER --password=$DATABASE_PASSWORD $DATABASE_NAME
          env:
            # ... 設定各種環境變數,例如資料庫連線與 AWS Token 等相關資訊
      restartPolicy: Never

重新部署資源到 K8s 之後,就會發現有一個 Job 會在資源都部署好之後才執行,並且在執行後立刻被刪除,此時資料庫中也會有之前備份的資料囉。

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

1 則留言
sharkHead sharkHead

結果 Argo CD 的 Resource Hooks 用了沒多久就換成 Helm 的 Hooks 了 😂。

apiVersion: batch/v1
kind: Job
metadata:
  name: mysql-migration-job
  namespace: docfunc
  annotations:
    "helm.sh/hook": post-install
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  # ...