TT Lab
はじめる
学ぶ 学習パス コース

Istioサービスメッシュ

メッシュの外のサーバーを構成員にする方法

TT Labで続きを見る

一言でいうと

メッシュの拡張とは、Kubernetesの外にあるサーバーに身元を与えて、メッシュのサービスマップに載せることです。WorkloadGroup(グループの型)、WorkloadEntry(サーバー1台)、ServiceEntry(呼び出すための名前)の3つのオブジェクトで表現します。

なぜこの問題が残っているのか

メッシュを導入した組織で、最後まで残るのは、移せないサーバーです。認証を取り直す必要がある決済システム、ライセンスがハードウェアに結び付いたソフトウェア、ビルド方法を誰も知らない古いサービス。これらをメッシュの外に置いておくと、見た目には何の問題もありません。呼び出しはうまくいき、画面もまともです。問題は、そこからメッシュが提供するものが途切れるという点です。その区間にはmTLSがなく、呼び出し元の身元に基づく認可もかからず、メッシュのサービスマップやメトリクスにも現れません。事故が起きると、「ここから先は私たちには見えません」ということになります。

外へ出ていく呼び出しを登録する作業(ServiceEntryで外部APIを書いておくこと)と、この作業は別物です。前者は、お客様を入り口まで案内することで、後者は、そのサーバーをメンバー名簿に載せることです。

3つのオブジェクトが分担する仕事

オブジェクト 対応するKubernetesの概念 何を書くか
WorkloadGroup DeploymentのPodテンプレート グループ共通のラベル、サービスアカウント、ネットワーク、ポート、ヘルスチェック
WorkloadEntry Pod1つ そのサーバーのアドレス、ネットワーク、身元、ロケーション(locality)、ポート
ServiceEntry Service メッシュ内で呼び出すホスト名と、その背後に立つワークロードを選ぶセレクター

ここで最もよく抜け落ちるのがServiceEntryです。WorkloadEntryだけを作っても、登録はされましたが、呼び出すための名前がありません。ServiceEntryのworkloadSelectorが、ラベルでWorkloadEntryを選んで、その名前の背後に立てます。このとき、セレクターが見るのはWorkloadEntryのmetadata.labelsです。specの中にラベルを書いても、何も選ばれません。

locationも意味が大きいです。MESH_INTERNALならメッシュの構成員として扱われて、mTLSやポリシーの対象になり、MESH_EXTERNALなら外部のサービスとして扱われます。同じServiceEntryでも、この1つの値がセキュリティモデルを分けます。

resolutionは、宛先をどう見つけるかを決めますが、値ごとにendpointのルールが違い、そのルールをCRDスキーマが強制します。NONEは、元の宛先アドレスをそのまま使うので、endpointを書くと拒否されます。DNS_ROUND_ROBINは、1つの名前を一度解決して、その結果を使い回す方式なので、endpointは0個か1個でなければなりません。STATICは、書かれたendpointや、セレクターが選んだWorkloadEntryを使います。

身元はどうやってそのサーバーに届くのか

Kubernetesの中では、kubeletがPodにトークンを入れてくれて、プロキシがそれで自分を証明します。VMにはkubeletがないので、人が入れてあげる必要があります。そのサーバーが必要とするものは3つです。

istioctl x workload entry configureが、この3つを集めて1つのディレクトリにしてくれます。結果のcluster.envを開くと、SERVICE_ACCOUNT、ISTIO_META_NETWORK、ISTIO_INBOUND_PORTSのような値が、WorkloadGroupからそのまま降りてきているのが見えます。つまり、WorkloadGroupは単なる宣言ではなく、実際の起動設定の原本です。

networkの値も、ここで意味を持ちます。同じnetwork名を持つワークロード同士は直接通信でき、違えばゲートウェイを経由する必要があると、メッシュが判断します。値が間違っていても、接続できなくなるのではなく、見当違いの経路を通ります。

現場での姿

最もよくある報告は、「登録したのに、どこからも見えない」というものです。原因の大半は、ラベルの不一致です。WorkloadEntryのラベルとServiceEntryのセレクターが1文字でも違うと、エラーは出ず、ただ何も選ばれません。そのため、セレクターが実際にいくつ選んでいるかを数えるスクリプトを、登録手順に付けているチームが多いです。

2つ目は、アドレスの打ち間違いです。WorkloadEntryのaddressは、IPでもFQDNでもよいため、CRDスキーマが形式を強制しません。そのため、空白が混ざった値もそのまま作られます。こうしたものを検出してくれるのは、APIサーバーではなくistioctl analyzeです。スキーマ検査と設定分析は別々の網で、両方あって初めて穴がふさがります。

このラボ環境の限界

ラボのPodでは、VMを実際に起動することはできません。そのため、作られた設定一式をサーバーに入れて、プロキシを立ち上げてメッシュにつなぐ場面は見られず、自動登録(VMが自分でWorkloadEntryを作ること)も確認できません。その代わり、3つのオブジェクトのスキーマによる強制、セレクターが実際に選ぶもの、そして、設定一式がWorkloadGroupからどのように作られるかは、すべて本物のAPIサーバーを相手に確認できます。

次のラボですること

サーバーが受け取る身元の文字列を先に書いてみて、WorkloadGroup、WorkloadEntry、ServiceEntryを順に作ります。スキーマが拒否する値(probeを両方書くこと、templateを抜くこと、resolutionごとのendpointルール)を自分で受けてみて、最後に、VMが受け取る設定一式を実際に作り、セレクターが何台を選ぶのかを数えるレポートを残します。