Ingress Sidecar TLS 终止

    用于此任务的示例 HTTPS 服务是一个简单的 httpbin 服务。在以下步骤中,您将在服务网格中部署 httpbin 服务并对其进行配置。

    以下信息描述了一个实验性功能,仅用于评估。

    • 按照安装指南中的说明设置 Istio ,启用实验功能 。

    • 创建一个 test 命名空间,在其中部署目标 httpbin 服务。确保为该命名空间启用 Sidecar 注入。

      1. $ kubectl create ns test
      2. $ kubectl label namespace test istio-injection=enabled

    启用全局 mTLS

    应用以下 PeerAuthentication 策略,对网格中的所有工作负载实现 mTLS 流量。

    1. $ kubectl -n test apply -f - <<EOF
    2. apiVersion: security.istio.io/v1beta1
    3. kind: PeerAuthentication
    4. metadata:
    5. name: default
    6. spec:
    7. mtls:
    8. mode: STRICT
    9. EOF

    为外部暴露的 httpbin 端口禁用 PeerAuthentication

    1. $ kubectl -n test apply -f - <<EOF
    2. apiVersion: security.istio.io/v1beta1
    3. kind: PeerAuthentication
    4. metadata:
    5. name: disable-peer-auth-for-external-mtls-port
    6. namespace: test
    7. spec:
    8. selector:
    9. matchLabels:
    10. app: httpbin
    11. mtls:
    12. mode: STRICT
    13. portLevelMtls:
    14. 9080:
    15. mode: DISABLE
    16. EOF

    对于此任务,您可以使用自己喜欢的工具来生成证书和密钥。下面的命令使用 openssl

    1. $ #CA is example.com
    2. $ 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
    3. $ openssl req -out httpbin.test.svc.cluster.local.csr -newkey rsa:2048 -nodes -keyout httpbin.test.svc.cluster.local.key -subj "/CN=httpbin.test.svc.cluster.local/O=httpbin organization"
    4. $ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in httpbin.test.svc.cluster.local.csr -out httpbin.test.svc.cluster.local.crt
    5. $ #client is client.test.svc.cluster.local
    6. $ openssl req -out client.test.svc.cluster.local.csr -newkey rsa:2048 -nodes -keyout client.test.svc.cluster.local.key -subj "/CN=client.test.svc.cluster.local/O=client organization"
    7. $ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in client.test.svc.cluster.local.csr -out client.test.svc.cluster.local.crt

    为证书和密钥创建 Kubernetes secret

    1. $ kubectl -n test create secret generic httpbin-mtls-termination-cacert --from-file=ca.crt=./example.com.crt

    部署测试服务 httpbin

    当创建 httpbin Deployment 时,我们需要在该 Deployment 中使用 userVolumeMount 注解来为 istio-proxy sidecar 挂载证书。请注意,之所以需要此步骤是因为 Istio Sidecar 目前不支持 credentialName 配置。

    1. sidecar.istio.io/userVolume: '{"tls-secret":{"secret":{"secretName":"httpbin-mtls-termination","optional":true}},"tls-ca-secret":{"secret":{"secretName":"httpbin-mtls-termination-cacert"}}}'
    2. sidecar.istio.io/userVolumeMount: '{"tls-secret":{"mountPath":"/etc/istio/tls-certs/","readOnly":true},"tls-ca-secret":{"mountPath":"/etc/istio/tls-ca-certs/","readOnly":true}}'

    使用以下命令部署带有 userVolumeMount 配置的 httpbin 服务:

    这是此功能的核心步骤。使用 Sidecar API 配置入口 TLS 设置。TLS 模式可以是 SIMPLEMUTUAL。本示例使用 MUTUAL

    1. $ kubectl -n test apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: Sidecar
    4. metadata:
    5. name: ingress-sidecar
    6. namespace: test
    7. spec:
    8. workloadSelector:
    9. labels:
    10. app: httpbin
    11. version: v1
    12. ingress:
    13. - port:
    14. number: 9080
    15. protocol: HTTPS
    16. name: external
    17. defaultEndpoint: 0.0.0.0:80
    18. tls:
    19. mode: MUTUAL
    20. privateKey: "/etc/istio/tls-certs/tls.key"
    21. serverCertificate: "/etc/istio/tls-certs/tls.crt"
    22. caCertificates: "/etc/istio/tls-ca-certs/ca.crt"
    23. - port:
    24. number: 9081
    25. protocol: HTTP
    26. name: internal
    27. defaultEndpoint: 0.0.0.0:80
    28. EOF

    验证

    现在已经部署和配置了 httpbin 服务器,启动两个客户端来测试网格内部和外部的端到端连接:

    1. 在与 httpbin 服务相同的命名空间(test)中的内部客户端(sleep),已注入 Sidecar。
    2. 在 default 命名空间(即服务网格外部)中的外部客户端(sleep)。
    1. $ kubectl apply -f samples/sleep/sleep.yaml
    2. $ kubectl -n test apply -f samples/sleep/sleep.yaml
    1. sleep-557747455f-xx88g 1/1 Running 0 4m14s
    1. $ kubectl get pods -n test
    2. NAME READY STATUS RESTARTS AGE
    3. httpbin-5bbdbd6588-z9vbs 2/2 Running 0 8m44s
    4. sleep-557747455f-brzf6 2/2 Running 0 6m57s
    1. $ kubectl get svc -n test
    2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    3. httpbin ClusterIP 10.100.78.113 <none> 8443/TCP,8080/TCP 10m
    4. sleep ClusterIP 10.110.35.153 <none> 80/TCP 8m49s

    在以下命令中,将 httpbin-5bbdbd6588-z9vbs 替换为 httpbin Pod 的名称。

    1. $ istioctl proxy-config secret httpbin-5bbdbd6588-z9vbs.test
    2. RESOURCE NAME TYPE STATUS VALID CERT SERIAL NUMBER NOT AFTER NOT BEFORE
    3. file-cert:/etc/istio/tls-certs/tls.crt~/etc/istio/tls-certs/tls.key Cert Chain ACTIVE true 1 2023-02-14T09:51:56Z 2022-02-14T09:51:56Z
    4. default Cert Chain ACTIVE true 329492464719328863283539045344215802956 2022-02-15T09:55:46Z 2022-02-14T09:53:46Z
    5. ROOTCA CA ACTIVE true 204427760222438623495455009380743891800 2032-02-07T16:58:00Z 2022-02-09T16:58:00Z
    6. file-root:/etc/istio/tls-ca-certs/ca.crt Cert Chain ACTIVE true 14033888812979945197 2023-02-14T09:51:56Z 2022-02-14T09:51:56Z

    在 8443 端口上验证外部到内部网格的连通性

    要验证来自外部客户端的 mTLS 流量,首先将 CA 证书和客户端证书/密钥复制到在 default 命名空间中运行的 sleep 客户端。

    1. $ export EXTERNAL_CLIENT=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
    2. $ kubectl cp client.test.svc.cluster.local.key default/"${EXTERNAL_CLIENT}":/tmp/
    3. $ kubectl cp client.test.svc.cluster.local.crt default/"${EXTERNAL_CLIENT}":/tmp/
    4. $ kubectl cp example.com.crt default/"${EXTERNAL_CLIENT}":/tmp/ca.crt

    现在证书可用于外部 sleep 客户端,您可以使用以下命令验证该客户端到内部 httpbin 服务的连通性。

    1. $ kubectl exec "${EXTERNAL_CLIENT}" -c sleep -- curl -IsS --cacert /tmp/ca.crt --key /tmp/client.test.svc.cluster.local.key --cert /tmp/client.test.svc.cluster.local.crt -HHost:httpbin.test.svc.cluster.local "https://httpbin.test.svc.cluster.local:8443/status/200"
    2. server: istio-envoy
    3. date: Mon, 24 Oct 2022 09:05:31 GMT
    4. content-type: text/html; charset=utf-8
    5. access-control-allow-origin: *
    6. access-control-allow-credentials: true
    7. content-length: 0
    8. x-envoy-upstream-service-time: 4
    9. x-envoy-decorator-operation: ingress-sidecar.test:9080/*

    除了通过入口端口 8443 验证外部 mTLS 连通性之外,验证端口 8080 不接受任何外部 mTLS 流量也很重要。

    1. $ kubectl exec "${EXTERNAL_CLIENT}" -c sleep -- curl -IsS --cacert /tmp/ca.crt --key /tmp/client.test.svc.cluster.local.key --cert /tmp/client.test.svc.cluster.local.crt -HHost:httpbin.test.svc.cluster.local "http://httpbin.test.svc.cluster.local:8080/status/200"
    2. curl: (56) Recv failure: Connection reset by peer
    3. command terminated with exit code 56

    清理双向 TLS 终止示例

    1. 移除创建的 Kubernetes 资源:

      1. $ kubectl delete secret httpbin-mtls-termination httpbin-mtls-termination-cacert -n test
      2. $ kubectl delete service httpbin sleep -n test
      3. $ kubectl delete deployment httpbin sleep -n test
      4. $ kubectl delete namespace test
      5. $ kubectl delete service sleep
      6. $ kubectl delete deployment sleep
      1. $ rm example.com.crt example.com.key httpbin.test.svc.cluster.local.crt httpbin.test.svc.cluster.local.key httpbin.test.svc.cluster.local.csr \
    2. 将 Istio 从集群内卸载: