外部トラフィック向け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サンプルアプリをデプロイします。自動サイドカーインジェクションを有効にしている場合は、次のコマンドを実行してサンプルアプリをデプロイします。
$ kubectl apply -f @samples/curl/curl.yaml@
それ以外の場合は、次のコマンドを使用してサイドカーを手動で挿入してから、
curl
アプリケーションをデプロイします。$ 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サンプルを起動します。$ 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サービス
デフォルトの名前空間に、
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
サービスを観察します。クラスタIPがないことに注意してください。
$ kubectl get svc my-httpbin NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-httpbin ExternalName <none> httpbin.org 80/TCP 4s
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" } }
この例では、暗号化されていない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
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サービスを使用して外部サービスにアクセスする
セレクタのないWikipediaのKubernetesサービスを作成します。
$ kubectl apply -f - <<EOF kind: Service apiVersion: v1 metadata: name: my-wikipedia spec: ports: - protocol: TCP port: 443 name: tls EOF
サービスのエンドポイントを作成します。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
サービスを観察します。
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
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>
この場合、ワークロードは
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
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>
アクセスが実際にクラスタ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