外部HTTPSプロキシの使用
エグレスゲートウェイの構成に関する例はこちら。これは、エグレスゲートウェイと呼ばれるIstioエッジコンポーネントを介して、メッシュから外部サービスへのトラフィックを転送する方法を示しています。ただし、外部サービスにアクセスするために、外部のレガシー(非Istio)HTTPSプロキシが必要となる場合があります。たとえば、企業が既にそのようなプロキシを導入しており、組織内のすべてのアプリケーションがそのプロキシを介してトラフィックを転送する必要がある場合などです。
この例では、外部HTTPSプロキシへのアクセスを有効にする方法を示します。アプリケーションはHTTP CONNECTメソッドを使用してHTTPSプロキシとの接続を確立するため、外部HTTPSプロキシへのトラフィックの構成は、外部HTTPおよびHTTPSサービスへのトラフィックの構成とは異なります。
始める前に
インストールガイドの手順に従って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})
HTTPSプロキシのデプロイ
レガシープロキシをシミュレートするため、そしてこの例のためだけに、クラスタ内にHTTPSプロキシをデプロイします。また、クラスタの外で実行されているより現実的なプロキシをシミュレートするために、プロキシのポッドにはKubernetesサービスのドメイン名ではなく、IPアドレスでアクセスします。この例ではSquidを使用していますが、HTTP CONNECTをサポートするHTTPSプロキシであれば何でも使用できます。
サイドカーインジェクションのためのラベル付けを行わずに、HTTPSプロキシ用の名前空間を作成します。ラベルがないと、新しい名前空間ではサイドカーインジェクションが無効になり、Istioはその名前空間内のトラフィックを制御しません。プロキシがクラスタの外にあることをシミュレートするには、この動作が必要です。
$ kubectl create namespace external
Squidプロキシの設定ファイルを作成します。
$ cat <<EOF > ./proxy.conf http_port 3128 acl SSL_ports port 443 acl CONNECT method CONNECT http_access deny CONNECT !SSL_ports http_access allow localhost manager http_access deny manager http_access allow all coredump_dir /var/spool/squid EOF
プロキシの設定を保持するためのKubernetes ConfigMapを作成します。
$ kubectl create configmap proxy-configmap -n external --from-file=squid.conf=./proxy.conf
Squidを含むコンテナをデプロイします。
$ kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: squid namespace: external spec: replicas: 1 selector: matchLabels: app: squid template: metadata: labels: app: squid spec: volumes: - name: proxy-config configMap: name: proxy-configmap containers: - name: squid image: sameersbn/squid:3.5.27 imagePullPolicy: IfNotPresent volumeMounts: - name: proxy-config mountPath: /etc/squid readOnly: true EOF
Istioトラフィック制御なしでプロキシへのトラフィックをテストするために、
external
名前空間にcurlサンプルをデプロイします。$ kubectl apply -n external -f @samples/curl/curl.yaml@
プロキシポッドのIPアドレスを取得し、それを格納するために
PROXY_IP
環境変数を定義します。$ export PROXY_IP="$(kubectl get pod -n external -l app=squid -o jsonpath={.items..podIP})"
プロキシのポートを格納するために
PROXY_PORT
環境変数を定義します。この場合、Squidはポート3128を使用します。$ export PROXY_PORT=3128
external
名前空間内のcurl
ポッドから、プロキシ経由で外部サービスへのリクエストを送信します。$ kubectl exec "$(kubectl get pod -n external -l app=curl -o jsonpath={.items..metadata.name})" -n external -- sh -c "HTTPS_PROXY=$PROXY_IP:$PROXY_PORT curl https://en.wikipedia.org/wiki/Main_Page" | grep -o "<title>.*</title>" <title>Wikipedia, the free encyclopedia</title>
プロキシのアクセスログでリクエストを確認します。
$ kubectl exec "$(kubectl get pod -n external -l app=squid -o jsonpath={.items..metadata.name})" -n external -- tail /var/log/squid/access.log 1544160065.248 228 172.30.109.89 TCP_TUNNEL/200 87633 CONNECT en.wikipedia.org:443 - HIER_DIRECT/91.198.174.192 -
これまでの作業は、Istioを使用せずに完了しました。
- HTTPSプロキシをデプロイしました。
curl
を使用して、プロキシ経由で外部サービスwikipedia.org
にアクセスしました。
次に、Istio対応ポッドからのトラフィックがHTTPSプロキシを使用するように設定する必要があります。
外部HTTPSプロキシへのトラフィックの構成
HTTPSプロキシ用のTCP(HTTPではない!)サービスエントリを定義します。アプリケーションはHTTPSプロキシとの接続確立にHTTP CONNECTメソッドを使用しますが、プロキシはHTTPではなくTCPトラフィック用に設定する必要があります。接続が確立されると、プロキシは単にTCPトンネルとして機能します。
$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: proxy spec: hosts: - my-company-proxy.com # ignored addresses: - $PROXY_IP/32 ports: - number: $PROXY_PORT name: tcp protocol: TCP location: MESH_EXTERNAL resolution: NONE EOF
default
名前空間内のcurl
ポッドからリクエストを送信します。curl
ポッドにはサイドカーがあるため、Istioがトラフィックを制御します。$ kubectl exec "$SOURCE_POD" -c curl -- sh -c "HTTPS_PROXY=$PROXY_IP:$PROXY_PORT curl https://en.wikipedia.org/wiki/Main_Page" | grep -o "<title>.*</title>" <title>Wikipedia, the free encyclopedia</title>
Istioサイドカープロキシのログでリクエストを確認します。
$ kubectl logs "$SOURCE_POD" -c istio-proxy [2018-12-07T10:38:02.841Z] "- - -" 0 - 702 87599 92 - "-" "-" "-" "-" "172.30.109.95:3128" outbound|3128||my-company-proxy.com 172.30.230.52:44478 172.30.109.95:3128 172.30.230.52:44476 -
プロキシのアクセスログでリクエストを確認します。
$ kubectl exec "$(kubectl get pod -n external -l app=squid -o jsonpath={.items..metadata.name})" -n external -- tail /var/log/squid/access.log 1544160065.248 228 172.30.109.89 TCP_TUNNEL/200 87633 CONNECT en.wikipedia.org:443 - HIER_DIRECT/91.198.174.192 -
発生した状況の理解
この例では、次の手順を実行しました。
- 外部プロキシをシミュレートするためにHTTPSプロキシをデプロイしました。
- Istio制御トラフィックを外部プロキシに有効にするためにTCPサービスエントリを作成しました。
wikipedia.org
など、外部プロキシ経由でアクセスする外部サービスに対してサービスエントリを作成してはならないことに注意してください。これは、Istioの観点からはリクエストが外部プロキシのみに送信されるためです。Istioは、外部プロキシがリクエストをさらに転送するという事実を認識していません。
クリーンアップ
curlサービスをシャットダウンします。
$ kubectl delete -f @samples/curl/curl.yaml@
external
名前空間内のcurlサービスをシャットダウンします。$ kubectl delete -f @samples/curl/curl.yaml@ -n external
Squidプロキシをシャットダウンし、
ConfigMap
と設定ファイルを削除します。$ kubectl delete -n external deployment squid $ kubectl delete -n external configmap proxy-configmap $ rm ./proxy.conf
external
名前空間を削除します。$ kubectl delete namespace external
サービスエントリを削除します。
$ kubectl delete serviceentry proxy