外部トラフィック向けKubernetesサービス

KubernetesのExternalNameサービスと、エンドポイントを持つKubernetesサービスを使用すると、外部サービスへのローカルDNS *エイリアス*を作成できます。このDNSエイリアスは、ローカルサービスのDNSエントリと同じ形式を持ちます。つまり、`<サービス名>.<名前空間名>.svc.cluster.local`です。DNSエイリアスは、ワークロードに*場所の透過性*を提供します。ワークロードは、ローカルサービスと外部サービスを同じ方法で呼び出すことができます。ある時点で外部サービスをクラスタ内にデプロイすることにした場合、そのKubernetesサービスをローカルバージョンを参照するように更新するだけで済みます。ワークロードは変更なしで動作を続けます。

このタスクは、外部サービスへのアクセスのためのこれらのKubernetesメカニズムがIstioでも引き続き機能することを示しています。実行する必要がある唯一の設定手順は、Istioの相互TLS以外のTLSモードを使用することです。外部サービスはIstioサービスメッシュの一部ではないため、Istioの相互TLSを実行できません。外部サービスのTLS要件と、ワークロードが外部サービスにアクセスする方法に応じて、TLSモードを設定する必要があります。ワークロードがプレーンHTTPリクエストを発行し、外部サービスがTLSを要求する場合は、IstioによるTLS発信を実行することを検討してください。ワークロードが既にTLSを使用している場合、トラフィックは既に暗号化されているため、Istioの相互TLSを無効にするだけです。

このタスクの例ではHTTPプロトコルを使用していますが、外部トラフィックのKubernetesサービスは他のプロトコルでも機能します。

開始前に

  • インストールガイドの手順に従ってIstioをセットアップします。

  • リクエストを送信するためのテストソースとして使用するために、curlサンプルアプリをデプロイします。自動サイドカーインジェクションを有効にしている場合は、次のコマンドを実行してサンプルアプリをデプロイします。

    Zip
    $ kubectl apply -f samples/curl/curl.yaml

    それ以外の場合は、次のコマンドを使用してサイドカーを手動で挿入してから、curlアプリケーションをデプロイします。

    Zip
    $ kubectl apply -f <(istioctl kube-inject -f samples/curl/curl.yaml)
  • ソースポッドの名前を格納するために、SOURCE_POD環境変数を設定します。

    $ export SOURCE_POD=$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})
  • Istioの制御を受けないソースポッドの名前空間を作成します。

    $ kubectl create namespace without-istio
  • without-istio名前空間にcurlサンプルを起動します。

    Zip
    $ kubectl apply -f samples/curl/curl.yaml -n without-istio
  • リクエストを送信するには、ソースポッドの名前を格納するためにSOURCE_POD_WITHOUT_ISTIO環境変数を作成します。

    $ export SOURCE_POD_WITHOUT_ISTIO="$(kubectl get pod -n without-istio -l app=curl -o jsonpath={.items..metadata.name})"
  • Istioサイドカーが挿入されていないこと、つまりポッドにコンテナが1つしかないことを確認します。

    $ kubectl get pod "$SOURCE_POD_WITHOUT_ISTIO" -n without-istio
    NAME READY STATUS RESTARTS AGE curl-66c8d79ff5-8tqrl 1/1 Running 0 32s

外部サービスへのアクセスのためのKubernetes ExternalNameサービス

  1. デフォルトの名前空間に、httpbin.orgのKubernetes ExternalNameサービスを作成します。

    $ kubectl apply -f - <<EOF kind: Service apiVersion: v1 metadata: name: my-httpbin spec: type: ExternalName externalName: httpbin.org ports: - name: http protocol: TCP port: 80 EOF
  2. サービスを観察します。クラスタIPがないことに注意してください。

    $ kubectl get svc my-httpbin
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-httpbin ExternalName <none> httpbin.org 80/TCP 4s
  3. Istioサイドカーのないソースポッドから、Kubernetesサービスのホスト名を使用してhttpbin.orgにアクセスします。Kubernetesのサービスに関するDNS形式、つまり`<サービス名>.<名前空間>.svc.cluster.local`を使用していることに注意してください。

    $ kubectl exec "$SOURCE_POD_WITHOUT_ISTIO" -n without-istio -c curl -- curl -sS my-httpbin.default.svc.cluster.local/headers
    { "headers": { "Accept": "*/*", "Host": "my-httpbin.default.svc.cluster.local", "User-Agent": "curl/7.55.0" } }
  4. この例では、暗号化されていないHTTPリクエストがhttpbin.orgに送信されます。例のためだけに、TLSモードを無効にし、外部サービスへの暗号化されていないトラフィックを許可します。現実的なシナリオでは、Istioによる外部TLS発信を実行することをお勧めします。

    $ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: my-httpbin spec: host: my-httpbin.default.svc.cluster.local trafficPolicy: tls: mode: DISABLE EOF
  5. Istioサイドカーのあるソースポッドから、Kubernetesサービスのホスト名を使用してhttpbin.orgにアクセスします。Istioサイドカーによって追加されたヘッダー(例:X-Envoy-Peer-Metadata)に注意してください。また、Hostヘッダーがサービスのホスト名と等しいことにも注意してください。

    $ kubectl exec "$SOURCE_POD" -c curl -- curl -sS my-httpbin.default.svc.cluster.local/headers
    { "headers": { "Accept": "*/*", "Content-Length": "0", "Host": "my-httpbin.default.svc.cluster.local", "User-Agent": "curl/7.64.0", "X-B3-Sampled": "0", "X-B3-Spanid": "5795fab599dca0b8", "X-B3-Traceid": "5079ad3a4af418915795fab599dca0b8", "X-Envoy-Peer-Metadata": "...", "X-Envoy-Peer-Metadata-Id": "sidecar~10.28.1.74~curl-6bdb595bcb-drr45.default~default.svc.cluster.local" } }

Kubernetes ExternalNameサービスのクリーンアップ

$ kubectl delete destinationrule my-httpbin $ kubectl delete service my-httpbin

エンドポイントを持つKubernetesサービスを使用して外部サービスにアクセスする

  1. セレクタのないWikipediaのKubernetesサービスを作成します。

    $ kubectl apply -f - <<EOF kind: Service apiVersion: v1 metadata: name: my-wikipedia spec: ports: - protocol: TCP port: 443 name: tls EOF
  2. サービスのエンドポイントを作成します。WikipediaのIPアドレス範囲リストからいくつかのIPを選択します。

    $ kubectl apply -f - <<EOF kind: Endpoints apiVersion: v1 metadata: name: my-wikipedia subsets: - addresses: - ip: 198.35.26.96 - ip: 208.80.153.224 ports: - port: 443 name: tls EOF
  3. サービスを観察します。wikipedia.orgにアクセスするために使用できるクラスタIPがあることに注意してください。

    $ kubectl get svc my-wikipedia
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-wikipedia ClusterIP 172.21.156.230 <none> 443/TCP 21h
  4. Istioサイドカーのないソースポッドから、KubernetesサービスのクラスタIPを使用してwikipedia.orgにHTTPSリクエストを送信します。curl--resolveオプションを使用して、クラスタIPでwikipedia.orgにアクセスします。

    $ kubectl exec "$SOURCE_POD_WITHOUT_ISTIO" -n without-istio -c curl -- curl -sS --resolve en.wikipedia.org:443:"$(kubectl get service my-wikipedia -o jsonpath='{.spec.clusterIP}')" https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
    <title>Wikipedia, the free encyclopedia</title>
  5. この場合、ワークロードはwikipedia.orgにHTTPSリクエスト(オープンTLS接続)を送信します。トラフィックはワークロードによって既に暗号化されているため、Istioの相互TLSを安全に無効にすることができます。

    $ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: my-wikipedia spec: host: my-wikipedia.default.svc.cluster.local trafficPolicy: tls: mode: DISABLE EOF
  6. Istioサイドカーのあるソースポッドから、KubernetesサービスのクラスタIPを使用してwikipedia.orgにアクセスします。

    $ kubectl exec "$SOURCE_POD" -c curl -- curl -sS --resolve en.wikipedia.org:443:"$(kubectl get service my-wikipedia -o jsonpath='{.spec.clusterIP}')" https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
    <title>Wikipedia, the free encyclopedia</title>
  7. アクセスが実際にクラスタIPによって実行されていることを確認します。curl -vの出力に「Connected to en.wikipedia.org (172.21.156.230)」という文があることに注意してください。これは、サービスの出力にクラスタIPとして表示されたIPが言及されています。

    $ kubectl exec "$SOURCE_POD" -c curl -- curl -sS -v --resolve en.wikipedia.org:443:"$(kubectl get service my-wikipedia -o jsonpath='{.spec.clusterIP}')" https://en.wikipedia.org/wiki/Main_Page -o /dev/null
    * Added en.wikipedia.org:443:172.21.156.230 to DNS cache * Hostname en.wikipedia.org was found in DNS cache * Trying 172.21.156.230... * TCP_NODELAY set * Connected to en.wikipedia.org (172.21.156.230) port 443 (#0) ...

エンドポイントを持つKubernetesサービスのクリーンアップ

$ kubectl delete destinationrule my-wikipedia $ kubectl delete endpoints my-wikipedia $ kubectl delete service my-wikipedia

クリーンアップ

  1. curlサービスをシャットダウンします。

    Zip
    $ kubectl delete -f samples/curl/curl.yaml
  2. without-istio名前空間内のcurlサービスをシャットダウンします。

    Zip
    $ kubectl delete -f samples/curl/curl.yaml -n without-istio
  3. without-istio名前空間を削除します。

    $ kubectl delete namespace without-istio
  4. 環境変数をアンセットします。

    $ unset SOURCE_POD SOURCE_POD_WITHOUT_ISTIO
この情報は役に立ちましたか?
改善のための提案はありますか?

ご意見ありがとうございます!