Envoy と Kubernetes で始める Progressive Delivery

本記事は 2020/01/08 に開催された [Envoy Meetup Tokyo #1](https://envoytokyo.connpass.com/event/157711/)の LT スライド兼補足資料です。

原則として、スライドモードでファーストビューに入るものはスライドとして、下にスクロールして表示される部分は補足資料です。

---

# Progressive Delivery とは

- Continuous Delivery ++
- 実装はたいてい Canary Release + Canary Analysis + Automated Rollback

> "Progressive Delivery is the next step after Continuos Delivery, where new versions are deployed to subset of users and are evaluated in terms of correctness and performance before rolling them to the totality of the users and rolled back if not matching some key metrics."
> Carlos Sanchez

---

# Progressive Delivery の実装

- Flagger
- Argo Rollouts
- Spinnaker (?)

Flagger は Weaveworks の Stefan さんが開発している、Kubernetes 上で様々な Ingress Gateway やサービスメッシュなどと連携して Progressive Delivery を行うための Kubernetes Operator。

Argo Rollouts は Intuit 手動の Argo プロジェクトのサブプロジェクトの一つで、 Argo CD などと組み合わせて Progressive Delivery を行うための Kubernetes Operator。

Spinnaker は知らないので詳しい方におまかせします(Kayenta で Canary Analysisができると聞いているので、可能なのでは?と思ってます、というレベルです)。

---

# Progressive Delivery の課題

- Kubernetes 上で実現したい場合、Istio、Linkerd、Contour、Ambassador などのそこそこリッチなサービスメッシュやイングレスゲートウェイとセットで導入することになる
- 素の Envoy を横に並べてフロントプロキシとして利用しているような事例がよくある
- Progressive Delivery を始めようとすると、突然サービスメッシュがIngress Gatewayのソリューションが必要になる。選定含めおおごとになりがち

---

# 提案

- まずは可能なかぎり素の Envoy を使って Progressive Delivery を実現する
- その後に必要性があれば EnvoyベースのIngress Gateway、API Gatewayやサービスメッシュを導入する(Contour, Ambassador, Istio Ingress Gateway等

---

# Progressive Delivery のためにプロキシに必要な機能

1. Front Proxy or Sidecar Proxy どちらでもOK
2. Primary、Canaryにトラフィックを振り分けとしたら、それぞれメトリクス（エラーレート、レイテンシ)などがとれること
3. 動的にPrimary、Canary へのルートの重み付けを変更できること（例えば重み変更のたびに数分かけてプロキシサーバをローリングアップデートして回る、というのは避けたい

---

# Progressive Delivery に使える "可能な限り素の Envoy" とは

- FlaggerやArgoCDから「動的にルートの重みを変更できる」ような Envoy
- それだけ。その他の機能は Progressive Delivery だけなら不要。

---

# 実装例

- Flagger
- Envoy + Crossover sidecar

---

# Crossover

> "Minimal sufficient Envoy xDS for Kubernetes that knows https://smi-spec.io/ "
> https://github.com/mumoshu/crossover

「Envoy を少しだけ拡張するサイドカー」と、Envoyとサイドカーをあわせてデプロイするための Helm Chart

```
Kubernetes ConfigMap, SMI TrafficSplit
|
K8s Watch/Read
↓
Crossover 
|
生成
↓ 
Envoy Route Discovery Service resources (routes)
|
inotify watch
↓
Envoy
```

ConfigMapの中身はEnvoyの設定ファイルそのもの。Crossover は Envoy のために ConfigMap 内の envoy.yaml と SMIリソースをマージする。

EnvoyのRDSリソースの一部をTrafficSplit CustomResourceから生成する。

---

# SMI?

SMI: Service Mesh Interface

Microsoft の Deis チーム、Linkerd チームなどが主導しているサービスメッシュの共通仕様

---

# SMI TrafficSplit？

TrafficSplit: SMIで「ルートとその重み付け」を表現するためのリソース「TrafficSplit」の仕様

```
apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
  name: foobar-rollout
spec:
  service: foobar
  backends:
  - service: foobar-v1
    weight: 100
  - service: foobar-v2
    weight: 0
```

https://github.com/deislabs/smi-spec/blob/master/traffic-split.md

---

## Flagger-Crossover integration

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5912/f2122e3d-04bb-8d59-6885-154ad3a1ed01.png)

Flaggerと組み合わせて Progressive Delivery を行うチュートリアルを用意しておきました。

https://docs.flagger.app/usage/crossover-progressive-delivery

仕組み:

```
ユーザ
|
kubectl, helm, GitOps等で書き込み
↓
Flagger "Canary" リソース
|
K8s Watch/Read
↓
Flagger
|
書き込み
↓ 
SMI TrafficSplit
|
Crossover
↓
Envoy
```

---

## Progressive Delivery の流れ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5912/ac2f0736-611b-72f1-9d92-20899d52e452.png)

canaryとしてv2をデプロイ(②)し、負荷に応じてスケールアウトさせながら徐々にトラフィックを増やしていく。設定した割合までトラフィックが増え、それまでにエラーレート等の値がしきい値を上回らないようであれば、primaryをv2にアップデートする(④)。

https://github.com/weaveworks/flagger/blob/master/docs/gitbook/usage/crossover-progressive-delivery.md#automated-canary-promotion

---

## トラフィックの変化を見てみる

- Canary へのトラフィックが少しずつ増えると同時に Primary へのトラフィックは減る
- Canary Analysis が成功する (Canary のエラーレートがしきい値以下、レイテンシがしきい値以下
- Canary を Primary へ昇格する(=Canaryのトラフィックが少しずつ減ると同時に Primary へのトラフィックが増える
- Fin.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5912/2a97cec1-11f8-2db7-73b8-083549d4ba86.png)

---

## まとめ

- ほぼ素の Envoy と Flagger を使って Progressive Delivery を実現しました
- Istio, Contour, Ambassador 等は(Progressive Deliveryをやりたいだけなら)不要
- もっと簡単な方法があったら教えてください
- 質問・意見等はコメント欄かTwitterまでどうぞ
-