IstioOperator でインストールを調整し、revision でアップグレードする
一言でいうと
Istioのインストールは、IstioOperatorという1つのドキュメントで表現され、profileはそのドキュメントのデフォルト値のまとまりで、MeshConfigはメッシュ全体に適用される設定です。アップグレードは、revisionを並べて立てるcanary方式が基本で、in-placeはより危険なので条件が付きます。
なぜ必要なのか
istioctl installの1行でIstioが立ち上がると、すべて終わったように見えます。ところが、運用ではすぐに、「アクセスログを有効にする必要がある」「egressゲートウェイを追加する必要がある」「外部の宛先をデフォルトでブロックに変える必要がある」という要求が来ます。このとき、--setフラグを1つずつ付けていくと、何を変えたのか誰も覚えていられなくなります。Istioのドキュメントは、--setと-fが同じことを行うものの、運用では-fでファイルを渡す方式を強く勧めると書いています。インストールの状態が1つのファイルに残っていて初めて、アップグレードのときに同じファイルをもう一度使えるからです。
アップグレードも同じです。コントロールプレーンをその場で入れ替えるin-place方式は、すべてのサイドカーが一度に新しいistiodを見ることになるので、問題が起きるとメッシュ全体が影響を受けます。そのためIstioは、新しいコントロールプレーンを隣にもう1つ立てて、ネームスペース単位で移していくcanary方式を推奨しています。ICA試験のInstall/Upgrade/Configドメイン(20%)は、まさにこの2つ、つまり何でインストールを揃えるのかと2つのアップグレード方式をいつ選ぶのかを問います。
どう動くのか
IstioOperator: クラスターに適用されない設定ドキュメント
istioctl install -fに渡すファイルは、install.istio.io/v1alpha1のIstioOperatorリソースです。公式のリファレンスは、このリソースを「Kubernetesのオブジェクトに似た形式だが、クラスターに適用されるものではなく、istioctlのファイル入力である」と説明しています。つまり、kubectl applyで入れるものではなく、istioctlが読んでマニフェストを作る材料です。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: default # 기본값 묶음. 비우면 default
revision: 1-31-0 # canary 업그레이드용 식별자. '.' 은 쓸 수 없다
meshConfig: # 메시 전체 설정
accessLogFile: /dev/stdout
outboundTrafficPolicy:
mode: REGISTRY_ONLY
components: # 어떤 구성요소를 켜고 끌지, k8s 리소스 설정
egressGateways:
- name: istio-egressgateway
enabled: true
values: {} # Helm values 로 바로 넘기는 통로(검증됨)
specの主要なフィールドは、profile、hub/tag(イメージの場所)、revision、meshConfig、components(base、pilot、cni、ztunnel、istiodRemote、ingressGateways、egressGateways)、valuesです。ドキュメントは、valuesがHelmテンプレートに渡る検証済みの通路であり、IstioOperatorSpecにある項目は、valuesの代わりに上のフィールドで書くように案内しています。古いHelmのvaluesのパスを--setで使うには、values.のプレフィックスを付けます。
profile: 名前の付いたHelm valuesのまとまり
profileは、Helmチャートに組み込まれた名前の付いたvaluesのオーバーライドのまとまりです。そのため、helmとistioctlの両方で、同じ名前で使います。デプロイのprofileは次のとおりです。
| profile | 用途 | istioctlが一緒にインストールする構成要素 |
|---|---|---|
| default | 運用とマルチクラスターのprimaryで推奨 | istiod、istio-ingressgateway |
| demo | 機能のデモ用。トレーシングとアクセスログを高く有効にするので、性能テストには不向き | istiod、ingress、egressゲートウェイ |
| minimal | defaultと同じだが、コントロールプレーンだけ | istiod |
| ambient | ambientモードの開始用 | istiod、CNI、ztunnel |
| remote / empty / preview | 外部のコントロールプレーン用 / 何もインストールしない土台 / 実験的な機能 | — |
ここで、試験が好む違いが1つあります。istioctlのprofileはどの構成要素をインストールするかの一覧まで含みますが、Helmのprofileは値の集まりにすぎず、各構成要素をhelm installで1つずつ立てる必要があります。そして、--set profile=default --set values.global.platform=gkeのように、プラットフォームのprofile(gke、eks、openshift、k3sなど)を、デプロイのprofileと一緒に渡すことが推奨されます。
MeshConfig: メッシュ全体に適用される値
meshConfigは「メッシュ全体の設定」です。accessLogFileは、空ならアクセスログを無効にし、/dev/stdoutを指定すると有効にします。accessLogEncodingはTEXTがデフォルトで、JSONに変えられます。outboundTrafficPolicyのデフォルトはALLOW_ANYなので、登録されていない外部の宛先にも出ていけます。enableTracingは、スパンの生成を有効にしますが、プロキシの設定に収集器が必要です。例外が1つ、defaultConfig(ProxyConfig)です。ドキュメントは、この値がサイドカーの注入時点に一度適用されて、Podが生きている間は変わらず、残りのMeshConfigは、実行中にも動的に配布されると書いています。そのため、プロキシの設定を変えたのに反映されないなら、Podを再起動する必要があります。
istioctlとHelmのインストール経路の違い
Helmのインストールは、3つのチャートを順番に立てます。クラスタースコープのCRDを含むbase、istiodをデプロイするistiod、そしてオプションのgatewayです。revisionでインストールするときは、baseチャートに--set defaultRevision=<revision>を渡して初めて、リソース検証のWebhookが動作します。Helmで削除してもCRDは残りますが、これは意図された設計です。CRDを消すと、VirtualServiceやDestinationRuleのようなユーザーのリソースが連鎖的に削除されるからです。istioctlでインストールしたものをHelmに移すときは、--take-ownershipで既存のリソースを引き継げます。ドキュメントは、Helmガイドのチャートが、istioctlが使うチャートと同じだが、gatewayチャートだけが異なると明記しています。
canaryアップグレード: revisionを並べて立てる
istioctl install --set revision=1-31-0のようにrevisionを指定すると、istiodのDeploymentとService、サイドカー注入のWebhookが、revision名を付けてもう1つできます。既存のサイドカーは、何も影響を受けません。ワークロードを移すには、ネームスペースのistio-injection=enabledラベルを消して、istio.io/rev=<revision>を付けてから、Podを再起動します。istio-injectionラベルは、後方互換のためにistio.io/revより優先されるので、必ず消す必要があります。
ネームスペースごとにラベルを直して回る代わりに、revision tagを使います。istioctl tag set prod-stable --revision 1-30-1でタグを作り、ネームスペースにはistio.io/rev=prod-stableを付けておけば、あとでistioctl tag set prod-stable --revision 1-31-0 --overwriteを1回実行するだけで、そのタグを使うすべてのネームスペースが、新しいrevisionに移ります。defaultタグは特別で、istio-injection=enabledの注入、リソースの検証、リーダーロックを担当します。検証が終わったら、istioctl uninstall --revision 1-30-1で古いコントロールプレーンを削除します。revision方式は、マイナーの2段階スキップ(1.15 → 1.17)をサポートします。
in-placeアップグレード: 条件が多い
istioctl upgradeは、その場でコントロールプレーンとゲートウェイを入れ替えます。ドキュメントが書いている条件は次のとおりです。インストールされているバージョンが、新しいバージョンよりマイナーで1段階以下しか低くてはならず、--revisionでインストールしたものには使えず、インストールのときに使った-fファイルや--setの値をそのまま渡さないと、カスタム設定がデフォルト値に戻ってしまいます。終わったあとは、kubectl rollout restart deploymentで、データプレーンを自分で再起動する必要があります。中断を減らすには、istiodを2つ以上置いて、PodDisruptionBudgetを最小可用1にするよう勧めています。
現場での姿
あるチームが、--set5つでインストールしたメッシュをistioctl upgradeで上げたところ、アクセスログが消えて、outboundTrafficPolicyがALLOW_ANYに戻ったことがあります。アップグレードのコマンドに、同じ--setを渡さなかったからで、原因を見つけるのに1日かかりました。IstioOperatorのファイルをリポジトリに置いて、インストールもアップグレードも-fで同じファイルを渡していれば、起きなかったことです。
もう1つは、canaryを元に戻すときです。defaultのprofileでは、ゲートウェイがrevisionごとに別々には立ち上がらず、新しいrevisionにin-placeでアップグレードされます。そのため、canaryのrevisionを消すと、ゲートウェイが古いコントロールプレーンを指さなくなります。ドキュメントは、canaryを消す前に、古いistioctlでゲートウェイを先に再インストールし、正常に動作することを確認するように書いています。順序を入れ替えると、Ingressが切れます。
次のクイズで確認すること
profileごとにistioctlがインストールする構成要素、defaultConfigだけが再起動を必要とする理由、istio-injectionとistio.io/revの優先順位、revision tagを移すコマンド、そして、in-placeアップグレードが失敗したり設定を失ったりする条件を問います。参考: Install with Istioctl、Installation Configuration Profiles、Canary Upgrades、In-place Upgrades、Install with Helm。