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

Istioサービスメッシュ

移行できなかったサーバーをメッシュに入れる — WorkloadGroup と WorkloadEntry

TT Labで続きを見る

目標

WorkloadGroupで、メッシュの外にあるサーバーのグループの型を作り、WorkloadEntryでサーバーを1台ずつ登録し、ServiceEntryでメッシュ内のサービス名に結び付けます。最後に、そのサーバーが受け取る設定一式を、istioctl x workload entry configureで実際に作ってみて、セレクターが何を選ぶのかを数えるレポートを残します。

なぜ重要なのか

メッシュを導入しても、Kubernetesに移せないサーバーは残ります。これらを外に置いておくと、メッシュが提供するものがそこで途切れます。身元、暗号化、アクセスポリシー、そして何より、1枚のサービスマップです。メッシュの拡張は、そのサーバーをお客様ではなく、構成員として迎え入れる作業です。核心は身元です。Kubernetesの中では、Podがサービスアカウントで身元を受け取りますが、VMにはそういうものがありません。そのため、WorkloadGroupにどのサービスアカウントを使うかを書いておき、そのサーバーには、クラスターが発行したトークンとルート証明書を、あらかじめ入れてあげます。この3つが合って初めて、VMのプロキシがコントロールプレーンにつながって、自分の身元を証明できます。3つのオブジェクトの関係も混同しやすいのですが、グループの型がWorkloadGroup、サーバー1台がWorkloadEntry、呼び出すための名前がServiceEntryと考えれば整理できます。

ステップ

  1. /root/ist-expansionとネームスペースexpansionを作成して、その中にServiceAccount billing-saを作成してください。そして、このサービスアカウントを使うワークロードがメッシュで受け取ることになる身元の文字列を、/root/ist-expansion/identity.txtに1行で書いてください。トラストドメインはデフォルト値のcluster.localです。
  2. /root/ist-expansion/wg.yamlにWorkloadGroup legacy-billingを書いて、expansionに適用してください。spec.metadata.labelsはapp: billing、spec.templateはserviceAccount: billing-sa、network: onprem、ports.http: 8080で、spec.probeはperiodSeconds: 5で、httpGetでポート8080の/healthzを見ます。
  3. /root/ist-expansion/wg-bad-probe.yamlにWorkloadGroup bad-probeを書いて、spec.probeにhttpGetとtcpSocketを両方入れてください。/root/ist-expansion/wg-no-template.yamlにはno-templateを書いて、spec.templateをまるごと抜いてください。どちらもサーバー側の試験適用だけを行って、拒否文を/root/ist-expansion/wg-reject.txtに順番に集めてください。
  4. /root/ist-expansion/we.yamlにWorkloadEntry billing-1を書いて適用してください。メタデータのラベルはapp: billing、addressは10.20.30.41、networkはonprem、serviceAccountはbilling-sa、localityはdc1/rack2、ports.httpは8080です。そのあと、/root/ist-expansion/we-typo.yamlにbilling-typoを書いて、アドレスを10.20.30 .41のように空白を入れて適用し、istioctl analyze -n expansion -o jsonの出力を/root/ist-expansion/analyze-address.jsonに保存してください。ラベルはapp: billing-brokenにします。
  5. /root/ist-expansion/se.yamlにServiceEntry billing-svcを書いて適用してください。hostsはbilling.expansion.internalの1つ、locationはMESH_INTERNAL、resolutionはSTATIC、ポートは番号8080で名前はhttp、プロトコルはHTTPで、workloadSelector.labelsはapp: billingです。
  6. 3つのServiceEntryファイルを作成して、サーバー側の試験適用でルールを確認してください。/root/ist-expansion/se-none-endpoints.yaml(resolution: NONEなのにendpointsがある)、/root/ist-expansion/se-roundrobin-two.yaml(resolution: DNS_ROUND_ROBINでendpointsが2つ)、/root/ist-expansion/se-roundrobin-one.yaml(resolution: DNS_ROUND_ROBINでendpointsが1つ)です。結果を/root/ist-expansion/resolution-rules.tsvに、<파일이름>\t<accepted|rejected>の形式で(プレースホルダーはファイル名です)上の順に書いて、拒否文は/root/ist-expansion/resolution-reject.txtに集めてください。3つのファイルとも、実際には適用しないでください。
  7. まずistio-systemネームスペースを作成して、istioctl manifest generate --set profile=minimalのレンダリングからConfigMap istioだけを取り出して/root/ist-expansion/istio-cm.yamlに保存してから適用してください。そのあと、expansionにConfigMap istio-ca-root-certを作成してください。キー名はroot-cert.pemで、値はopensslで作成した自己署名のルート証明書です(/root/ist-expansion/root-cert.pem)。最後に、istioctl x workload entry configure -f /root/ist-expansion/wg.yaml -o /root/ist-expansion/vmcfg --clusterID lab-clusterを実行して、設定一式を作成してください。
  8. /root/ist-expansion/we2.yamlに2台目のサーバーbilling-2を書いて適用してください。ラベルはapp: billing、アドレスは10.20.30.42、network: onprem、serviceAccount: billing-sa、locality: dc1/rack3、ports.httpは8080です。そのあと、/root/ist-expansion/se-match.shを作成して、expansionのServiceEntryのうち、workloadSelectorがあるものごとに、<ServiceEntry 이름>\t<잡힌 WorkloadEntry 수>\t<이름들 쉼표>の形式で(プレースホルダーはServiceEntryの名前と選ばれたWorkloadEntryの数と名前のカンマ区切りです)、名前順に標準出力にだけ出力するようにして、その出力を/root/ist-expansion/match-result.txtに保存してください。

参考

メッシュがそのサーバーを何と呼ぶかを先に決める

/root/ist-expansionとネームスペースexpansionを作成して、その中にServiceAccount billing-saを作成してください。そして、このサービスアカウントを使うワークロードがメッシュで受け取ることになる身元の文字列を、/root/ist-expansion/identity.txtに1行で書いてください。トラストドメインはデフォルト値のcluster.localです。

メッシュの身元は、IPやホスト名ではなく、サービスアカウントから得られます。形式はspiffe://<신뢰도메인>/ns/<네임스페이스>/sa/<서비스어카운트>です(プレースホルダーはトラストドメインとネームスペースとサービスアカウントです)。メッシュの外のサーバーも、結局はこの名札を受け取ってはじめて、内側に入れます。

VM1台ではなく、VMのグループの型を作る

/root/ist-expansion/wg.yamlにWorkloadGroup legacy-billingを書いて、expansionに適用してください。spec.metadata.labelsはapp: billing、spec.templateはserviceAccount: billing-sa、network: onprem、ports.http: 8080で、spec.probeはperiodSeconds: 5で、httpGetでポート8080の/healthzを見ます。

WorkloadGroupは、PodのDeploymentに相当する場所です。個々のサーバーではなく、そのグループが共通で持つラベル・身元・ネットワーク・ポート・ヘルスチェックの方法を書きます。network値は、そのサーバーがどのネットワークにあるのかを指し、あとでプロキシがその値で経路を選びます。

スキーマが拒否する2つのケースを、自分で受けてみる

/root/ist-expansion/wg-bad-probe.yamlにWorkloadGroup bad-probeを書いて、spec.probeにhttpGetとtcpSocketを両方入れてください。/root/ist-expansion/wg-no-template.yamlにはno-templateを書いて、spec.templateをまるごと抜いてください。どちらもサーバー側の試験適用だけを行って、拒否文を/root/ist-expansion/wg-reject.txtに順番に集めてください。

probeは、検査方法のうち1つだけを選ぶようになっています。スキーマのoneOf制約です。templateは、なければグループのデフォルト値がわからないので、必須です。拒否文がどのフィールドを指しているかを、読んでみてください。

サーバー1台を実際に登録して、打ち間違いがどこで検出されるかを見る

/root/ist-expansion/we.yamlにWorkloadEntry billing-1を書いて適用してください。メタデータのラベルはapp: billing、addressは10.20.30.41、networkはonprem、serviceAccountはbilling-sa、localityはdc1/rack2、ports.httpは8080です。そのあと、/root/ist-expansion/we-typo.yamlにbilling-typoを書いて、アドレスを10.20.30 .41のように空白を入れて適用し、istioctl analyze -n expansion -o jsonの出力を/root/ist-expansion/analyze-address.jsonに保存してください。ラベルはapp: billing-brokenにします。

WorkloadEntryは、グループの中のサーバー1台です。アドレスの形式はCRDスキーマが検査しないので、変な値も作成されます。そうしたものを検出してくれるのは、アナライザーです。どのコードで出力されるかを、確認してみてください。

登録したサーバーを、メッシュのサービス名に結び付ける

/root/ist-expansion/se.yamlにServiceEntry billing-svcを書いて適用してください。hostsはbilling.expansion.internalの1つ、locationはMESH_INTERNAL、resolutionはSTATIC、ポートは番号8080で名前はhttp、プロトコルはHTTPで、workloadSelector.labelsはapp: billingです。

WorkloadEntryだけを作っても、呼び出すための名前がありません。ServiceEntryがメッシュ内のサービス名を作り、workloadSelectorでその名前の背後に立つワークロードを選びます。locationがMESH_INTERNALなら、メッシュの構成員として扱われて、mTLSとポリシーが適用される対象になります。

resolutionごとに、endpointのルールが違う

3つのServiceEntryファイルを作成して、サーバー側の試験適用でルールを確認してください。/root/ist-expansion/se-none-endpoints.yaml(resolution: NONEなのにendpointsがある)、/root/ist-expansion/se-roundrobin-two.yaml(resolution: DNS_ROUND_ROBINでendpointsが2つ)、/root/ist-expansion/se-roundrobin-one.yaml(resolution: DNS_ROUND_ROBINでendpointsが1つ)です。結果を/root/ist-expansion/resolution-rules.tsvに、<파일이름>\t<accepted|rejected>の形式で(プレースホルダーはファイル名です)上の順に書いて、拒否文は/root/ist-expansion/resolution-reject.txtに集めてください。3つのファイルとも、実際には適用しないでください。

resolutionは、宛先をどう見つけるかを決めます。NONEは元の宛先IPをそのまま使い、STATICは書かれたendpointを、DNSは名前を解決して使います。そのため、方式ごとにendpointを何個書けるかが違います。このルールは、istioctlではなく、CRDの検証ルールが強制します。

そのサーバーが受け取る設定一式を、実際に作ってみる

まずistio-systemネームスペースを作成して、istioctl manifest generate --set profile=minimalのレンダリングからConfigMap istioだけを取り出して/root/ist-expansion/istio-cm.yamlに保存してから適用してください。そのあと、expansionにConfigMap istio-ca-root-certを作成してください。キー名はroot-cert.pemで、値はopensslで作成した自己署名のルート証明書です(/root/ist-expansion/root-cert.pem)。最後に、istioctl x workload entry configure -f /root/ist-expansion/wg.yaml -o /root/ist-expansion/vmcfg --clusterID lab-clusterを実行して、設定一式を作成してください。

VM側のプロキシが必要とするものは3つです。メッシュ設定(どこにつなぐか)、ルート証明書(誰を信頼するか)、トークン(自分が誰なのか)です。前の2つはクラスターのConfigMapから得られ、トークンは、このコマンドがサービスアカウントで直接発行します。発行されたトークンは寿命が短いものですが、画面に出力しないでください。

セレクターが実際に何を選ぶのかを数えて、レポートとして残す

/root/ist-expansion/we2.yamlに2台目のサーバーbilling-2を書いて適用してください。ラベルはapp: billing、アドレスは10.20.30.42、network: onprem、serviceAccount: billing-sa、locality: dc1/rack3、ports.httpは8080です。そのあと、/root/ist-expansion/se-match.shを作成して、expansionのServiceEntryのうち、workloadSelectorがあるものごとに、<ServiceEntry 이름>\t<잡힌 WorkloadEntry 수>\t<이름들 쉼표>の形式で(プレースホルダーはServiceEntryの名前と選ばれたWorkloadEntryの数と名前のカンマ区切りです)、名前順に標準出力にだけ出力するようにして、その出力を/root/ist-expansion/match-result.txtに保存してください。

ラベルセレクターは、kubectl get workloadentry -l app=billingのように、そのまま問い合わせられます。セレクターが複数のラベルなら、カンマでつなげます。選ばれたものがなければ、0とハイフンを出力するようにしておくと、あとでラベルがずれた日にすぐ見えます。