Kubernetesでカナリアリリースを試す
Kubernetesではコンテナイメージを実行するのにDeploymentが使われます。
ただこのDeploymentではカナリアリリースを実現することはできません。
そこでArgo Rolloutsを使って、カナリアリリースを試します。
以下に試した内容を紹介します。
Argo Rolloutsのバージョンはv0.9.1時点の内容になります。
Argo Rolloutsとは
Kubernetesにおけるデプロイ戦略にブルーグリーンデプロイメントとカナリアリリースを追加します。
今回はこの2つのうち、カナリアリリースを試します。
カナリアリリースを試す
Argo Rolloutsをインストールする
kubectl create namespace argo-rollouts kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml
Argo RolloutsのKubectl Pluginをインストールする
brew install argoproj/tap/kubectl-argo-rollouts
検証用のイメージを準備する
カナリアリリースによって、指定した割合で新バージョンになっているか確認するためのイメージを用意します。
nginxを使って、表示する内容を変更したイメージを用意します。
Dockerfile
FROM nginx COPY app /usr/share/nginx/html
version:0.0.1
app/index.html
<html><body>1</body></html>
version:0.0.2
app/index.html
<html><body>2</body></html>
カナリアリリースを実施する
Argo Rolloutsをインストールすることで使用可能になったRolloutリソースでコンテナイメージを実行します。
strategy
でcanary
を指定することでカナリアリリースになります。
setWeight
で新バージョンをデプロイした時の割合を決めます。ここでは20%にしています。
nginx.yaml
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: sample spec: replicas: 5 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: nginx image: hi1280/nginx:0.0.1 ports: - containerPort: 80 strategy: canary: steps: - setWeight: 20 - pause: {}
version:0.0.1のnginxイメージをrolloutリソースでデプロイします。
kubectl apply -f nginx.yaml
最初のデプロイ時点での状態です。
kubectl pluginのgetコマンドで状態を可視化できます。
$ kubectl argo rollouts get rollout sample --watch Name: sample Namespace: default Status: ✔ Healthy Strategy: Canary Step: 2/2 SetWeight: 100 ActualWeight: 100 Images: hi1280/nginx:0.0.1 (stable) Replicas: Desired: 5 Current: 5 Updated: 5 Ready: 5 Available: 5 NAME KIND STATUS AGE INFO ⟳ sample Rollout ✔ Healthy 11s └──# revision:1 └──⧉ sample-747794b696 ReplicaSet ✔ Healthy 11s stable ├──□ sample-747794b696-rbczl Pod ✔ Running 11s ready:1/1 ├──□ sample-747794b696-sgtj7 Pod ✔ Running 11s ready:1/1 ├──□ sample-747794b696-xklcb Pod ✔ Running 11s ready:1/1 ├──□ sample-747794b696-xvf54 Pod ✔ Running 11s ready:1/1 └──□ sample-747794b696-zxrpn Pod ✔ Running 11s ready:1/1
version:0.0.2のnginxイメージをデプロイします。
set imageコマンドでイメージをデプロイできます。
kubectl argo rollouts set image sample nginx=hi1280/nginx:0.0.2
デプロイした後の状態です。20%の割合でデプロイされていることが分かります。
$ kubectl argo rollouts get rollout sample --watch Name: sample Namespace: default Status: ॥ Paused Strategy: Canary Step: 1/2 SetWeight: 20 ActualWeight: 20 Images: hi1280/nginx:0.0.1 (stable) hi1280/nginx:0.0.2 (canary) Replicas: Desired: 5 Current: 5 Updated: 1 Ready: 5 Available: 5 NAME KIND STATUS AGE INFO ⟳ sample Rollout ॥ Paused 9m6s ├──# revision:2 │ └──⧉ sample-5669f74b97 ReplicaSet ✔ Healthy 17s canary │ └──□ sample-5669f74b97-rzl8z Pod ✔ Running 17s ready:1/1 └──# revision:1 └──⧉ sample-747794b696 ReplicaSet ✔ Healthy 9m6s stable ├──□ sample-747794b696-rbczl Pod ✔ Running 9m6s ready:1/1 ├──□ sample-747794b696-xklcb Pod ✔ Running 9m6s ready:1/1 ├──□ sample-747794b696-xvf54 Pod ✔ Running 9m6s ready:1/1 └──□ sample-747794b696-zxrpn Pod ✔ Running 9m6s ready:1/1
promoteコマンドを実行することで、100%の割合でデプロイします。
kubectl argo rollouts promote sample
100%でデプロイした後の状態です。
$ kubectl argo rollouts get rollout rollouts-demo --watch Name: sample Namespace: default Status: ✔ Healthy Strategy: Canary Step: 2/2 SetWeight: 100 ActualWeight: 100 Images: hi1280/nginx:0.0.2 (stable) Replicas: Desired: 5 Current: 5 Updated: 5 Ready: 5 Available: 5 NAME KIND STATUS AGE INFO ⟳ sample Rollout ✔ Healthy 11m ├──# revision:2 │ └──⧉ sample-5669f74b97 ReplicaSet ✔ Healthy 2m47s stable │ ├──□ sample-5669f74b97-rzl8z Pod ✔ Running 2m47s ready:1/1 │ ├──□ sample-5669f74b97-wtvbq Pod ✔ Running 37s ready:1/1 │ ├──□ sample-5669f74b97-zvvjl Pod ✔ Running 37s ready:1/1 │ ├──□ sample-5669f74b97-8l8z9 Pod ✔ Running 35s ready:1/1 │ └──□ sample-5669f74b97-jjhkj Pod ✔ Running 35s ready:1/1 └──# revision:1 └──⧉ sample-747794b696 ReplicaSet • ScaledDown 11m
少ない割合で新バージョンをデプロイして、その後、新バージョンに変更することができました。
指定した時間だけ新バージョンをデプロイする
カナリアリリースの設定によって、指定した時間だけ新バージョンを試して、自動的に旧バージョンに戻すといったことが可能です。
steps
に記述します。
ここでは、30秒間は20%の割合で新バージョンを試して、その後は0%の割合にすることで旧バージョンに戻しています。
nginx.yaml
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: sample spec: replicas: 5 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: nginx image: hi1280/nginx:0.0.1 ports: - containerPort: 80 strategy: canary: steps: - setWeight: 20 - pause: duration: 30 - setWeight: 0 - pause: {}
duration
の単位は秒数になります。
Rolloutリソースでローリングアップデートを実施する
ローリングアップデートはDeploymentリソースでも実施できますが、リソースが異なるので取り回しが面倒です。
ローリングアップデートも同じリソースでできると便利です。
ローリングアップデートはcanary:{}
で実現できます。
nginx.yaml
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: sample spec: replicas: 5 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: nginx image: hi1280/nginx:0.0.1 ports: - containerPort: 80 strategy: canary: {}
まとめ
カナリアリリースは既に一般的なデプロイ戦略だと思いますが、Kubernetesではそれができないのが残念なところでした。
Argo Rolloutsを使うとKubernetesで簡単にカナリアリリースを実現することができます。