使用外部 HTTPS 代理
在配置出口网关示例中,展示了如何通过名为出口网关的 Istio 边缘组件,将流量从您的服务网格定向到外部服务。但是,某些情况下需要使用外部的遗留(非 Istio)HTTPS 代理来访问外部服务。例如,您的公司可能已经部署了这样的代理,并且组织内的所有应用程序可能都需要将其流量定向到该代理。
此示例展示了如何启用对外部 HTTPS 代理的访问。由于应用程序使用 HTTP CONNECT 方法与 HTTPS 代理建立连接,因此将流量配置到外部 HTTPS 代理与将流量配置到外部 HTTP 和 HTTPS 服务的方式不同。
开始之前
按照安装指南中的说明设置 Istio。
部署curl示例应用程序,用作发送请求的测试源。如果您启用了自动 Sidecar 注入,请运行以下命令部署示例应用程序
$ kubectl apply -f @samples/curl/curl.yaml@
否则,在使用以下命令部署
curl
应用程序之前,手动注入 Sidecar$ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@)
将
SOURCE_POD
环境变量设置为源 Pod 的名称$ export SOURCE_POD=$(kubectl get pod -l app=curl -o jsonpath={.items..metadata.name})
部署 HTTPS 代理
为了模拟遗留代理,并且仅限于此示例,您将在集群内部署一个 HTTPS 代理。此外,为了模拟在集群外部运行的更真实的代理,您将通过其 IP 地址而不是 Kubernetes 服务的域名来寻址代理的 Pod。此示例使用Squid,但您可以使用任何支持 HTTP CONNECT 的 HTTPS 代理。
为 HTTPS 代理创建一个命名空间,但不要为其标记 Sidecar 注入。没有标签,新的命名空间中将禁用 Sidecar 注入,因此 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
在
external
命名空间中部署curl示例,以测试到代理的流量,而无需 Istio 流量控制。$ kubectl apply -n external -f @samples/curl/curl.yaml@
获取代理 Pod 的 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
Pod 通过代理向外部服务发送请求$ 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 启用的 Pod 的流量以使用 HTTPS 代理。
将流量配置到外部 HTTPS 代理
为 HTTPS 代理定义一个 TCP(而非 HTTP!)服务条目。尽管应用程序使用 HTTP CONNECT 方法与 HTTPS 代理建立连接,但您必须为 TCP 流量而不是 HTTP 配置代理。连接建立后,代理仅充当 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
Pod 发送请求。由于curl
Pod 具有 Sidecar,因此 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 Sidecar 代理的日志以查看您的请求
$ 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 代理来模拟外部代理。
- 创建了一个 TCP 服务条目以启用 Istio 控制的流量到外部代理。
请注意,您不能为通过外部代理(如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