通过 SDS 提供身份服务

该任务展示了启用 SDS (secret discovery service) 来为 Istio 提供身份服务的过程。

Istio 1.1 之前,Istio 为工作负载提供的密钥和证书是由 Citadel 生成并使用加载 Secret 卷的方式分发给 Sidecar 的,这种方式有几大缺陷:

  • 证书轮换造成的性能损失: 证书发生轮换时,Envoy 会进行热重启以加载新的证书和密钥,会造成性能下降。

  • 潜在的安全漏洞: 工作负载的私钥使用 Kubernetes Secret 的方式进行分发,存在一定风险

在 Istio 1.1 之中,上述问题可以使用 SDS 来解决。下面描述了它的工作流程:

  1. 工作负载的 Sidecar 从 Citadel 代理中请求密钥和证书:Citadel 代理是一个 SDS 服务器,这一代理以 DaemonSet 的形式在每个节点上运行,在这一请求中,Envoy 把 Kubernetes service account 的 JWT 传递给 Citadel 代理。

  2. Citadel 代理生成密钥对,并向 Citadel 发送 CSR 请求: Citadel 校验 JWT,并给 Citadel 代理签发证书。

  3. Citadel 代理把密钥和证书返回给工作负载的 Sidecar。

这种方法有如下好处:

  • 私钥不会离开节点:私钥仅存在于 Citadel 代理和 Envoy Sidecar 的内存中。

  • 不再需要加载 Secret 卷:去掉对 Kubernetes Secret 的依赖。

  • Sidecar 能够利用 SDS API 动态的刷新密钥和证书:证书轮换过程不再需要重启 Envoy。

开始之前

  • 使用 Helm 安装 Istio,并启用 SDS 和全局的双向 TLS:

    Zip
    $ cat install/kubernetes/namespace.yaml > istio-auth-sds.yaml
    $ cat install/kubernetes/helm/istio-init/files/crd-* >> istio-auth-sds.yaml
    $ helm dep update --skip-refresh install/kubernetes/helm/istio
    $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system --values @install/kubernetes/helm/istio/values-istio-sds-auth.yaml@ >> istio-auth-sds.yaml
    $ kubectl create -f istio-auth-sds.yaml
    

通过 SDS 提供的密钥和证书支持服务间的双向 TLS

参考认证策略任务中的内容,部署测试服务。

ZipZipZipZip
$ kubectl create ns foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n foo
$ kubectl create ns bar
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n bar
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n bar

验证双向 TLS 请求是否成功:

$ for from in "foo" "bar"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200

验证:没有通过加载 Secret 卷的方式生成的文件

要验证是否有通过加载 Secret 卷的方式生成的文件,可以访问工作负载的 Sidecar 容器:

$ kubectl exec -it $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c istio-proxy -n foo  -- /bin/bash

这里会看到,在 /etc/certs 文件夹中没有加载 Secret 卷生成的文件。

清理

清理测试服务以及 Istio 控制面:

$ kubectl delete ns foo
$ kubectl delete ns bar
$ kubectl delete -f istio-auth-sds.yaml

注意事项

目前 SDS 的身份服务有几点需要注意的地方:

  • 要启用控制面加密,还需要加载 Secret 卷。控制面的 SDS 支持还在开发之中。

  • 从 Secret 卷到 SDS 的平滑迁移过程,也还在开发之中。