プロキシをポッドから外すと — アンビエントの構成要素と二つの層
目標
アンビエントプロファイルをレンダリングして、サイドカーモードと構成要素を見比べ、ネームスペースのラベルでデータプレーンを選ぶ方法と、2つのラベルを重ねたときにアナライザーが何を検出するかを確認します。waypointマニフェストを生成してフィールドを読み、このクラスターで適用がなぜ失敗するのかまで、直接見ます。最後に、ネームスペースをモード別に数える点検表を作ります。
なぜ重要なのか
アンビエントは、プロキシをPodから切り離して、ノードに移す設計です。得られるものは明確です。Podごとにプロキシがないのでリソースが減り、ワークロードを再起動せずに、メッシュに入れたり外したりできます。その代わり、機能が2つの層に分かれます。ノードのL4プロキシだけでできるのは、相互認証とL4認可までで、HTTPパスに基づくルーティングや、メソッド単位の認可のように、リクエストの内容を見る必要がある作業には、waypointという別のL7プロキシが必要です。そのため、移行計画は「サイドカーをオフにしよう」ではなく、「このネームスペースが使っている機能のうち、L7が必要なものは何か」から始まります。そして、切り替えの最中は、2つのモードが1つのクラスターに共存するので、どのネームスペースがどのモードなのかを、機械が読める形で数えておくことが、人の記憶よりもはるかに信頼できます。
ステップ
/root/ist-ambientを作成して、istioctl manifest generate --set profile=ambientの出力を/root/ist-ambient/ambient.yamlに保存してください。その中のDeploymentとDaemonSetをすべて取り出して、/root/ist-ambient/ambient-workloads.tsvに、<kind>|<이름>の形式で(プレースホルダーは種類名と名前です)ソートして書いてください。- defaultプロファイルもレンダリングして
/root/ist-ambient/default.yamlに保存し、2つのレンダリングのServiceAccount名を見比べて、/root/ist-ambient/sa-diff.tsvに、only-ambient\t<이름>とonly-default\t<이름>の行で(プレースホルダーは名前です)ソートして書いてください(両方にあるものは書きません)。 - ステップ1のレンダリングから、名前が
istioのConfigMapのdata.meshだけを取り出して、/root/ist-ambient/ambient-mesh.yamlに保存してください。そして、そのレンダリングに含まれるConfigMap名をすべて、/root/ist-ambient/ambient-configmaps.txtに1行ずつソートして書いてください。 - ネームスペースを2つ作成してください。
shop-sidecarにはistio-injection=enabledラベルを、shop-ambientにはistio.io/dataplane-mode=ambientラベルを付けます。そして、2つのネームスペースのラベルをクラスターから読み取って、/root/ist-ambient/ns-labels.tsvに、<네임스페이스>\t<라벨키>=<값>の形式で(プレースホルダーはネームスペースとラベルキーと値です)ソートして書いてください。 - ネームスペース
shop-bothを作成して、istio-injection=enabledとistio.io/dataplane-mode=ambientを両方付けてください。istioctl analyze -n shop-both -o jsonの出力を/root/ist-ambient/analyze-conflict.jsonに保存してください。IST0123が出る必要があります。そのあと、サイドカー側のラベルだけを削除して、同じコマンドの出力を/root/ist-ambient/analyze-fixed.jsonに保存してください。今度はIST0123がない必要があります。 istioctl waypoint generate --for service -n shop-ambient --name shop-waypointの出力を/root/ist-ambient/waypoint.yamlに保存してください。そして、そこから読み取った4つを、/root/ist-ambient/waypoint-fields.tsvにapiVersion・gatewayClassName・port・protocolの4行で書いてください。--for workloadでも一度生成して/root/ist-ambient/waypoint-workload.yamlに保存し、2つのファイルのmetadata.labels."istio.io/waypoint-for"の値を、/root/ist-ambient/waypoint-for.tsvにserviceとworkloadの2行で、<파일이름>\t<값>の形式で書いてください(プレースホルダーはファイル名と値です。名前はshop-waypoint-wlにします)。そのあと、ステップ6のwaypoint.yamlを実際に適用してみて、その結果を/root/ist-ambient/waypoint-apply.txtに保存してください。/root/ist-ambient/mode-report.shを作成して、クラスターのすべてのネームスペースを<네임스페이스>\t<모드>の形式で名前順に、標準出力にだけ出力するようにしてください(プレースホルダーはネームスペースとモードです)。モードは、2つのラベルが両方あればconflict、アンビエントのラベルだけがあればambient、istio-injectionがenabledならsidecar、それ以外はnoneです。出力を/root/ist-ambient/mode-report.txtに保存してください。
参考
--set profile=ambientのレンダリングには、サイドカープロファイルにないDaemonSetが2つ出てきます。- データプレーンのラベルは
istio.io/dataplane-mode=ambient、サイドカーのラベルはistio-injection=enabledです。 - ラベルを削除するときは、
kubectl label ns <이름> <키>-のように、キーの後ろにマイナス記号を付けます(プレースホルダーはネームスペース名とキーです)。 - よくある間違い: 2つのラベルを一緒に付けたまま、切り替わったと思い込むこと。アナライザーがIST0123として検出してくれます。
- よくある間違い: waypointをIstio専用のオブジェクトだと思うこと。Gateway APIのGatewayです。
- 参考: https://istio.io/v1.24/docs/ambient/architecture/data-plane/
- 参考: https://istio.io/v1.24/docs/ambient/usage/waypoint/
- 参考: https://istio.io/v1.24/docs/ambient/usage/l7-features/
アンビエントプロファイルが何を起動するのかを数える
/root/ist-ambientを作成して、istioctl manifest generate --set profile=ambientの出力を/root/ist-ambient/ambient.yamlに保存してください。その中のDeploymentとDaemonSetをすべて取り出して、/root/ist-ambient/ambient-workloads.tsvに、<kind>|<이름>の形式で(プレースホルダーは種類名と名前です)ソートして書いてください。
アンビエントは、Podごとにプロキシを入れる代わりに、ノードごとに2つを敷きます。トラフィックを横取りするほうと、L4プロキシの役割を果たすほうです。どちらもDaemonSetとして出力されます。レンダリングから取り出すときは、yq -N e 'select(.kind=="DaemonSet") | .metadata.name'のように、種類で絞り込めば済みます。
サイドカーモードと見比べると、身元が2つ増えて1つ減る
defaultプロファイルもレンダリングして/root/ist-ambient/default.yamlに保存し、2つのレンダリングのServiceAccount名を見比べて、/root/ist-ambient/sa-diff.tsvに、only-ambient\t<이름>とonly-default\t<이름>の行で(プレースホルダーは名前です)ソートして書いてください(両方にあるものは書きません)。
構成要素が増えたり減ったりすると、その構成要素が使うサービスアカウントも一緒に動きます。2つのリストをそれぞれソートして、commで比較すれば、片方にだけある名前が出ます。アンビエントには、ゲートウェイが既定でないという点も、ここで見えてきます。
アンビエントのメッシュ設定には、何が追加で有効になっているか
ステップ1のレンダリングから、名前がistioのConfigMapのdata.meshだけを取り出して、/root/ist-ambient/ambient-mesh.yamlに保存してください。そして、そのレンダリングに含まれるConfigMap名をすべて、/root/ist-ambient/ambient-configmaps.txtに1行ずつソートして書いてください。
アンビエントでは、Pod間のトラフィックが、ノードのL4プロキシを通って、トンネルで渡されます。そのトンネルを有効にする値が、プロキシのメタデータに入っているので、defaultConfig.proxyMetadataの下を見てください。ConfigMapの一覧には、サイドカープロファイルになかったものが、もう1つあります。
ネームスペースのラベル1行が、データプレーンを選ぶ
ネームスペースを2つ作成してください。shop-sidecarにはistio-injection=enabledラベルを、shop-ambientにはistio.io/dataplane-mode=ambientラベルを付けます。そして、2つのネームスペースのラベルをクラスターから読み取って、/root/ist-ambient/ns-labels.tsvに、<네임스페이스>\t<라벨키>=<값>の形式で(プレースホルダーはネームスペースとラベルキーと値です)ソートして書いてください。
2つのモードは、別々のラベルキーを使います。サイドカー側は、注入Webhookが見るラベルで、アンビエント側は、ノードのCNIが見るラベルです。kubectl get ns -o jsonにjqを付ければ、ラベルをそのまま取り出せます。
2つのラベルを一緒に付けると、動作が定義されない
ネームスペースshop-bothを作成して、istio-injection=enabledとistio.io/dataplane-mode=ambientを両方付けてください。istioctl analyze -n shop-both -o jsonの出力を/root/ist-ambient/analyze-conflict.jsonに保存してください。IST0123が出る必要があります。そのあと、サイドカー側のラベルだけを削除して、同じコマンドの出力を/root/ist-ambient/analyze-fixed.jsonに保存してください。今度はIST0123がない必要があります。
2つのラベルは、別々の構成要素が読みます。1つは注入Webhook、もう1つはノードのCNIです。両方付くと、そのPodがどちらのデータプレーンを使うのかが決まりません。ラベルを削除するときは、キーの後ろにマイナス記号を付けます。
L7が必要なら、waypointを別に立てる
istioctl waypoint generate --for service -n shop-ambient --name shop-waypointの出力を/root/ist-ambient/waypoint.yamlに保存してください。そして、そこから読み取った4つを、/root/ist-ambient/waypoint-fields.tsvにapiVersion・gatewayClassName・port・protocolの4行で書いてください。
waypointは、Istio専用のオブジェクトではなく、Gateway APIのGatewayとして表現されます。どのゲートウェイクラスなのかが、これをwaypointにします。リスナーのポートとプロトコルは、アンビエントがPod間で使うトンネルそのものです。
何のためのwaypointなのか、そして、なぜここでは適用されないのか
--for workloadでも一度生成して/root/ist-ambient/waypoint-workload.yamlに保存し、2つのファイルのmetadata.labels."istio.io/waypoint-for"の値を、/root/ist-ambient/waypoint-for.tsvにserviceとworkloadの2行で、<파일이름>\t<값>の形式で書いてください(プレースホルダーはファイル名と値です。名前はshop-waypoint-wlにします)。そのあと、ステップ6のwaypoint.yamlを実際に適用してみて、その結果を/root/ist-ambient/waypoint-apply.txtに保存してください。
waypointは、サービスの前に立てることも、ワークロードの前に立てることもできます。ラベル1つが、その範囲を語ります。適用は、このクラスターでは成功しません。なぜそうなるのかは、エラー文がそのまま語ってくれます。
クラスターのネームスペースを、モード別に数える点検表
/root/ist-ambient/mode-report.shを作成して、クラスターのすべてのネームスペースを<네임스페이스>\t<모드>の形式で名前順に、標準出力にだけ出力するようにしてください(プレースホルダーはネームスペースとモードです)。モードは、2つのラベルが両方あればconflict、アンビエントのラベルだけがあればambient、istio-injectionがenabledならsidecar、それ以外はnoneです。出力を/root/ist-ambient/mode-report.txtに保存してください。
kubectl get ns -o jsonを1回実行すれば、すべてのラベルを受け取れるので、jqで振り分けます。ラベルのキーにはドットとスラッシュが混ざっているので、jqでは、角括弧と引用符で取り出すほうが安全です。istio-injectionは、値がdisabledの場合もあるので、有効なものだけを数える必要があります。