Istio が壊れました。と言わないために

## はじめに

現在サイバーエージェントのメディア事業部でサーバサイドエンジニアをやっているukiy6969です。
メディア事業部の横軸組織PTAの[アドベントカレンダー](https://adventar.org/calendars/5741)の7日目の記事となります。
今回はIstioのカナリアアップグレードについて書きたいと思います。

## 背景

Istioを利用し始めると、想像以上にIstioの開発スピードが早く、自分たちが気づかないままにマイナーアップデートが進んでいるなんてこともありました。
また、導入当初は自分のIstioの知見が少なく、Istioの設定をいじっている内に修正不可能な状態となりKubernetesクラスタを再作成をお願いすることになるなど、チームに迷惑をかけてしまうことなどありました。
そういった状況を変える上で、Istioを入れ直したりすることができるようになれば、クラスタの再作成といった最悪の手段を回避できるようになるかと思います。
今回は[Canary Upgrades](https://istio.io/latest/docs/setup/upgrade/canary/)を参考にローカルkubernetesクラスタで実際にIstioのバージョンを1.6系から1.7系へカナリアアップグレードを行ってみたいと思います。


## 手順

大まかな手順は以下の通りです。

1: Istio 1.6系のコントロールプレーンとサンプルアプリケーションをインストールし、サービスメッシュを組む。

![istio-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104440/b0f9a3b6-2e22-86db-2c94-fa9d1dcc5abb.png)

2: Istio 1.7系のコントロールプレーンをインストール

![istio-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104440/7ec7ec7e-beeb-6e4b-364e-bf2b376ce0bb.png)

3: サンプルアプリケーションをIstio 1.7系のコントロールプレーンを向くように変更

![istio-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104440/7ceb91c2-36d6-8316-0008-2f0187477acd.png)


4: Istio 1.6系のコントロールプレーンを削除

![istio-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104440/ebb4a6db-e175-40da-28c8-498c6f9ca5e4.png)


## Istio 1.6系のコントロールプレーンとサンプルアプリケーションをインストールし、サービスメッシュを組む。

はじめに、Istio 1.6系のバージョンをダウンロードします。

```bash
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.14 sh -
```

次に、Istio v1.6をIstio Operatorを利用して、インストールします。
今回は、default プロファイルを利用します。

```yaml
# example-istio-oprator-1-6-14.yaml
# 今回インストールする istio v1.6.14 用の IstioOperator
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: example-istio-operator-1-6-14
spec:
  profile: default
  revision: 1-6-14
```

```
$ istio-1.6.14/bin/istioctl operator init
$ kubectl create ns istio-system
$ kubectl apply -f example-istio-oprator-1-6-14.yaml
```

また、動作確認のため公式から提供されている[Bookinfo サンプルアプリケーション](https://istio.io/latest/docs/examples/bookinfo/)を `bookinfo` という名前空間でインストールします。
`bookinfo` の名前空間のラベルに `istio.io/rev=1-6-14` をつけることで、 `bookinfo` では、 リビジョン `1-6-14` で指定されたIstioが有効となります。

```
$ kubectl create namespace bookinfo
$ kubectl label namespace bookinfo istio.io/rev=1-6-14
$ kubectl -n bookinfo apply -f istio-1.6.14/samples/bookinfo/platform/kube/bookinfo.yaml
$ kubectl -n bookinfo apply -f istio-1.6.14/samples/bookinfo/networking/bookinfo-gateway.yaml
```

動作確認のため、ingressgateway経由でアクセスしてみます。

```bash
$ kubectl -n istio-system get svc istio-ingressgateway
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.97.206.161   localhost     15021:32652/TCP,80:32480/TCP,443:32155/TCP,31400:30266/TCP,15443:30903/TCP   108s
```

筆者の環境では、Ingressgatewayはlocalhostで受けてくれているため、[localhost/productpage](http://localhost/productpage) にブラウザでアクセスしました。

![スクリーンショット 2020-12-06 182844.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104440/a25a19fd-0f43-c89c-c52a-c62d8539356b.png)

問題なく動作していることを確認しました。

## Istio 1.7系のコントロールプレーンをインストール

では、新しいIstioをインストールしたいと思います。
アップデートしたいIstio v1.7 をダウンロードしてきます。

```bash
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.7.5 sh -
```

ダウンロードした Istio v1.7を Istio Operator を利用して、インストールします。

```yaml
# example-istio-oprator-1-7-5.yaml
# 今回インストールする istio v1.7.5 用の IstioOperator
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: example-istio-operator-1-7-5
spec:
  profile: default
  revision: 1-7-5
```
```bash
$ istio-1.7.5/bin/istioctl operator init --revision 1-7-5
$ kubectl apply -f example-istio-oprator-1-7-5.yaml
```

2つのバージョンのコントロールプレーンが動作していることを確認します。


```bash
$ kubectl -n istio-system get pod --show-labels
NAME                                    READY   STATUS    RESTARTS   AGE     LABELS
...
istiod-1-6-14-74bbf7cdd6-z2vvr          1/1     Running   0          80m     app=istiod,istio.io/rev=1-6-14,istio=istiod,pod-template-hash=74bbf7cdd6
istiod-1-7-5-df7df7ccd-thdzs            1/1     Running   0          7m11s   app=istiod,istio.io/rev=1-7-5,istio=istiod,pod-template-hash=df7df7ccd
...
```

bookinfo の Pod は まだ リビジョン `1-6-14` を見ていることを確認。
また、ingressgateway は、カナリアアップグレードすることはできず、この時点でバージョンアップされます。

```bash
$ istio-1.7.5/bin/istioctl proxy-status
NAME                                                   CDS        LDS        EDS        RDS        ISTIOD                             VERSION
details-v1-79c697d759-4kpt4.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
istio-ingressgateway-79f846b5f8-2bhsq.istio-system     SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
productpage-v1-65576bb7bf-lt542.bookinfo               SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
prometheus-6c7c9554c6-z7xh4.istio-system               SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
ratings-v1-7d99676f7f-wdztb.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
reviews-v1-987d495c-hmfzx.bookinfo                     SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
reviews-v2-6c5bf657cf-v9sbf.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
reviews-v3-5f7b9f4f77-52p55.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-6-14-77b5df9c65-nrjv4     1.6.14
```

## サンプルアプリケーションをIstio 1.7系のコントロールプレーンを向くように変更

次にデータプレーンを リビジョン `1-7-5` のコントロールプレーンに向けたいと思います。
先程 `bookinfo` の名前空間のラベルに付けた `istio.io/rev=1-6-14` を `istio.io/rev=1-7-5` に上書きし、Podを再起動することで `bookinfo` は、 リビジョン `1-7-5` で指定されたコントロールプレーンが有効となります。

```bash
$ kubectl label namespaces bookinfo istio.io/rev=1-7-5 --overwrite
$ kubectl -n bookinfo rollout restart deployment
```

コントロールプレーンが変更しているか確認します。

```bash
$ istio-1.7.5/bin/istioctl proxy-status
NAME                                                   CDS        LDS        EDS        RDS        ISTIOD                             VERSION
details-v1-5f5df74fbb-8jsr2.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
istio-ingressgateway-79f846b5f8-2bhsq.istio-system     SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
productpage-v1-cc959d59d-m6rrl.bookinfo                SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
ratings-v1-696ff84874-ttnj9.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
reviews-v1-75cd569fd6-wfxrp.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
reviews-v2-5c9bc7bf8-gmqkl.bookinfo                    SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
reviews-v3-6ccbff6b98-hqqkr.bookinfo                   SYNCED     SYNCED     SYNCED     SYNCED     istiod-1-7-5-94b8f8754-lng7x       1.7.5
```

## Istio 1.6系のコントロールプレーンを削除

最後に リビジョン `1-6-14` のコントロールプレーンを削除します。

```
$ kubectl delete -f example-istio-oprator-1-6-14.yaml
```

`istiod-1-6-14-` のPodが削除されていることを確認。

```bash
$ kubectl -n istio-system get pod --show-labels
NAME                                    READY   STATUS    RESTARTS   AGE     LABELS
...
istiod-1-7-5-df7df7ccd-thdzs            1/1     Running   0          7m11s   app=istiod,istio.io/rev=1-7-5,istio=istiod,pod-template-hash=df7df7ccd
...
```

お疲れ様です。これでIstioのバージョンを 1.6系から 1.7系にあげることができました。

今回は、リビジョンにIstioのバージョンを用いていましたが、文字列であればなんでもよく、`revision=canary` などを用いて、同じIstioのバージョンでもコントロールプレーンを切り替えることができます。

## まとめ

実際にやってみて、改めて理解したこととして、

* データプレーンのアップデートには、Podの再起動が必要
* ingressgatewayは、カナリアアップグレードすることはできない

ということがわかりました。

## さいごに

今回は、ローカル環境でIstioのカナリアアップグレードを行ってみました。
実際にIstioと仲良くなるには、手を動かして慣れるしかないかと思います。
これからIstioを検討しようとしている方や運用どうなるんだろうと悩んでいる方の手助けになればと思いこの記事を書きました。
世の中のIstioが少しでも多くメンテされるよう祈っております。

明日は我らが[Pagu](https://twitter.com/pagu0602)の出番となります。楽しみにしてください。:dog:

では、よいクリスマスを！:christmas_tree: