プロファイルとメッシュ設定 — 取り消しが高くつく二つの決定
一言でいうと
Istioのインストールは、「プロファイルというまとまりを選ぶ作業」と「メッシュ全体の設定に値を書く作業」の2つの層に分かれます。どちらも、クラスターに届く前にistioctl manifest generateで丸ごと読めます。
なぜインストールを事前に読むのか
メッシュを初めて立ち上げるとき、人が最もよくやるのは、ドキュメントのインストールコマンドの1行をそのままコピーして貼り付けることです。その1行の裏には40個近いオブジェクトがあり、そのうちいくつかはクラスター全体にわたる権限を持ちます。もっと重要なのは、そのコマンドが一緒に植え付けるデフォルト値です。メッシュ全体の設定は、その後に注入されるすべてのプロキシが読む値なので、あとから直すと、メッシュ内のすべてのワークロードが設定を受け取り直します。元に戻すコストは、上げるコストよりもずっと大きくなります。
最も手荒な例がoutboundTrafficPolicy.modeです。デフォルトのALLOW_ANYは、登録されていない外部アドレスへ出ていく呼び出しを、プロキシが通します。REGISTRY_ONLYに変えると、プロキシが登録されていない宛先へのトラフィックを拒否します。有効にする日に誰にも予告していなければ、決済代行会社・社内SMTP・外部ログ収集サーバーへ出ていた呼び出しが、一斉に切れます。こうした値は、「インストールしてから確認」ではなく、「インストールする前に合意」しておくものです。ただし、この設定だけで、Podのすべての外部通信を制御するセキュリティ境界ができるわけではありません。プロキシがキャプチャしない通信経路まで遮断するには、別のネットワーク制御が必要です。Istioのセキュリティのベストプラクティスも、サービス登録の漏れを見つける設定と、強制的な外部通信のセキュリティポリシーを区別しています。
2つのつまみ: プロファイルと値
プロファイルは、何を立ち上げるかを選ぶまとまりです。1.24基準でよく使う4つは、次のように分かれます。
| プロファイル | コントロールプレーン | ゲートウェイ | アンビエントの構成要素 |
|---|---|---|---|
minimal |
istiod | なし | なし |
default |
istiod | ingress | なし |
demo |
istiod | ingress + egress | なし |
ambient |
istiod | なし | ztunnel + istio-cni-node |
minimalは、ゲートウェイ1式(Deployment・Service・HPA・PDB・Role・RoleBinding・ServiceAccount)が丸ごと抜けたもので、demoは、そこにegress1式を加えたものです。まとまりではなく値を1つだけ変えたいときは、--set values.…を使います。たとえば、--set values.gateways.istio-ingressgateway.autoscaleMin=3は、プロファイルはそのままにして、レンダリングされたHPAのminReplicasだけを1から3に変えます。2つのつまみを混ぜて使うと、「プロファイルを変えたつもりだったのに、値が1つだけ変わっていた」という状態になります。
メッシュ全体の設定は、3つ目の場所です。--set meshConfig.…で入れ、レンダリング結果では、別のCRDではなく、istio-systemネームスペースのConfigMap istioの中のmeshキーに、YAMLのかたまりとして入ります。
istioctl manifest generate --set profile=minimal \
--set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY \
--set meshConfig.trustDomain=lab.internal
ここでtrustDomainは、ワークロードの身元(SPIFFE ID)の前半部分を決める値なので、あとから変えると、すでに発行された身元を基準に書いた認可ポリシーがすべてずれてしまいます。defaultConfigの下に書くものは、プロキシ1つ1つのデフォルトの動作です。プロキシの準備が整うまでアプリケーションコンテナを待たせるか、終了するときにどれだけ待つか、といったものです。
値を間違えると、クラスターに届く前に引っかかります。列挙型にない値を渡すと、レンダリングはunknown value ... for enum istio.mesh.v1alpha1.MeshConfig.OutboundTrafficPolicy.Modeで終わり、存在しないプロファイル名を渡すと、プロファイルファイルが見つからないと言われます。もう1つあります。1.24には--profileというフラグ自体がありません。--set profile=が正しく、間違えるとunknown flagで終わります。
現場での姿
1つ目は、「インストールは同じなのに、クラスターごとに動作が違う」という報告です。原因は、たいてい、人によって違う--setを付けてインストールし、そのコマンドがどこにも記録されていないことです。レンダリング結果をリポジトリに置いて比較する習慣が、これを防ぎます。マニフェストはクラスターなしで作れるので、インストールの変更をコードレビューに出せます。
2つ目は、範囲を絞らないグローバル設定です。ある1つのチームがプロキシのスレッド数を増やしてほしいと言うので、メッシュ全体のdefaultConfig.concurrencyを上げると、数千個のPodのメモリ使用量が一緒に上がります。こういうときに使うのがProxyConfig CRDです。ネームスペースやワークロードのセレクター単位で、グローバルなデフォルト値を上書きします。値の検査は、istioctlではなくCRDスキーマが行うので、負の数のような値は、APIサーバーが拒否します。
このラボ環境の限界
ラボのPodには、istiodもゲートウェイも立ち上がりません。そのため、「REGISTRY_ONLYに変えたら呼び出しが切れた」ことを直接見ることはできず、プロキシがこの設定を実際に読む場面も確認できません。その代わり、インストールを決めるそのドキュメント自体は、オフラインで完全に作れますし、本物のAPIサーバーがつながっているので、ProxyConfigのようにCRDとして入る設定は、スキーマによる強制まで実際に確認できます。
次のラボですること
4つのプロファイルを順にレンダリングして、何が増えて何が減るかをファイルで比較し、メッシュ全体の設定を4つ入れて、レンダリングされたConfigMap istioの中で探してみます。わざと間違えた値・存在しないプロファイル・存在しないフラグで3回拒否されてみて、最後に、プロファイルと構成要素の表を作り、自分でもう一度レンダリングして検証するスクリプトを組みます。