• 使用 cert-manager 加密 Kubernetes Ingress
    • 开始之前
    • 配置 DNS 名称和 Gateway
    • 部署演示应用
    • 使用 cert-manager 获取 Let’s Encrypt 证书
    • 相关内容

    使用 cert-manager 加密 Kubernetes Ingress

    这个例子演示了在 Istio 中使用 Let’s Encrypt 获取 TLS 证书为 Kubernetes Ingress controller 提供安全加固的过程。虽然 Istio 提供了更强大的功能,例如 Gateway 和 Virtual service,它们可以用于更加高级的流量管理功能,而可选的 Kubernetes Ingress 控制器支持则可以简单的把传统应用和第三方解决方案集成到服务网格之中,并由此获得 Istio 提供的遥测和跟踪能力。

    首先要从一个全新安装的 Istio 入手,创建一个示例应用,并利用 Kubernetes Ingress 资源将服务开放出去,Istio 可以为这一过程提供加密服务,它调用自带的 cert-manager 管理 TLS 证书的签发和续期,然后把证书分发给 Istio 的 Ingress gateway,并在必要时使用 SDS 进行证书的热交换。

    开始之前

    安装 Istio 并确认已经启用 Ingress Gateway 的 Kubernetes Ingress 支持、SDS 以及 cert-manager。下面的例子展示了使用 Helm template 完成设置这些依赖项目的方法:

    1. $ helm template $HOME/istio-fetch/istio \
    2. --namespace=istio-system \
    3. --set gateways.istio-ingressgateway.sds.enabled=true \
    4. --set global.k8sIngress.enabled=true \
    5. --set global.k8sIngress.enableHttps=true \
    6. --set global.k8sIngress.gatewayName=ingressgateway \
    7. --set certmanager.enabled=true \
    8. --set certmanager.email=mailbox@donotuseexample.com \
    9. > $HOME/istio-fetch/istio.yaml

    缺省情况下, istio-ingressgateway 会以 LoadBalancer 的服务类型开放出来。根据本地环境条件,可以考虑把 gateways.istio-ingressgateway.type 参数设置为 NodePort

    配置 DNS 名称和 Gateway

    记录一下 istio-ingressgateway 服务的外部 IP 地址:

    1. $ kubectl -n istio-system get service istio-ingressgateway

    对你的 DNS 进行设置,给 istio-ingressgateway 服务的外部 IP 地址分配一个合适的域名。为了能让例子正常执行,需要一个真正的域名,用于签署 TLS 证书。可以把域名保存为环境变量,便于后面的使用:

    1. $ INGRESS_DOMAIN=mysubdomain.mydomain.edu

    Istio 安装中包含了一个自动生成的 Gateway,用于给 Kubernetes Ingress 资源提供路由服务。缺省情况下,它不会使用 SDS,所以需要对其进行修改,让 SDS 来为 istio-ingressgateway 分发 TLS 证书:

    1. $ kubectl -n istio-system edit gateway

    然后修改 https-default 端口对应的 tls 内容:

    1. $ kubectl -n istio-system \
    2. patch gateway istio-autogenerated-k8s-ingress --type=json \
    3. -p='[{"op": "replace", "path": "/spec/servers/1/tls", "value": {"credentialName": "ingress-cert-staging", "mode": "SIMPLE", "privateKey": "sds", "serverCertificate": "sds"}}]'

    现在就可以部署一个演示应用了。

    部署演示应用

    接下来使用一个简单的 helloworld 应用来进行演示。下面的命令会为示例应用创建 DeploymentService 对象,并使用 istio-ingressgateway 所支持的 Ingress 资源开放服务。

    1. $ cat <<EOF | kubectl apply -f -
    2. apiVersion: v1
    3. kind: Service
    4. metadata:
    5. name: helloworld
    6. labels:
    7. app: helloworld
    8. spec:
    9. ports:
    10. - port: 5000
    11. name: http
    12. selector:
    13. app: helloworld
    14. ---
    15. apiVersion: extensions/v1beta1
    16. kind: Deployment
    17. metadata:
    18. name: helloworld
    19. spec:
    20. template:
    21. metadata:
    22. labels:
    23. app: helloworld
    24. spec:
    25. containers:
    26. - name: helloworld
    27. image: istio/examples-helloworld-v1
    28. resources:
    29. requests:
    30. cpu: "100m"
    31. imagePullPolicy: IfNotPresent
    32. ports:
    33. - containerPort: 5000
    34. ---
    35. apiVersion: extensions/v1beta1
    36. kind: Ingress
    37. metadata:
    38. annotations:
    39. kubernetes.io/ingress.class: istio
    40. name: helloworld-ingress
    41. spec:
    42. rules:
    43. - host: "$INGRESS_DOMAIN"
    44. http:
    45. paths:
    46. - path: /hello
    47. backend:
    48. serviceName: helloworld
    49. servicePort: 5000
    50. ---
    51. EOF

    注意,这里用了前面定义的 INGRESS_DOMAIN 变量。

    现在就可以用 HTTP 来访问演示应用了:

    1. $ curl http://$INGRESS_DOMAIN/hello
    2. Hello version: v1, instance: helloworld-5d498979b6-jp2mf

    因为没有配置任何的 TLS 证书,所以 HTTPS 访问还未能启用,下面就开始进行配置。

    使用 cert-manager 获取 Let’s Encrypt 证书

    目前的 Istio 中应该已经启动了 cert-manager,并带有两个 ClusterIssuer 对象(分别对应 Let’s Encrypt 的生产和演练环境)。这个例子中可以使用演练环境(letsencrypt-staging 替换为 letsencrypt 就能获得受浏览器信任的证书),

    为了用 cert-manager 进行证书的签发和管理,需要创建一个 Certificate 资源:

    1. $ cat <<EOF | kubectl apply -f -
    2. apiVersion: certmanager.k8s.io/v1alpha1
    3. kind: Certificate
    4. metadata:
    5. name: ingress-cert-staging
    6. namespace: istio-system
    7. spec:
    8. secretName: ingress-cert-staging
    9. issuerRef:
    10. name: letsencrypt-staging
    11. kind: ClusterIssuer
    12. commonName: $INGRESS_DOMAIN
    13. dnsNames:
    14. - $INGRESS_DOMAIN
    15. acme:
    16. config:
    17. - http01:
    18. ingressClass: istio
    19. domains:
    20. - $INGRESS_DOMAIN
    21. ---
    22. EOF

    注意这里的 secretName 要匹配前面配置 Gateway 资源时其中的 credentialName 字段值。Certificate 对象会被 cert-manager 处理,最终会签发新证书。可以通过对 Certificate 对象状态的查询来得知整个过程的进展:

    1. $ kubectl -n istio-system describe certificate ingress-cert-staging
    2. -> 状态最终会切换为 'Certificate issued successfully'

    这样一来就可以使用 HTTPS 进行访问了:

    1. $ curl --insecure https://$INGRESS_DOMAIN/hello
    2. Hello version: v1, instance: helloworld-5d498979b6-jp2mf

    注意,因为演练环境签发的证书不受信任,这里用了 —insecure 参数。

    相关内容

    没有 TLS 的 Ingress gateway

    介绍如何为入口网关配置 SNI 直通。

    使用 Cert-Manager 部署一个自定义 Ingress 网关

    如何使用 cert-manager 手工部署一个自定义 Ingress 网关。

    使用AWS NLB 配置 Istio Ingress

    描述如何在AWS上使用网络负载均衡器配置 Istio Ingress。

    使用外部 Web 服务

    描述基于 Istio Bookinfo 示例的简单场景。

    使用 SDS 为 Gateway 提供 HTTPS 加密支持

    如何配置 Istio,借助 SDS(Secret 发现服务),使用 TLS 或双向 TLS 将服务开放到网格之外。

    控制 Ingress 流量

    介绍在服务网格 Istio 中如何配置外部公开服务。