プロキシをポッドから外すと何を得て何を分けるのか
一言でいうと
アンビエントは、Podごとに置いていたプロキシをノードのL4プロキシに移し、リクエストの内容を見る必要がある機能だけを、waypointという別のL7プロキシに任せる設計です。そのため、移行はラベル1行ではなく、機能の一覧から始まります。
なぜ別のデータプレーンが必要だったのか
サイドカーモデルのコストは3つあります。第一に、Podごとにコンテナが1つずつ増えます。Podが2,000個ならプロキシも2,000個で、その分のリクエストリソースが確保されます。第二に、プロキシを入れたり、外したり、バージョンアップしたりするには、Podを再起動する必要があります。メッシュに入ること自体がデプロイイベントになるので、導入そのものが、各チームのデプロイ日程に縛られます。第三に、プロキシがアプリケーションと同じPodにあるため、起動順序・終了順序・リソース競合のような問題がついて回ります。
アンビエントは、この3つを一度に避けます。ノードごとに2つを敷きます。トラフィックをPodから横取りする構成要素と、横取りしたトラフィックを相互認証されたトンネルで運ぶL4プロキシです。Podはそのままにして、ネームスペースのラベル1行で、メッシュに入ったり出たりします。再起動は必要ありません。
2つの層に分かれる機能
ここで正確に知っておくべきことがあります。ノードのL4プロキシは、リクエストの内容を見ません。そのため、できることとできないことが、はっきり分かれます。
| 機能 | L4プロキシだけで | waypointが必要 |
|---|---|---|
| ワークロード間の相互認証と暗号化 | できる | — |
| 呼び出し元の身元による許可・拒否(L4) | できる | — |
| ポート・身元を基準にしたポリシー | できる | — |
| HTTPのパス・ヘッダーに基づくルーティング | できない | 必要 |
| メソッド・パス単位の認可 | できない | 必要 |
| リトライ・タイムアウト・トラフィック分割 | できない | 必要 |
waypointは、Istio専用のオブジェクトではなく、Gateway APIのGatewayとして表現されます。ゲートウェイクラスがistio-waypointであることが、それをwaypointにし、リスナーは、アンビエントがPod間で使うトンネルプロトコルをそのまま受け付けます。何のためのwaypointなのかは、ラベルistio.io/waypoint-forが語ります。サービスの前に立てるのか、ワークロードの前に立てるのか、その両方か、どちらでもないのかです。
切り替えはどうするのか
ラベルが2つあるという点が、落とし穴です。サイドカーは、注入Webhookが見るラベルを、アンビエントは、ノードの構成要素が見るラベルを使います。両者はお互いを知りません。そのため、ネームスペースに両方を付けておいても、エラーは出ず、そのネームスペースのPodがどちらのデータプレーンを使うのかが、決まらない状態になります。istioctl analyzeが、この場合をIST0123として検出してくれます。切り替え作業の点検項目に、このコマンドを入れておく理由です。
順序は、次のように決めます。まず、そのネームスペースが実際に使っているメッシュ機能を書き出します。L7機能が1つでもあれば、waypointを先に立てます。そのあとで、サイドカーのラベルを削除して、アンビエントのラベルを付けます。元に戻すときは、逆の順序です。切り替えの最中は、2つのモードが1つのクラスターに共存するので、どのネームスペースがどのモードなのかを数えるスクリプトを作っておくほうが、人の記憶よりも頼りになります。
現場での姿
最もよくある事故は、「アンビエントに移したら、ヘッダーに基づくルーティングが効かない」というものです。ルールはそのまま残っていて、エラーもありません。そのルールを強制するL7プロキシが、その場所にないだけです。2つの層を知らずに移すと、必ずぶつかります。
この事故が特にたちが悪い理由は、静かだという点です。L4の層はそのまま動くので、接続は確立され、相互認証もかかります。切れるのは、リクエストの内容によって分かれていた経路だけなので、見た目にはメッシュがうまく回っているのに、特定のバージョンに行くべきトラフィックだけが、見当違いの場所へ行きます。ログにもエラーは残りません。そのため、切り替え計画には、「このネームスペースが使っているメッシュオブジェクトの一覧」が必ず入る必要があり、その中でL7を要求するものが1つでもあれば、waypointを先に立ててから、ラベルを変えます。
2つ目は、ラベルを削除せずに追加してしまった場合です。サイドカーのラベルが残っていると、新しく起動するPodには、相変わらずプロキシが注入されます。画面では、切り替えが終わったように見えるのに、実際には半分だけ移った状態で、この状態は、デプロイが起きるたびに、少しずつ変わります。
このラボ環境の限界
この環境では、ztunnelもwaypointも、実際に起動できません。そのため、トンネルを通るトラフィックや、L4認可が本当に強制される場面は、見られません。さらに、このクラスターにはGateway APIのCRDがないため、waypointのマニフェストは生成はできても、適用はできません。この事実を隠さず、ラボの中で直接確認します。適用が失敗するエラー文が、waypointが何の上に立っているのかを、最もはっきり語ってくれるからです。その代わり、プロファイルのレンダリング、ラベルとその競合の判定、waypointマニフェストのフィールドは、すべて本物のツールと本物のAPIサーバーで確認できます。
次のラボですること
アンビエントプロファイルをレンダリングして、サイドカープロファイルと構成要素・身元を見比べ、メッシュ設定に何が追加で有効になっているかを見ます。ネームスペースのラベルで2つのモードを作ってみて、2つを重ねたときにアナライザーが何を検出するかを確認してから、waypointマニフェストを生成してフィールドを読み、適用がなぜ失敗するのかまで見ます。最後に、クラスターのネームスペースをモード別に数える点検表を作ります。