こんにちは。広告技術部の yamaYu です。 広告サービスのバックエンド〜インフラを中心に触っています。 最近は専らパルデアの大地を駆け回る日々です。
今回の記事ですが、Kubernetes 上で管理している Rails 製システムの DB マイグレーションの扱いについて書きました。 下の記事の続編になっているため、こちらも参考にしていただけると幸いです。
- Kubernetes 上でいいかんじに DB マイグレーションしたい
- Sync Phases, Waves, Resource Hooks
- Resource Hooks を用いた DB マイグレーション
- まとめ
Kubernetes 上でいいかんじに DB マイグレーションしたい
前回までの記事で、Rails 製の管理画面が現状抱える CI/CD の課題の整理と GitOps で解決できるかの検討を行い、 Kubernetes 上で GitOps パターンを実現するツールである Argo CD を実際に導入することでその課題の一部を解決しました。 この記事では前回までで未解決の課題であった DB マイグレーション の扱いにフォーカスします。
DB スキーマに変更があった場合、新しいバージョンの Pod をデプロイする前に DB マイグレーションを実行する必要があります。 CI/CD ツールには DB へのアクセス権限を持たせない場合、Kubernetes の Job 等で DB マイグレーションのプロセスを走らせることになると思いますが、 Kubernetes 上のリソース同士は基本的に非同期にしか連携できないため、DB マイグレーション → 新しいバージョンの Pod の起動という順序を保証する仕組みが必要になります。
- DB マイグレーションが完了してから新しいバージョンの Pod を起動する
というのが今回やりたいことです。
Sync Phases, Waves, Resource Hooks
結論としては Argo CD の機能でこれを実現することができました。
Argo CD には Sync Phase という概念があり、pre-sync
→ sync
→ post-sync
の三段階にデプロイのタイミングが分かれています*1。
Resource Hooks で Sync Phase を指定したアノテーションを各 Kubernetes リソースに付与することでデプロイ順序を設定できます。
もっと詳細な設定が必要な場合には Sync Wave を用いることで同一 Phase 内でのより細かい順序を整数値で定義することも可能です。
metadata: annotations: argocd.argoproj.io/hook: PreSync argocd.argoproj.io/sync-wave: "5"
Resource Hooks を用いた DB マイグレーション
今回は hook: PreSync
を設定することでデプロイ時に最初にDBマイグレーションJobが実行されるようにしました。
また Job が削除されるタイミングも指定でき、hook-delete-policy: BeforeHookCreation
とすることで次回 sync 実行時まで Job を残しています。
これにより、ログが追いやすくなります。
余談ではありますが、args
の部分ではマイグレーション結果を SlackのIncoming Webhook で通知もしています。
apiVersion: batch/v1 kind: Job metadata: name: rails-migration annotations: argocd.argoproj.io/hook: PreSync argocd.argoproj.io/hook-delete-policy: BeforeHookCreation ︙ spec: template: spec: containers: - name: rails-migration image: rails-image command: ["/bin/sh", "-c"] args: - | RESULT=$(bundle exec rails db:migrate); RESULT=${RESULT:-"No DB migration"}; TEXT="DB migration result\n*environment*: ${RAILS_ENV:-development}\n"'```\n'"${RESULT}\n"'```'; curl -X POST -H 'Content-type: application/json' \ --data '{"channel": "#deploy_channel", "username": "Rail DB Migration", "icon_emoji": ":rails:", "text": "'"${TEXT}"'" }' \ ${SLACK_WEB_HOOK_URL}; echo $TEXT ︙
まとめ
Rails のサービスを Kubernetes 上にデプロイする際に問題になる DB マイグレーションについて、Argo CD の Sync Phase と Resource Hooks を用いて同期的に実行する方法を扱いました。 本記事が読者様の一助になれば幸いです。
*1:マニフェストファイルと実リソースの同期の意味で sync という単語が使われてます