Egress 网关 TLS 连接 发起的过程 (SDS)
使用SDS在 Egress 网关上执行 TLS 连接
本节描述了如何执行TLS 连接流量 Egress 的例子。只是这次使用了一个 Egress 网关。请注意,在这种情况下,TLS初始化将由 Egress 网关完成。是由 Egress 网关完成的,而不是前一个例子中的挎包。Egress 网关将使用 SDS 而不是文件挂载来提供客户证书。
生成 CA 及证书密钥
1、创建一个根证书和私钥,为您的服务签署证书:
$ 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
2、为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 -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 代理注入的命名空间中。
1、创建一个命名空间来代表 Istio 网状结构之外的服务,即mesh-external
。请注意,Sidecar 代理将不会被自动注入到这个命名空间的 Pod 中,因为自动注入 Sidecar 的功能没有被启用 上。
$ kubectl create namespace mesh-external
2、创建 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
3、为 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
4、创建一个 Kubernetes ConfigMap 来保存 NGINX 服务器的配置。
$ kubectl create configmap nginx-configmap -n mesh-external --from-file=nginx.conf=./nginx.conf
5、部署 NGINX 服务器:
$ kubectl apply -f - <<EOF apiVersion: v1 kind: Service metadata: name: my-nginx namespace: mesh-external labels: run: my-nginx spec: ports: - port: 443 protocol: TCP selector: run: my-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx namespace: mesh-external spec: selector: matchLabels: run: my-nginx replicas: 1 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 443 volumeMounts: - name: nginx-config mountPath: /etc/nginx readOnly: true - name: nginx-server-certs mountPath: /etc/nginx-server-certs readOnly: true - name: nginx-ca-certs mountPath: /etc/nginx-ca-certs readOnly: true volumes: - name: nginx-config configMap: name: nginx-configmap - name: nginx-server-certs secret: secretName: nginx-server-certs - name: nginx-ca-certs secret: secretName: nginx-ca-certs EOF
为 Egress 流量配置简单的 TLS 连接
1、创建一个 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”。
2、为my-nginx.mesh-external.svc.cluster.local
创建一个 Egress gateway
,端口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
3、定义一个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
4、添加一个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
5、发送一个 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> ...
6、检查istio-egressgateway
Pod 的日志,看看有没有与我们的请求相对应的日志。如果 Istio 被部署在istio-system
命名空间,打印日志的命令是:
$ kubectl logs -l istio=egressgateway -n istio-system | grep 'my-nginx.mesh-external.svc.cluster.local' | grep HTTP
通过 Egress 网关发起 双向TLS 连接
与上一节类似,这一节描述了如何配置一个 Egress 网关来执行为外部服务进行 TLS 连接,只是这次使用的是一个需要双向 TLS 连接的服务。
Egress 网关将使用 SDS 而不是文件挂载来提供客户端证书。
生成客户端和服务端的证书和钥匙
对于这项任务,您可以使用您喜欢的工具来生成证书和钥匙。也可以参考下面命令:openssl.
1、创建一个 root 证书和私钥,为您的服务端签署证书:
$ 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