Argo Rolloutsを使う

Argo Rolloutsを使ってみます。
コンセプト

クラスタは、Minikubeでは動かなかったのでGKEを使っています。

Argo Rolloutsをインストール

クラスタにargo-rollouts controllerをインストールし、kubectlのargo-rolloutsプラグインをインストールします。
公式ドキュメント

まずクラスタにインストールします。
公式ドキュメント

Podが実行されていることを確認します。

1
kubectl get pod -n argo-rollouts 
1
2
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

続いてプラグインをインストールします。

1
2
3
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x ./kubectl-argo-rollouts-linux-amd64
sudo mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

インスールできたことを確認します。

1
kubectl argo rollouts version

UI Dashboardを実行

ダッシュボードがあると更新状況がわかりやすいです。
公式ドキュメント

1
kubectl argo rollouts dashboard

この状態でブラウザでhttp://localhost:3100にアクセスしておきます。

Getting Started

まずはGetting Startedをすすめてみるもがいいでしょう。

Getting Started - Nginx Ingress

続いてNginx Ingressと連携してみます。
ドキュメント

1
2
3
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/nginx/rollout.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/nginx/services.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/nginx/ingress.yaml

サービスを確認

サービスを確認します。

1
kubectl get svc 

結果例:

1
2
3
4
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
argo-rollouts-metrics ClusterIP 10.196.10.213 <none> 8090/TCP 4d20h
rollouts-demo-canary ClusterIP 10.196.13.24 <none> 80/TCP 47h
rollouts-demo-stable ClusterIP 10.196.10.84 <none> 80/TCP 47h

rollouts-demo-canaryrollouts-demo-stableの2つが実行されています。それぞれに対してリクエストを送ってみましょう。

まずはrollouts-demo-stableです。

1
kubectl run --rm -it curl --image=curlimages/curl --restart=Never rollouts-demo-stable/color

結果:

1
"blue"pod "curl" deleted

blueが返ってきました。
続いてrollouts-demo-canaryです。

1
kubectl run --rm -it curl --image=curlimages/curl --restart=Never rollouts-demo-canary/color

結果:

1
"blue"pod "curl" deleted

blueが返ってきました。

Ingressを確認

Ingressを確認します。

1
kubectl get ing

結果例:

1
2
3
NAME                                        CLASS    HOSTS                 ADDRESS        PORTS   AGE
rollouts-demo-rollouts-demo-stable-canary <none> rollouts-demo.local 10.196.6.209 80 47h
rollouts-demo-stable <none> rollouts-demo.local 10.196.6.209 80 47h

リクエストを送るなら以下のコマンドです。

1
kubectl run --rm -it curl --image=curlimages/curl --restart=Never -- -H "Host: rollouts-demo.local" 10.196.6.209/color

結果:

1
"blue"pod "curl" deleted

rollouts-demo-rollouts-demo-stable-canaryはcanary ingressです。これはRolloutリソースのstableIngressのクローンです。このIngrssは、カナリヤデプロイメントのトラフィック制御をするために使われます。また、このIngressの名前は<ROLLOUT-NAME>-<INGRESS-NAME>-canaryのルールによって自動的に定義されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/nginx/rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
replicas: 1
strategy:
canary:
canaryService: rollouts-demo-canary
stableService: rollouts-demo-stable
trafficRouting:
nginx:
stableIngress: rollouts-demo-stable
steps:
- setWeight: 5
- pause: {}
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollouts-demo
template:
metadata:
labels:
app: rollouts-demo
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m

更新する

新しいターミナルを開きRolloutを確認します。

1
kubectl argo rollouts get rollout rollouts-demo --watch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Name:            rollouts-demo
Namespace: argo-rollouts
Status: ✔ Healthy
Strategy: Canary
Step: 2/2
SetWeight: 100
ActualWeight: 100
Images: argoproj/rollouts-demo:blue (stable)
Replicas:
Desired: 1
Current: 1
Updated: 1
Ready: 1
Available: 1

NAME KIND STATUS AGE INFO
⟳ rollouts-demo Rollout ✔ Healthy 87s
└──# revision:1
└──⧉ rollouts-demo-6668595956 ReplicaSet ✔ Healthy 85s stable
└──□ rollouts-demo-6668595956-hxxdv Pod ✔ Running 85s ready:1/1

イメージをblueからyellowに更新します。このとき、–watchを実行しているもう1つのターミナルに注目しておきます。

1
kubectl argo rollouts set image rollouts-demo rollouts-demo=argoproj/rollouts-demo:yellow

結果例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Name:            rollouts-demo
Namespace: argo-rollouts
Status: ॥ Paused
Message: CanaryPauseStep
Strategy: Canary
Step: 1/2
SetWeight: 5
ActualWeight: 5
Images: argoproj/rollouts-demo:blue (stable)
argoproj/rollouts-demo:yellow (canary)
Replicas:
Desired: 1
Current: 2
Updated: 1
Ready: 2
Available: 2

NAME KIND STATUS AGE INFO
⟳ rollouts-demo Rollout ॥ Paused 9m57s
├──# revision:2
│ └──⧉ rollouts-demo-75f756d67b ReplicaSet ✔ Healthy 16s canary
│ └──□ rollouts-demo-75f756d67b-lr4vk Pod ✔ Running 16s ready:1/1
└──# revision:1
└──⧉ rollouts-demo-6668595956 ReplicaSet ✔ Healthy 9m55s stable
└──□ rollouts-demo-6668595956-hxxdv Pod ✔ Running 9m55s ready:1/1

Step 1/2とあるように、更新の途中です。この状態はRolloutリソースのcanary.stepsで指定したとおり、5%のリクエストをcanaryに流すようになっています。

これはingress-nginxの機能を使って実現しているようです。Argo Rolloutsはingress-nginxの機能を使うために以下のアノテーションをIngressに追加しているようです。

  • nginx.ingress.kubernetes.io/canary: “true”
  • nginx.ingress.kubernetes.io/canary-weight: “5”

ingress-nginxの公式ドキュメンt

この状態で問題ないことが確認できたら全てのリクエストをyellowに向けます。

1
kubectl argo rollouts promote rollouts-demo 

この状態だとstep1で停止状態なのでステップを進めます。

1
kubectl argo rollouts promote rollouts-demoa

このコマンドを実行後30秒経過すると古いバージョンのpodが終了し新しいバージョンのpodだけになります。

カナリヤサービスにリクエストが流れているときのPodの状態

1
kubectl get svc -o yaml

stable:

1
2
3
4
5
  name: rollouts-demo-stable
spec:
selector:
app: rollouts-demo
rollouts-pod-template-hash: "6668595956"

canary:

1
2
3
4
5
  name: rollouts-demo-canary
spec:
selector:
app: rollouts-demo
rollouts-pod-template-hash: 75f756d67b

それぞれ、特定のPodに対してリクエストを流していることがわかります。一応Podを確認します。

1
kubectl get pod
1
2
3
4
NAME                             READY   STATUS    RESTARTS   AGE
argo-rollouts-6bc46bcfd-4gjfq 1/1 Running 0 34m
rollouts-demo-6668595956-nhfrw 1/1 Running 0 5m17s
rollouts-demo-75f756d67b-tqfgp 1/1 Running 0 3m30s

この状態でサービスを指定してリクエストを送ると、当然ですがstableはblueを、canaryはyellowを返します。

1
kubectl run --rm -it curl --image=curlimages/curl --restart=Never rollouts-demo-canary/color
1
"yellow"pod "curl" deleted
1
kubectl run --rm -it curl --image=curlimages/curl --restart=Never rollouts-demo-stable/color
1
"blue"pod "curl" deleted

では続いてカナリヤをリリースし、その後の状態について確認します。

1
kubectl argo rollouts promote rollouts-demo
1
kubectl get svc -o yaml

stable:

1
2
3
4
5
  name: rollouts-demo-stable
spec:
selector:
app: rollouts-demo
rollouts-pod-template-hash: 75f756d67b

canary:

1
2
3
4
5
  name: rollouts-demo-canary
spec:
selector:
app: rollouts-demo
rollouts-pod-template-hash: 75f756d67b

どちらもyellowを向いています。