Istio 1.6.0でIstio自身のCanary upgradeをお試し

お昼の続き。土曜日を満喫してる。お昼はIn place upgradeをしたけど、今回はCanary upgradeに挑戦。

bufferings.hatenablog.com

## 準備

とりあえずIstio 1.5.4を入れたGKEを準備した。

❯ bin/istioctl version                                                     
client version: 1.5.4
control plane version: 1.5.4
data plane version: 1.5.4 (7 proxies)

## インストールを実行

ここを読みながら:

https://istio.io/docs/setup/upgrade/

んー。ドキュメントにはこう書いてあるんだけど:

$ istioctl install --set revision=canary

なんとなく、設定ファイルを指定した方が良いのでは?と思った。指定しないとdefaultプロファイルが使われる気がする。なので、コマンドのリファレンスをチェックしてみたら:

https://istio.io/docs/reference/commands/istioctl/#istioctl-install

-f オプションがあるから大丈夫そうかな。こうやってみるかな?

❯ bin/istioctl install --set revision=canary -f config.yaml
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete

podをwatchしといたらこうなった

❯ kubectl -n istio-system get pods -w
NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-7f76b9fc9f-ffr4j   1/1     Running   0          4m29s
istiod-6558b7b7f4-9d2dk                 1/1     Running   0          4m50s

# ここでinstallを実行した

istiod-canary-848948494f-vrpz8          0/1     Pending   0          0s
istiod-canary-848948494f-vrpz8          0/1     Pending   0          0s
istiod-canary-848948494f-vrpz8          0/1     ContainerCreating   0          0s
istiod-canary-848948494f-vrpz8          0/1     Running             0          9s
istiod-canary-848948494f-vrpz8          1/1     Running             0          10s
istio-ingressgateway-ccbb848f5-b94mh    0/1     Pending             0          0s
istio-ingressgateway-ccbb848f5-b94mh    0/1     Pending             0          0s
istio-ingressgateway-ccbb848f5-b94mh    0/1     ContainerCreating   0          1s
istio-ingressgateway-ccbb848f5-b94mh    0/1     Running             0          8s
istio-ingressgateway-ccbb848f5-b94mh    1/1     Running             0          10s
istio-ingressgateway-7f76b9fc9f-ffr4j   1/1     Terminating         0          5m37s
istio-ingressgateway-7f76b9fc9f-ffr4j   0/1     Terminating         0          5m43s
istio-ingressgateway-7f76b9fc9f-ffr4j   0/1     Terminating         0          5m44s
istio-ingressgateway-7f76b9fc9f-ffr4j   0/1     Terminating         0          5m44s

終わったあとはこうなった:

❯ kubectl get pods -n istio-system
NAME                                   READY   STATUS    RESTARTS   AGE
istio-ingressgateway-ccbb848f5-b94mh   1/1     Running   0          7m16s
istiod-6558b7b7f4-9d2dk                1/1     Running   0          13m
istiod-canary-848948494f-vrpz8         1/1     Running   0          7m29s

## つまり

  • istiod-canary が追加でデプロイされてる。元の istiod はそのまま。
  • istio-ingressgateway は、元のやつが停止されて、新しくデプロイされてる。

ふむ。そうなのか。istio-ingressgateway の中を見てみても1.6.0になってるな。

❯ kubectl -n istio-system get pods istio-ingressgateway-ccbb848f5-b94mh -o yaml | grep image: 
    image: docker.io/istio/proxyv2:1.6.0
    image: istio/proxyv2:1.6.0

バージョンはこんな感じ:

❯ bin/istioctl version
client version: 1.6.0
pilot version: 1.5.4
istiod version: 1.6.0
data plane version: 1.5.4 (6 proxies), 1.6.0 (1 proxies)

ん?install前はこうだったから:

❯ bin/istioctl version                                     
client version: 1.5.4
control plane version: 1.5.4
data plane version: 1.5.4 (7 proxies)

control plane version のところが pilot versionistiod version に分かれた。へー。

ingress-gateway が更新されるのはそういうものみたいね:

https://github.com/istio/istio/issues/23923#issuecomment-630892188

## この時点では

Data Planeは1.5.4のまま。リスタートをしても、1.5.4のままのはず。やってみよう。

❯ kubectl rollout restart deployment
deployment.apps/details-v1 restarted
deployment.apps/productpage-v1 restarted
deployment.apps/ratings-v1 restarted
deployment.apps/reviews-v1 restarted
deployment.apps/reviews-v2 restarted
deployment.apps/reviews-v3 restarted
     
❯ bin/istioctl version   
client version: 1.6.0
pilot version: 1.5.4
istiod version: 1.6.0
data plane version: 1.5.4 (6 proxies), 1.6.0 (1 proxies)

1.5.4のままだね。よかった。

## Data Planeの更新

今試したみたいに、新たに istiod-canary を入れただけだと、まだ各Podには旧バージョンのproxyがinjectされる。新しいバージョンを使うためにはnamespaceの設定を変更する必要がある。

❯ kubectl label namespace default istio-injection- istio.io/rev=canary
namespace/default labeled

❯ kubectl get namespaces default --show-labels
NAME      STATUS   AGE   LABELS
default   Active   48m   istio.io/rev=canary

僕がbookinfoをインストールしたdefault namespace から istio-injection ラベルを消して istio.io/rev=canary のラベルを新たに設定した。istio-injection のラベルを消す理由は、そっちの方がistio.io/rev のラベルより優先度が高くなってるかららしい。後方互換性のために。

これでリスタートをすると新しいバージョンを見に行くはず!

❯ kubectl rollout restart deployment
deployment.apps/details-v1 restarted
deployment.apps/productpage-v1 restarted
deployment.apps/ratings-v1 restarted
deployment.apps/reviews-v1 restarted
deployment.apps/reviews-v2 restarted
deployment.apps/reviews-v3 restarted

ポッドが再起動するのを待ってバージョンを確認すると:

❯ bin/istioctl version
client version: 1.6.0
pilot version: 1.5.4
istiod version: 1.6.0
data plane version: 1.6.0 (7 proxies)

Data Planeのところ更新されてた。わーい。一個だけ向き先を見てみると:

❯ bin/istioctl proxy-config endpoints details-v1-7bc48f795d-2fwzr --cluster xds-grpc -ojson | grep hostname
                "hostname": "istiod-canary.istio-system.svc",

canaryバージョンを見てた。

### ふと疑問

Canary upgradeについてはここまでなんだけど、ちょっと疑問に思ったことがある。新しいバージョンをデプロイするときにsetオプションでrevisionを指定したけど、それって設定ファイル(今回だとconfig.yaml)に書けないのかな?書ける方が嬉しいよなと思った。ので試してみた。

結論から言うと、こんな風に書いたらOKだった。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: default

  revision: "v160"

  addonComponents:
    prometheus:
      enabled: false

  values:
# 省略

最初は v1.6.0 って書いたんだけどそれだとエラーになった。ピリオドがダメなんだろうな:

❯ bin/istioctl install -f config.yaml
Error: failed to apply manifests: errors occurred during operation

## 気になるところ

### (1) 旧バージョンをどうやって削除する?

istiodとかsidecar-injectorとかが残ってるけど、これ普通に削除したらいいんかな?他にも残ってるリソースありそう?

❯ kubectl get pods -n istio-system
NAME                                   READY   STATUS    RESTARTS   AGE
istio-ingressgateway-ccbb848f5-b94mh   1/1     Running   0          62m
istiod-6558b7b7f4-9d2dk                1/1     Running   0          68m
istiod-canary-848948494f-vrpz8         1/1     Running   0          62m

❯ kubectl get mutatingwebhookconfigurations
NAME                                                 CREATED AT
istio-sidecar-injector                               2020-05-23T13:57:59Z
istio-sidecar-injector-canary                        2020-05-23T14:03:42Z
pod-ready.config.common-webhooks.networking.gke.io   2020-05-23T13:49:48Z

実際に手でistiodのdeploymentを削除してから、もう一度違うバージョンを入れてみようとしたらエラーがでて、見た感じvalidationのhookがistiodを参照してるみたい?元Galleyが持ってた機能かな?

❯ bin/istioctl install -f config.yaml                               
✔ Istio core installed                                                                                                                                                           
2020-05-23T15:31:02.866368Z     error   installer       failed to create "EnvoyFilter/istio-system/metadata-exchange-1.6-v160-2": Internal error occurred: failed calling webhook "validation.istio.io": Post https://istiod.istio-system.svc:443/validate?timeout=30s: no endpoints available for service "istiod"
2020-05-23T15:31:03.008138Z     error   installer       failed to create "EnvoyFilter/istio-system/stackdriver-filter-1.6-v160-2": Internal error occurred: failed calling webhook "validation.istio.io": Post https://istiod.istio-system.svc:443/validate?timeout=30s: no endpoints available for service "istiod"
2020-05-23T15:31:03.164115Z     error   installer       failed to create "EnvoyFilter/istio-system/tcp-metadata-exchange-1.6-v160-2": Internal error occurred: failed calling webhook "validation.istio.io": Post https://istiod.istio-system.svc:443/validate?timeout=30s: no endpoints available for service "istiod"
✘ Istiod encountered an error: failed to create "EnvoyFilter/istio-system/metadata-exchange-1.6-v160-2": Internal error occurred: failed calling webhook "validation.istio.io": Post https://istiod.istio-system.svc:443/validate?timeout=30s: no endpoints available for service "istiod"
failed to create "EnvoyFilter/istio-system/stackdriver-filter-1.6-v160-2": Internal error occurred: failed calling webhook "validation.istio.io": Post https://istiod.istio-system.svc:443/validate?timeout=30s: no endpoints available for service "istiod"
failed to create "EnvoyFilter/istio-system/tcp-metadata-exchange-1.6-v160-2": Internal error occurred: failed calling webhook "validation.istio.io": Post https://istiod.istio-system.svc:443/validate?timeout=30s: no endpoints available for service "istiod"

### (2) canaryって名前を使い続ける?

revisionにcanaryって名前をつけたけど、このやり方だと、このまま使い続けることになりそう。使い続けること前提のrevision名の方が良さそう?v160とか?

### (3) pod単位での更新はできなさそう?

このやり方だとnamaspace単位での設定変更になる。pod単位ではできなさそうだな。pod単位でできた方が良いような気もするけど、namespace単位で十分といえばそういう気もしてきた。

## まとめ

  • 複数バージョンの istiod をインストールして、順次そちらを利用するように切り替えていくのは便利そうではある。
  • IngressGatewayが更新されてしまうのでそこに注意する。
  • クリーンアップ系が整ってくるのを1.7あたりに期待しておいたら良さそう。

このIssueはSubscribeしておこうかな

github.com

面白かった!