ワイルドカードホストを使用したエグレス
外部サービスへのアクセス タスクと イグレスゲートウェイの設定 の例では、edition.cnn.com
のような特定のホスト名に対するイグレストラフィックの設定方法について説明しています。この例では、各ホストを個別に設定する代わりに、共通ドメイン内のホストのセット(例:*.wikipedia.org
)に対するイグレストラフィックを有効にする方法を示します。
背景
Istioで、すべての言語のwikipedia.org
サイトに対するイグレストラフィックを有効にしたいとします。特定の言語のwikipedia.org
の各バージョンには、それぞれ独自のホスト名があります(例:英語ではen.wikipedia.org
、ドイツ語ではde.wikipedia.org
)。各言語のサイトを個別に指定することなく、すべてのWikipediaサイトに対して共通の設定項目でイグレストラフィックを有効にしたいと考えています。
始める前に
- アクセスログが有効になっており、デフォルトでブロックするアウトバウンドトラフィックポリシーが適用されている状態でIstioをインストールします。
$ istioctl install --set profile=demo --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
$ istioctl install --set profile=minimal -y \
--set values.pilot.env.PILOT_ENABLE_ALPHA_GATEWAY_API=true \
--set meshConfig.accessLogFile=/dev/stdout \
--set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
リクエストを送信するためのテストソースとして使用する、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})
ワイルドカードホストへのダイレクトトラフィックの設定
共通ドメイン内のホストのセットにアクセスする最初の、そして最も簡単な方法は、ワイルドカードホストを持つ単純なServiceEntry
を設定し、サイドカーから直接サービスを呼び出すことです。サービスを直接呼び出す場合(つまり、イグレスゲートウェイを介さない場合)、ワイルドカードホストの設定は他の(例:完全修飾)ホストの設定と変わりません。共通ドメイン内に多くのホストがある場合にのみ、はるかに便利です。
*.wikipedia.org
に対するServiceEntry
を定義します。$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: wikipedia spec: hosts: - "*.wikipedia.org" ports: - number: 443 name: https protocol: HTTPS EOF
https://en.wikipedia.orgとhttps://de.wikipedia.orgにHTTPSリクエストを送信します。
$ kubectl exec "$SOURCE_POD" -c curl -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"' <title>Wikipedia, the free encyclopedia</title> <title>Wikipedia – Die freie Enzyklopädie</title>
ワイルドカードホストへのダイレクトトラフィックのクリーンアップ
$ kubectl delete serviceentry wikipedia
ワイルドカードホストへのイグレスゲートウェイトラフィックの設定
すべてのワイルドカードホストが単一のサーバーによって提供される場合、ワイルドカードホストへのイグレスゲートウェイベースのアクセスの設定は、ほとんどのホストの設定と非常に似ています。ただし、1つの例外があります。構成されたルートの宛先は、構成されたホスト(つまり、ワイルドカード)と同じではありません。代わりに、ドメインのセットの単一サーバーのホストを使用して構成されます。
- *.wikipedia.orgに対するイグレス
Gateway
と、トラフィックをイグレスゲートウェイ経由で、そしてイグレスゲートウェイから外部サービスに転送するルートルールを作成します。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*.wikipedia.org"
tls:
mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: egressgateway-for-wikipedia
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: wikipedia
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: direct-wikipedia-through-egress-gateway
spec:
hosts:
- "*.wikipedia.org"
gateways:
- mesh
- istio-egressgateway
tls:
- match:
- gateways:
- mesh
port: 443
sniHosts:
- "*.wikipedia.org"
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: wikipedia
port:
number: 443
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 443
sniHosts:
- "*.wikipedia.org"
route:
- destination:
host: www.wikipedia.org
port:
number: 443
weight: 100
EOF
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: wikipedia-egress-gateway
annotations:
networking.istio.io/service-type: ClusterIP
spec:
gatewayClassName: istio
listeners:
- name: tls
hostname: "*.wikipedia.org"
port: 443
protocol: TLS
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: direct-wikipedia-to-egress-gateway
spec:
parentRefs:
- kind: ServiceEntry
group: networking.istio.io
name: wikipedia
rules:
- backendRefs:
- name: wikipedia-egress-gateway-istio
port: 443
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: forward-wikipedia-from-egress-gateway
spec:
parentRefs:
- name: wikipedia-egress-gateway
hostnames:
- "*.wikipedia.org"
rules:
- backendRefs:
- kind: Hostname
group: networking.istio.io
name: www.wikipedia.org
port: 443
---
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: wikipedia
spec:
hosts:
- "*.wikipedia.org"
ports:
- number: 443
name: https
protocol: HTTPS
EOF
宛先サーバーwww.wikipedia.orgに対する
ServiceEntry
を作成します。$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: www-wikipedia spec: hosts: - www.wikipedia.org ports: - number: 443 name: https protocol: HTTPS resolution: DNS EOF
https://en.wikipedia.orgとhttps://de.wikipedia.orgにHTTPSリクエストを送信します。
$ kubectl exec "$SOURCE_POD" -c curl -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"' <title>Wikipedia, the free encyclopedia</title> <title>Wikipedia – Die freie Enzyklopädie</title>
*.wikipedia.orgへのリクエストに対応するカウンターについて、イグレスゲートウェイのプロキシの統計を確認します。
$ kubectl exec "$(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}')" -c istio-proxy -n istio-system -- pilot-agent request GET clusters | grep '^outbound|443||www.wikipedia.org.*cx_total:'
outbound|443||www.wikipedia.org::208.80.154.224:443::cx_total::2
$ kubectl exec "$(kubectl get pod -l gateway.networking.k8s.io/gateway-name=wikipedia-egress-gateway -o jsonpath='{.items[0].metadata.name}')" -c istio-proxy -- pilot-agent request GET clusters | grep '^outbound|443||www.wikipedia.org.*cx_total:'
outbound|443||www.wikipedia.org::208.80.154.224:443::cx_total::2
ワイルドカードホストへのイグレスゲートウェイトラフィックのクリーンアップ
$ kubectl delete serviceentry www-wikipedia
$ kubectl delete gateway istio-egressgateway
$ kubectl delete virtualservice direct-wikipedia-through-egress-gateway
$ kubectl delete destinationrule egressgateway-for-wikipedia
$ kubectl delete se wikipedia
$ kubectl delete se www-wikipedia
$ kubectl delete gtw wikipedia-egress-gateway
$ kubectl delete tlsroute direct-wikipedia-to-egress-gateway
$ kubectl delete tlsroute forward-wikipedia-from-egress-gateway
任意のドメインに対するワイルドカード設定
前のセクションの設定は、すべての*.wikipedia.org
サイトがwikipedia.org
サーバーのいずれかによって提供されるため機能しました。しかし、これは常に当てはまるわけではありません。たとえば、*.com
や*.org
のようなより一般的なワイルドカードドメインへのアクセスに対してイグレス制御を設定したい場合があります。任意のワイルドカードドメインへのトラフィックの設定は、Istioゲートウェイにとって課題となります。Istioゲートウェイは、事前に定義されたホスト、事前に定義されたIPアドレス、またはリクエストの元の宛先IPアドレスへのトラフィックのルーティングのみを構成できます。
前のセクションでは、仮想サービスを構成してトラフィックを事前に定義されたホストwww.wikipedia.org
に転送するように設定しました。しかし、一般的なケースでは、リクエストで受信した任意のホストを提供できるホストまたはIPアドレスがわからないため、リクエストをルーティングするための値としてリクエストの元の宛先アドレスだけが残ります。残念ながら、イグレスゲートウェイを使用する場合、元の要求がゲートウェイにリダイレクトされるため、リクエストの元の宛先アドレスは失われ、宛先IPアドレスはゲートウェイのIPアドレスになります。
Istioの実装の詳細に依存するため、簡単ではなく、やや脆弱ではありますが、Envoyフィルターを使用して、HTTPSまたはTLSリクエストのSNI値を使用して、リクエストをルーティングする元の宛先を識別することで、ゲートウェイが任意のドメインをサポートするように構成できます。この構成アプローチの例は、ワイルドカード宛先へのイグレストラフィックのルーティングにあります。
クリーンアップ
curlサービスをシャットダウンします。
$ kubectl delete -f @samples/curl/curl.yaml@
クラスタからIstioをアンインストールします。
$ istioctl uninstall --purge -y