Egress 网关 TLS 连接 发起的过程 (SDS)
TLS 所需的私钥、服务器证书和 root 证书是通过以下方式配置的Secret Discovery Service (SDS).
按照安装指南中的说明设置 Istio。
启动样例这将被用作外部调用的测试源。
如果您已经启用了自动 Sidecar 注入,请执行
否则,您必须在部署”sleep”应用程序之前手动注入 Sidecar。
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)
注意,任何您可以
exec
和curl
的 Pod 都可以。对于macOS用户,请确认您使用的是1.1或更高版本的
openssl
。$ openssl version -a | grep OpenSSL OpenSSL 1.1.1g 2020年4月21日
如果前面的命令输出的是”1.1”或更高版本,如图所示,您的”openssl”命令应该可以按照本任务的说明正常工作。否则,请升级您的
openssl
或尝试不同的openssl
实现,例如在 Linux 机器上。
如果您使用基于文件挂载的方法配置了一个egress网关。 而您想把您的 Egress 网关迁移到使用SDS方法,则不需要额外的步骤。
本节描述了如何执行TLS 连接流量 Egress 的例子。只是这次使用了一个 Egress 网关。请注意,在这种情况下,TLS初始化将由 Egress 网关完成。是由 Egress 网关完成的,而不是前一个例子中的挎包。Egress 网关将使用 SDS 而不是文件挂载来提供客户证书。
对于这项任务,您可以使用您喜欢的工具来生成证书和钥匙。下面的命令使用openssl.
创建一个根证书和私钥,为您的服务签署证书:
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
为
my-nginx.mesh-external.svc.cluster.local
创建一个证书和私钥:$ openssl req -out my-nginx.mesh-external.svc.cluster.local.csr -newkey rsa:2048 -nodes -keyout my-nginx.mesh-external.svc.cluster.local.key -subj "/CN=my-nginx.mesh-external.svc.cluster.local/O=some organization" $ openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in my-nginx.mesh-external.svc.cluster.local.csr -out my-nginx.mesh-external.svc.cluster.local.crt
部署一个简单的 TLS 服务器
为了模拟一个支持简单 TLS 协议的实际外部服务。在您的Kubernetes集群中部署一个NGINX服务器,但在 Istio 服务网外运行,即在没有启用 Istio sidecar 代理注入的命名空间中。
创建一个命名空间来代表 Istio 网状结构之外的服务,即
mesh-external
。请注意,Sidecar 代理将不会被自动注入到这个命名空间的 Pod 中,因为自动注入 Sidecar 的功能没有被 上。$ kubectl create namespace mesh-external
创建 Kubernetes Secrets来保存服务器的和 CA 的证书。
$ kubectl create -n mesh-external secret tls nginx-server-certs --key my-nginx.mesh-external.svc.cluster.local.key --cert my-nginx.mesh-external.svc.cluster.local.crt $ kubectl create -n mesh-external secret generic nginx-ca-certs --from-file=example.com.crt
为 NGINX 服务器创建一个配置文件:
$ cat <<\EOF > ./nginx.conf events { } http { log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; server { listen 443 ssl; root /usr/share/nginx/html; index index.html; server_name my-nginx.mesh-external.svc.cluster.local; ssl_certificate /etc/nginx-server-certs/tls.crt; ssl_certificate_key /etc/nginx-server-certs/tls.key; ssl_client_certificate /etc/nginx-ca-certs/example.com.crt; ssl_verify_client off; # In simple TLS, server doesn't verify client's certificate } } EOF
创建一个 Kubernetes 来保存 NGINX 服务器的配置。
$ kubectl create configmap nginx-configmap -n mesh-external --from-file=nginx.conf=./nginx.conf
部署 NGINX 服务器:
创建一个 Kubernetes Secret 来保存 Egress 网关用来发起 TLS 连接的CA证书。
$ kubectl create secret generic client-credential-cacert --from-file=ca.crt=example.com.crt -n istio-system
请注意,Istio 的纯 CA 证书的 Secret 名称必须以
-cacert
结尾,并且秘密必须在与 Istio 相同的命名空间中创建。Secret 必须与 Istio 部署的命名空间相同,本例中为 “istio-system”。为
my-nginx.mesh-external.svc.cluster.local
创建一个 Egressgateway
,端口443,以及目标规则和虚拟服务,以引导流量通过 Egress 网关并从 Egress 网关到外部服务$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: istio-egressgateway spec: selector: istio: egressgateway servers: - port: number: 443 name: https protocol: HTTPS hosts: - my-nginx.mesh-external.svc.cluster.local tls: mode: ISTIO_MUTUAL --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: egressgateway-for-nginx spec: host: istio-egressgateway.istio-system.svc.cluster.local subsets: - name: nginx trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: ISTIO_MUTUAL sni: my-nginx.mesh-external.svc.cluster.local EOF
定义一个来引导流量通过 Egress 网关:
$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: direct-nginx-through-egress-gateway spec: hosts: - my-nginx.mesh-external.svc.cluster.local gateways: - istio-egressgateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-system.svc.cluster.local subset: nginx port: number: 443 weight: 100 - match: - gateways: - istio-egressgateway port: 443 route: - destination: host: my-nginx.mesh-external.svc.cluster.local port: number: 443 weight: 100 EOF
添加一个
DestinationRule
来执行一个简单的 TLS 连接$ kubectl apply -n istio-system -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: originate-tls-for-nginx spec: host: my-nginx.mesh-external.svc.cluster.local trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: SIMPLE credentialName: client-credential # this must match the secret created earlier without the "-cacert" suffix sni: my-nginx.mesh-external.svc.cluster.local EOF
发送一个 HTTP 请求到
http://my-nginx.mesh-external.svc.cluster.local
:$ kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl -sS http://my-nginx.mesh-external.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
检查
istio-egressgateway
Pod 的日志,看看有没有与我们的请求相对应的日志。如果 Istio 被部署在istio-system
命名空间,打印日志的命令是:$ kubectl logs -l istio=egressgateway -n istio-system | grep 'my-nginx.mesh-external.svc.cluster.local' | grep HTTP
您应该看到与下面类似的一行:
[2018-08-19T18:20:40.096Z] "GET / HTTP/1.1" 200 - 0 612 7 5 "172.30.146.114" "curl/7.35.0" "b942b587-fac2-9756-8ec6-303561356204" "my-nginx.mesh-external.svc.cluster.local" "172.21.72.197:443"
清理 TLS 连接的示例{#cleanup-the-TLS-origination example}
- 删除您创建的 Istio 配置项:
```
$ kubectl delete destinationrule originate-tls-for-nginx -n istio-system
$ kubectl delete virtualservice direct-nginx-through-egress-gateway
$ kubectl delete destinationrule egressgateway-for-nginx
$ kubectl delete gateway istio-egressgateway
$ kubectl delete secret client-credential-cacert -n istio-system
$ kubectl delete service my-nginx -n mesh-external
$ kubectl delete deployment my-nginx -n mesh-external
$ kubectl delete configmap nginx-configmap -n mesh-external
$ kubectl delete secret nginx-server-certs nginx-ca-certs -n mesh-external
$ kubectl delete namespace mesh-external
```
删除证书和私钥:
$ rm example.com.crt example.com.key my-nginx.mesh-external.svc.cluster.local.crt my-nginx.mesh-external.svc.cluster.local.key my-nginx.mesh-external.svc.cluster.local.csr
删除本例中生成的配置文件。
$ rm ./nginx.conf
与上一节类似,这一节描述了如何配置一个 Egress 网关来执行为外部服务进行 TLS 连接,只是这次使用的是一个需要双向 TLS 连接的服务。
Egress 网关将使用 SDS 而不是文件挂载来提供客户端证书。
对于这项任务,您可以使用您喜欢的工具来生成证书和钥匙。也可以参考下面命令:openssl.
为
my-nginx.mesh-external.svc.cluster.local
创建一个证书和私钥:$ openssl req -out my-nginx.mesh-external.svc.cluster.local.csr -newkey rsa:2048 -nodes -keyout my-nginx.mesh-external.svc.cluster.local.key -subj "/CN=my-nginx.mesh-external.svc.cluster.local/O=some organization" $ openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in my-nginx.mesh-external.svc.cluster.local.csr -out my-nginx.mesh-external.svc.cluster.local.crt
生成客户端的证书和私钥:
$ openssl req -out client.example.com.csr -newkey rsa:2048 -nodes -keyout client.example.com.key -subj "/CN=client.example.com/O=client organization" $ openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in client.example.com.csr -out client.example.com.crt
部署一个双向TLS服务器{deploy-a-mutual-TLS-server}
为了模拟一个支持双向 TLS 连接的实际外部服务。在您的 Kubernetes 集群中部署一个NGINX服务器,但在 Istio 服务网外运行,即在没有启用 Istio Sidecar 代理注入的命名空间中运行。
创建一个命名空间来代表 Istio 网状结构之外的服务,即
mesh-external
。请注意,Sidecar 代理将不会被自动注入到这个命名空间的 Pod 中,因为自动注入 Sidecar 的功能没有被 上。$ kubectl create namespace mesh-external
-
$ kubectl create -n mesh-external secret tls nginx-server-certs --key my-nginx.mesh-external.svc.cluster.local.key --cert my-nginx.mesh-external.svc.cluster.local.crt $ kubectl create -n mesh-external secret generic nginx-ca-certs --from-file=example.com.crt
为 NGINX 服务器创建一个配置文件:
$ cat <<\EOF > ./nginx.conf events { } http { log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; server { listen 443 ssl; root /usr/share/nginx/html; index index.html; server_name my-nginx.mesh-external.svc.cluster.local; ssl_certificate /etc/nginx-server-certs/tls.crt; ssl_certificate_key /etc/nginx-server-certs/tls.key; ssl_client_certificate /etc/nginx-ca-certs/example.com.crt; ssl_verify_client on; # In mutual TLS, server verifies client's certificate } } EOF
创建一个 Kubernetes ConfigMap 来保存 NGINX 服务器的配置。
$ kubectl create configmap nginx-configmap -n mesh-external --from-file=nginx.conf=./nginx.conf
部署 NGINX 服务器。
创建 Kubernetes Secrets来保存客户的证书。
$ kubectl create secret -n istio-system generic client-credential --from-file=tls.key=client.example.com.key \ --from-file=tls.crt=client.example.com.crt --from-file=ca.crt=example.com.crt
The secret must be created in the same namespace as Istio is deployed in,
istio-system
in this case.To support integration with various tools, Istio supports a few different Secret formats.
In this example. a single generic Secret with keys
tls.key
,tls.crt
, andca.crt
is used.为
my-nginx.mesh-external.svc.cluster.local
创建一个 EgressGateway
,端口443,以及目标规则和虚拟服务,以引导流量通过 Egress 网关并从 Egress 网关到外部服务。$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: istio-egressgateway spec: selector: istio: egressgateway servers: - port: number: 443 name: https protocol: HTTPS hosts: - my-nginx.mesh-external.svc.cluster.local tls: mode: ISTIO_MUTUAL --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: egressgateway-for-nginx spec: host: istio-egressgateway.istio-system.svc.cluster.local subsets: - name: nginx trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: ISTIO_MUTUAL sni: my-nginx.mesh-external.svc.cluster.local EOF
定义一个
VirtualService
来引导流量通过 Egress 网关:$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: direct-nginx-through-egress-gateway spec: hosts: - my-nginx.mesh-external.svc.cluster.local gateways: - istio-egressgateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-system.svc.cluster.local subset: nginx port: number: 443 weight: 100 - match: - gateways: - istio-egressgateway port: 443 route: - destination: host: my-nginx.mesh-external.svc.cluster.local port: number: 443 weight: 100 EOF
添加一个
DestinationRule
来执行双向 TLS 连接$ kubectl apply -n istio-system -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: originate-mtls-for-nginx spec: host: my-nginx.mesh-external.svc.cluster.local trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: MUTUAL credentialName: client-credential # this must match the secret created earlier to hold client certs sni: my-nginx.mesh-external.svc.cluster.local EOF
发送一个 HTTP 请求到
http://my-nginx.mesh-external.svc.cluster.local
:$ kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl -sS http://my-nginx.mesh-external.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
检查
istio-egressgateway
Pod 的日志,看看有没有与我们的请求相对应的日志。如果 Istio 被部署在istio-system
命名空间,打印日志的命令是:$ kubectl logs -l istio=egressgateway -n istio-system | grep 'my-nginx.mesh-external.svc.cluster.local' | grep HTTP
您应该看到与下面类似的一行。
[2018-08-19T18:20:40.096Z] "GET / HTTP/1.1" 200 - 0 612 7 5 "172.30.146.114" "curl/7.35.0" "b942b587-fac2-9756-8ec6-303561356204" "my-nginx.mesh-external.svc.cluster.local" "172.21.72.197:443"
清理双向TLS连接的示例{cleanup-the mutual-TLS-origination-example}
移除创建的 Kubernetes 资源:
$ kubectl delete secret nginx-server-certs nginx-ca-certs -n mesh-external $ kubectl delete secret client-credential -n istio-system $ kubectl delete configmap nginx-configmap -n mesh-external $ kubectl delete service my-nginx -n mesh-external $ kubectl delete deployment my-nginx -n mesh-external $ kubectl delete namespace mesh-external $ kubectl delete gateway istio-egressgateway $ kubectl delete virtualservice direct-nginx-through-egress-gateway $ kubectl delete destinationrule -n istio-system originate-mtls-for-nginx $ kubectl delete destinationrule egressgateway-for-nginx
删除证书和私钥:
$ rm example.com.crt example.com.key my-nginx.mesh-external.svc.cluster.local.crt my-nginx.mesh-external.svc.cluster.local.key my-nginx.mesh-external.svc.cluster.local.csr client.example.com.crt client.example.com.csr client.example.com.key
删除本例中生成的配置文件:
$ rm ./nginx.conf $ rm ./gateway-patch.json
删除服务和部署。
$ kubectl delete service sleep $ kubectl delete deployment sleep