这个task展示Istio Mutual TLS如何同HTTPS服务一起工作。它包括:
- 部署一个没有Istio sidecar的HTTPS服务。
- 部署一个不开启互相TLS认证的Istio HTTPS服务
- 部署一个开启互相TLS认证的HTTPS服务。对每个部署,连接此服务并验证它是否工作。
当Istio sidecar采用HTTPS服务部署时,代理自动从L7降级为L4(无论是否启用互相TLS),这意味着它不会终止原始HTTPS流量。这就是Istio可以使用HTTPS服务的原因。
Before you begin
按照 quick start 的步骤安装Istio。注意在第五步禁用身份验证。
Generate certificates and configmap
你需要运行这个命令安装openssl:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/nginx.key -out /tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx" kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
secret “nginxsecret” created
为HTTPS服务创建一个configmap:
kubectl create configmap nginxconfigmap --from-file=samples/https/default.conf
configmap “nginxconfigmap” created
Deploy an HTTPS service without Istio sidecar
本节创建一个基于nginx的HTTPS服务。
kubectl apply -f samples/https/nginx-app.yaml
service “my-nginx” created
replicationcontroller “my-nginx” created
然后创建另一个pod调用这个服务。
kubectl apply -f <(bin/istioctl kube-inject -f samples/sleep/sleep.yaml)
查看以下pods
kubectl get pod
NAME READY STATUS RESTARTS AGE my-nginx-jwwck 1/1 Running 0 1h sleep-847544bbfc-d27jg 2/2 Running 0 18h
将ssh放入sleep的pod的istio代理容器中。
kubectl exec -it $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy /bin/bash
调用my-nginx
curl https://my-nginx -k
... <h1>Welcome to nginx!</h1> ...
实际上你可以将上述三个命令合并为一个:
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
... <h1>Welcome to nginx!</h1> ...
Create an HTTPS service with the Istio sidecar and mutual TLS disabled
在“Before you begin” 那节,Istio控制平面在禁用相互TLS的情况下进行部署。所以你只需要用sidecar重新部署nginx HTTPS服务。
删除HTTPS服务。
kubectl delete -f samples/https/nginx-app.yaml
带有sidecar部署
kubectl apply -f <(bin/istioctl kube-inject -f samples/https/nginx-app.yaml)
确认pod启动并运行
kubectl get pod
NAME READY STATUS RESTARTS AGE my-nginx-6svcc 2/2 Running 0 1h sleep-847544bbfc-d27jg 2/2 Running 0 18h
并运行
kubectl exec sleep-847544bbfc-d27jg -c sleep -- curl https://my-nginx -k
... <h1>Welcome to nginx!</h1> ...
如果你从istio-proxy容器运行,它应该也可以工作
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
... <h1>Welcome to nginx!</h1> ...
这个示例可以在 kubernetes examples 中查看。
Create an HTTPS service with Istio sidecar with mutual TLS enabled
你需要启动互相TLS的情况下部署istio控制平面。如果你安装了禁用互相TLS的istio控制平面,请删除它:
kubectl delete -f install/kubernetes/istio.yaml
等到所有停止,即,控制层命名空间(istio-system)没有pod。
kubectl get pod -n istio-system
No resources found.
然后部署启用互相TLS认证的istio控制平面:
kubectl apply -f install/kubernetes/istio-demo-auth.yaml
确保所有都启动并运行:
kubectl get po -n istio-system
NAME READY STATUS RESTARTS AGE grafana-6f6dff9986-r6xnq 1/1 Running 0 23h istio-citadel-599f7cbd46-85mtq 1/1 Running 0 1h istio-cleanup-old-ca-mcq94 0/1 Completed 0 23h istio-egressgateway-78dd788b6d-jfcq5 1/1 Running 0 23h istio-ingressgateway-7dd84b68d6-dxf28 1/1 Running 0 23h istio-mixer-post-install-g8n9d 0/1 Completed 0 23h istio-pilot-d5bbc5c59-6lws4 2/2 Running 0 23h istio-policy-64595c6fff-svs6v 2/2 Running 0 23h istio-sidecar-injector-645c89bc64-h2dnx 1/1 Running 0 23h istio-statsd-prom-bridge-949999c4c-mv8qt 1/1 Running 0 23h istio-telemetry-cfb674b6c-rgdhb 2/2 Running 0 23h istio-tracing-754cdfd695-wqwr4 1/1 Running 0 23h prometheus-86cb6dd77c-ntw88 1/1 Running 0 23h servicegraph-5849b7d696-jrk8h 1/1 Running 0 23h
然后重新部署HTTPS服务和sleep服务
kubectl delete -f <(bin/istioctl kube-inject -f samples/sleep/sleep.yaml) kubectl apply -f <(bin/istioctl kube-inject -f samples/sleep/sleep.yaml) kubectl delete -f <(bin/istioctl kube-inject -f samples/https/nginx-app.yaml) kubectl apply -f <(bin/istioctl kube-inject -f samples/https/nginx-app.yaml)
确认pod启动并运行
kubectl get pod
NAME READY STATUS RESTARTS AGE my-nginx-9dvet 2/2 Running 0 1h sleep-77f457bfdd-hdknx 2/2 Running 0 18h
运行
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl https://my-nginx -k
... <h1>Welcome to nginx!</h1> ...
原因在于对于工作流“sleep -> sleep-proxy -> nginx-proxy -> nginx”,整个工作流是L7流量,而在sleep-proxy和nginx-proxy之间存在L4互相TLS加密。在这种情况下,一切都工作的很好。
但,如果你从istio-proxy容器运行这个命令,它将不再工作
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
curl: (35) gnutls_handshake() failed: Handshake failed
command terminated with exit code 35
原因在于工作流“sleep-proxy -> nginx-proxy -> nginx”,nginx-proxy期望从sleep-proxy获取相互TLS的流量。上面的命令中,sleep-proxy不提供客户端证书。因此,它不会工作。此外,即使sleep-proxy提供上述命令的客户端证书,它也不会工作,因为从nginx到nginx-proxy的流量将降级到http。
Cleanup
kubectl delete -f samples/sleep/sleep.yaml kubectl delete -f samples/https/nginx-app.yaml kubectl delete configmap nginxconfigmap kubectl delete secret nginxsecret