使用 Cert-Manager 加密 Kubernetes Ingress

    您将从全新的 Istio 安装开始,创建示例服务,使用 Kubernetes Ingress 把它开放出去,并使用 cert-manager(与 Istio 捆绑在一起)管理 TLS 证书的签发和续订来确保它的安全,这个证书之后会给 Istio ingress gateway 使用,并根据需要通过 提供 hot-swapped 功能。

    • 安装 Istio 并确认已经启用支持 Kubernetes Ingress 和 的 ingress gateway。下面是例子:

    默认情况下, 会以 LoadBalancer 的服务类型开放出来。您可以根据自己的 Kubernetes 环境把 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 安装中包含了一个自动生成的 ,用于提供 Kubernetes Ingress 定义的路由服务。默认情况下,它不会使用 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", "mode": "SIMPLE", "privateKey": "sds", "serverCertificate": "sds"}}]'

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

    接下来使用一个简单的 helloworld 应用来进行演示。下面的命令会为示例应用创建 DeploymentService,并使用 Istio Ingress 开放服务。

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

    现在,您应该能够通过 HTTP 访问演示应用:

    1. Hello version: v1, instance: helloworld-5d498979b6-jp2mf

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

    目前,您的 Istio 中应该已经启动了 cert-manager,并带有两个 ClusterIssuer 对象(分别对应 的生产和测试 ACME-endpoints)。这个例子中使用测试 ACME-endpoint(将 letsencrypt-staging 替换为 letsencrypt 就能获得浏览器信任的证书)。

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

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

    注意这里的 secretName 要匹配前面配置 gateway 时的 credentialName 字段值。Certificate 对象会被 cert-manager 处理,最终会签发新证书。为了看到这个过程我们可以查询 Certificate 对象的状态:

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

    这样一来,该服务也应通过 HTTPS 访问了:

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

    注意,您需要使用 —insecure 参数,因为测试 ACME-endpoints 签发的证书不受信任。

    现在换成生产 letsencrypt。首先,我们重新申请一下证书。

    1. certificate.cert-manager.io/ingress-cert configured

    现在删除 secret 来强制 cert-manager 从生产 ACME-endpoints 请求新证书:

    1. $ kubectl delete secret -n istio-system ingress-cert

    等等看证书是否成功签发了:

      您应该能看到如下显示:

      相关内容

      把 Istio 作为外部服务的代理

      说明了如何为一个 ingress gateway 配置 SNI 透传。

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

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

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

      使用外部 Web 服务

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

      描述如何配置 Istio gateway,以将服务暴露至服务网格之外。