通过 HTTPS 进行双向 TLS

这个任务展示了 Istio 双向 TLS 是如何与 HTTPS 服务一起工作的。它包括:

  • 在没有 Istio sidecar 的情况下部署 HTTPS 服务

  • 关闭 Istio 双向 TLS 认证情况下部署 HTTPS 服务

  • 部署一个启动双向 TLS 的 HTTPS 服务。对于每个部署,请连接到此服务并验证其是否有效。

当 Istio sidecar 使用 HTTPS 服务部署时,代理将自动从 L7 降至 L4(无论是否启用了双向 TLS),这就意味着它不会终止原来的 HTTPS 通信。这就是为什么 Istio 可以在 HTTPS 服务上工作。

开始之前

按照下面的快速开始设置 Istio。注意,在安装步骤第5步中,身份验证应该被禁用

生成证书和 configmap

您需要安装 openssl 来运行以下命令:

  1. $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/nginx.key -out /tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
  2. $ kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
  3. secret "nginxsecret" created

创建用于 HTTPS 服务的 configmap

  1. $ kubectl create configmap nginxconfigmap --from-file=samples/https/default.conf
  2. configmap "nginxconfigmap" created

在没有 Istio sidecar 的情况下部署 HTTPS 服务

本节将创建一个基于 nginx 的 HTTPS 服务。

Zip

  1. $ kubectl apply -f @samples/https/nginx-app.yaml@
  2. service "my-nginx" created
  3. replicationcontroller "my-nginx" created

然后,创建另一个 pod 来调用这个服务。

Zip

  1. $ kubectl apply -f <(bin/istioctl kube-inject -f @samples/sleep/sleep.yaml@)

获取 pods

  1. $ kubectl get pod
  2. NAME READY STATUS RESTARTS AGE
  3. my-nginx-jwwck 1/1 Running 0 1h
  4. sleep-847544bbfc-d27jg 2/2 Running 0 18h

SSH 进入包含 sleep pod 的 istio-proxy 容器。

  1. $ kubectl exec -it $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy /bin/bash

调用 my-nginx

  1. $ curl https://my-nginx -k
  2. ...
  3. <h1>Welcome to nginx!</h1>
  4. ...

你可以把上面的三个命令合并成一个:

  1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
  2. ...
  3. <h1>Welcome to nginx!</h1>
  4. ...

使用 Istio sidecar 和禁用双向 TLS 创建 HTTPS 服务

在”开始之前”部分中,Istio 控制平面被部署在双向 TLS 禁用的情况下。所以您只需要使用 sidecar 重新部署 NGINX HTTPS 服务。

删除这个 HTTPS 服务

Zip

  1. $ kubectl delete -f @samples/https/nginx-app.yaml@

用一个 sidecar 来部署它

Zip

  1. $ kubectl apply -f <(bin/istioctl kube-inject -f @samples/https/nginx-app.yaml@)

确保这个 pod 已经启动并运行

  1. $ kubectl get pod
  2. NAME READY STATUS RESTARTS AGE
  3. my-nginx-6svcc 2/2 Running 0 1h
  4. sleep-847544bbfc-d27jg 2/2 Running 0 18h

运行

  1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl https://my-nginx -k
  2. ...
  3. <h1>Welcome to nginx!</h1>
  4. ...

如果从 istio-proxy 容器运行,它也应该正常运行

  1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
  2. ...
  3. <h1>Welcome to nginx!</h1>
  4. ...

用 Istio sidecar 创建一个 HTTPS 服务,并使用双向 TLS

您需要使用启用了双向 TLS 的 Istio 控制平面。如果您已经安装了 Istio 控制平面,并安装了双向 TLS,请删除它:

  1. $ kubectl delete -f install/kubernetes/istio-demo.yaml

等待一切都完成了,也就是说在控制平面名称空间(istio-system)中没有 pod。

  1. $ kubectl get pod -n istio-system
  2. No resources found.

然后,部署启用了双向 TLS 的 Istio 控制平面:

  1. $ kubectl apply -f install/kubernetes/istio-demo-auth.yaml

确保一切正常运转:

  1. $ kubectl get po -n istio-system
  2. NAME READY STATUS RESTARTS AGE
  3. grafana-6f6dff9986-r6xnq 1/1 Running 0 23h
  4. istio-citadel-599f7cbd46-85mtq 1/1 Running 0 1h
  5. istio-cleanup-old-ca-mcq94 0/1 Completed 0 23h
  6. istio-egressgateway-78dd788b6d-jfcq5 1/1 Running 0 23h
  7. istio-ingressgateway-7dd84b68d6-dxf28 1/1 Running 0 23h
  8. istio-mixer-post-install-g8n9d 0/1 Completed 0 23h
  9. istio-pilot-d5bbc5c59-6lws4 2/2 Running 0 23h
  10. istio-policy-64595c6fff-svs6v 2/2 Running 0 23h
  11. istio-sidecar-injector-645c89bc64-h2dnx 1/1 Running 0 23h
  12. istio-statsd-prom-bridge-949999c4c-mv8qt 1/1 Running 0 23h
  13. istio-telemetry-cfb674b6c-rgdhb 2/2 Running 0 23h
  14. istio-tracing-754cdfd695-wqwr4 1/1 Running 0 23h
  15. prometheus-86cb6dd77c-ntw88 1/1 Running 0 23h

然后重新部署 HTTPS 服务和 sleep 服务

ZipZipZipZip

  1. $ kubectl delete -f <(bin/istioctl kube-inject -f @samples/sleep/sleep.yaml@)
  2. $ kubectl apply -f <(bin/istioctl kube-inject -f @samples/sleep/sleep.yaml@)
  3. $ kubectl delete -f <(bin/istioctl kube-inject -f @samples/https/nginx-app.yaml@)
  4. $ kubectl apply -f <(bin/istioctl kube-inject -f @samples/https/nginx-app.yaml@)

确保 pod 已启动并正在运行

  1. $ kubectl get pod
  2. NAME READY STATUS RESTARTS AGE
  3. my-nginx-9dvet 2/2 Running 0 1h
  4. sleep-77f457bfdd-hdknx 2/2 Running 0 18h

运行

  1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl https://my-nginx -k
  2. ...
  3. <h1>Welcome to nginx!</h1>
  4. ...

因为工作流”sleep –> sleep-proxy –> nginx-proxy –> nginx”,整个过程是7层流量,在 sleep-proxy 和 nginx-proxy 之间有一个 L4 双向 TLS 加密。在这种情况下,一切都很好。

但是,如果您从 istio-proxy 容器运行这个命令,它将无法工作。

  1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
  2. curl: (35) gnutls_handshake() failed: Handshake failed
  3. command terminated with exit code 35

原因是对于工作流”sleep-proxy –> nginx-proxy –> nginx”,nginx-proxy 可以从 sleep-proxy 中获得双向的 TLS 流量。在上面的命令中,sleep-proxy 不提供客户端证书,因此它不会起作用。此外,即使是 sleep-proxy 可以在上面的命令中提供客户端证书,它也不会工作,因为流量会从 nginx-proxy 降级到 nginx。

清除

ZipZip

  1. $ kubectl delete -f @samples/sleep/sleep.yaml@
  2. $ kubectl delete -f @samples/https/nginx-app.yaml@
  3. $ kubectl delete configmap nginxconfigmap
  4. $ kubectl delete secret nginxsecret