この記事は Gunosy Advent Calendar 2020 10日目の記事です。 昨日はjohnmanjiroさんの TerraformでLaunch Templateを使ったManaged Node Groupを導入する でした。
こんにちは、広告技術部のhidappleです。普段は広告配信サーバや管理画面の開発をしています。 この記事では、以前EKSでのアプリケーションのデプロイにArgo Rolloutsを導入したので、それについて紹介したいと思います。
Argo Rolloutsとは
Argo RolloutsはArgo Projectsの1プロダクトであり、KubernetesにBlue-GreenやCanary等のより高度なデプロイ機能を提供してくれるものです。類似のツールとしてはflagger等が候補に上がると思いますが、今回はサービスメッシュなどのツールを必要とせず単独で入れられ、後述しますがKubernetesのDeploymentをArgo Rolloutsの定義するRolloutリソースに置き換えることで比較的容易に導入が可能といった理由から、Argo Rolloutsを採用しました。
今回はCanaryデプロイのためにArgo Rolloutsを導入し、デプロイ時にまず一部のPodのみ新しいアプリケーションに入れ替え、問題がなければ全体にデプロイを適用するといったフローを実現しました。
Argo Rolloutsの導入
Argo Rolloutsをクラスタにインストールするには、namespaceを作って、公開されているmanifestをapplyしてやります。
kubectl create namespace argo-rollouts kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml
Helmでも提供されており、広告技術部ではEKSのクラスタをTerraformで管理しているので、今回は terraform-helm-provider
を使ってHelm Chartをデプロイする方法をとりました。Terraformに以下のようなresourceを追加してやればいいです。
resource "helm_release" "argo_rollouts" { name = "argo-rollouts" chart = "https://argoproj.github.io/argo-helm/argo-rollouts-0.3.7.tgz" namespace = "argo-rollouts" # values等は必要に応じて適宜追加 }
またArgo Rolloutsを操作するためにkubectl argo pluginが必要なのでInstall Guideに従って事前に入れておくといいでしょう。
Rolloutsリソースの定義
次にRolloutリソースを定義していきます。基本的にほとんど通常のDeploymentと同じ構成ですがRolloutではspec.strategy
にcanary
またはblueGreen
を指定することができるので、ここにデプロイのステップを記述していくことになります。
簡略化したものですが以下にRolloutのyamlの例を示します。
apiVersion: argoproj.io/v1alpha1 kind: Rollout spec: strategy: canary: maxSurge: 1 maxUnavailable: 1 steps: - setWeight: 1 - pause: {} template: # template以下は通常のtemplateを定義する
このようにsetWeight
でCanaryに流すトラフィックを指定*1し、pause
で条件を満たすまで停止させるといった流れを記述していきます。pause
ではduration
を指定して一定期間待機するといったことができますが、今回のように指定しない場合は先に紹介したpluginのコマンドである kubectl argo rollouts promote
*2 を受け付けるまで停止します。もちろんsetWeight
、pause
を複数書けるので例えばsetWeight
を指定した後promote
コマンドを受け付けるまで待機し、その後はduration
指定により徐々にデプロイを拡大していくといったより細かい設定もできます。その場合は例えば以下のようになるでしょう。
apiVersion: argoproj.io/v1alpha1 kind: Rollout spec: strategy: canary: maxSurge: 1 maxUnavailable: 1 steps: - setWeight: 1 - pause: {} # promoteを待機 - setWeight: 10 - pause: { duration: 1m } # 1分待機 - setWeight: 50 - pause: { duration: 10s } # 10秒待機 template: # template以下は通常のtemplateを定義する
その他の詳細な設定やBlue-Greenでの書き方を知りたい方は以下のリンクを参考にしてみてください。
デプロイの流れ
さてArgo RolloutsのインストールとRolloutリソースの定義ができたので実際にデプロイをするための仕組みを作っていきます。方法としては同じArgo ProjectsのArgo CDに組み込む等が考えられますが、今回はこちらの記事と同様にCircleCIからskaffold
を使ってデプロイフローを構築することにしました。
先の記事でも紹介しているように弊社ではskaffold
のCI-imageを公開しており、CircleCIの記述も通常のDeploymentを使っていたときとほとんど同様です。一点、現状skaffold
ではbuildしたimageのタグをRolloutのようなカスタムリソースに対してうまく当てられない*3という問題がありましたが、今回はYAMLのパッケージングにkustomize
を使っていたので、kustomize edit set image
を使って事前にYAMLに埋め込むことで解消しました。
docker: - image: gunosy/ci-skaffold:1.0.1 steps: - checkout - setup_remote_docker - run: name: docker login command: $(aws ecr get-login --no-include-email) - run: aws eks update-kubeconfig --name << parameters.env_short >>-cluster - run: name: set docker image tag command: | cd k8s/overlays/<< parameters.env_long >> && \ kustomize edit set image front-api=front-api:new-tag \ # Tag名は実際は動的に生成しています - run: skaffold run --profile << parameters.env_long >> --label skaffold.dev/run-id="static",skaffold.dev/docker-api-version="static",app.kubernetes.io/managed-by="skaffold",skaffold.dev/tag-policy="static"
さてここまでの手順で概ねArgo Rolloutsを使ったCanaryデプロイが実現できるようになりました。上記のフローを実行するとArgo RolloutsによるCanaryデプロイがおこなわれるので、問題なくデプロイを拡大できると判断した場合は先述したpromote
コマンドを送ってやります。(実際はCircleCIからpromote
もおこなっています。)
Rolloutの状態はkubectl argo rollouts get
コマンドで可視化できるので異変があった場合等にはすぐに状態を確認できます。
> kubectl argo rollouts get rollout front-api --watch Name: front-api Namespace: default Status: ॥ Paused Strategy: Canary Step: 1/2 SetWeight: 1 ActualWeight: 50 Images: front-api:new-tag (canary) front-api:old-tag (stable) Replicas: Desired: 2 Current: 2 Updated: 1 Ready: 2 Available: 2 NAME KIND STATUS AGE INFO ⟳ front-api Rollout ॥ Paused 17m ├──# revision:2 │ └──⧉ front-api-68f7d86788 ReplicaSet ✔ Healthy 8m15s canary │ └──□ front-api-68f7d86788-g742f Pod ✔ Running 8m15s ready:1/1 └──# revision:1 └──⧉ front-api-57bd7bbbdb ReplicaSet ✔ Healthy 17m stable └──□ front-api-57bd7bbbdb-v4bwb Pod ✔ Running 17m ready:1/1
まとめ
ここまでArgo Rolloutsを使ったCanaryデプロイについて紹介しました。普段書いているDeploymentの定義を少し変更してやるだけで比較的容易に導入することができたという印象なので、Kubernetes上でBlue-GreenやCanaryデプロイをしたい場合には1つの候補として検討してみてはいかがでしょうか。また今回は最低限の機能しか使っていないのですがAnalysisやExperimentsの機能を使ってさらに高度なデプロイフローを実現することもできるのでこちらもそのうち試してみたいと思います。
明日は山本さんが記事を書いてくれます。お楽しみに!
*1:Taraffic Managementによる、よりきめ細やかな制御も可能です
*2:またはkubectl argo rollouts abortでabortも可能です