智汇华云 | 深入理解 Istio 中的证书管理
Istio 是由 Google、IBM、Lyft 联合开发的开源项目,它是一款微服务管理框架,也被称为第二代微服务 Service Mesh 代表。Istio 的架构思想类似软件定义网络,近年来随着技术的不断发展,Istio 因其轻量级、服务网格管理理念、兼容各大容器编排平台等优势在近两年脱颖而出。本期智汇华云将为大家详细描述 Istio 中证书签发和管理的整个流程以及涉及到的组件。
一、概述
本文会详细描述 Istio 中证书签发和管理的整个流程以及涉及到的组件,假设读者已经有一些技术储备,对于 Istio 中的基本概念和使用比较熟悉。
上图是 Istio 内部在签发证书时的流程和相关的组件。
在 Istiod 内部有一个名为 CA Server 服务的组件,用来提供证书签名的服务。
上图中 Pod A 是用户的负载,伴随着 Pod A 是 Istio 注入的 sidecar,启动的主进程被称为 Pilot Agent,它核心的功能是启动 Envoy 进程来劫持并管理 Pod A 的进出口流量,除此之外,在 Pilot Agent 还有一个名为 SDS Server 的组件,用来生成私钥和证书签名请求文件并向 CA Server 发起证书签名请求。
CA Server 和 SDS Server 通信时,需要验证对方的身份,这时双方都需要有一个公共的 CA 根证书,这个根证书最初由 CA Server 在启动时创建,并存储于 Kubernetes 一个名为 istio-ca-root-cert 的 ConfigMap 对象中。这个 ConfigMap 会在注入 sidecar 时,挂载到 sidecar 的/var/run/secrets/istio 目录中,随后当 SDS Server 与 CA Server 交互时会读取这个根证书,并用它创建 client 然后进行通信。
主要的流程如下:
1. 当 Envoy 进程在与其它 Envoy 进程交互时,发现需要进行 TLS 认证,它会从静态配置文件或者动态配置服务器获取证书的名称等相关信息,这时 Envoy 进程就会通过 SDS API 向 Pilot Agent 中的 SDS Server 发起请求获取证书。
2. SDS Server 收到请求后,会首先读取本地的 ServiceAccount Token,路径为/var/run/secrets/kubernetes.io/serviceaccount/token,然后从 token 中解析出 namespace 和 ServiceAccount 等信息,再用这些信息生成私钥和证书签名请求文件。接下来使用证书签名请求文件作为参数,向 Istiod 发起申请证书签名的请求。
3. Istiod 中的 CA Server 收到请求后会对其中的凭证进行验证,通过后会对根据请求对证书进行签名、生成证书,并将签名后的数字证书发送给 SDS Server。
4. SDS Server 将私钥和从 CA Server 处获得的证书一起通过 SDS API 发送给 Envoy。
5. 以上过程会周期性地重复执行以便实现证书的轮换。
二、CA Server
Istio 内部的 CA Server 用来提供证书签名服务。内部会管理 4 个证书,都会挂载到/etc/cacerts/目录下。
ca 证书用于给集群中的工作负载进行签名,即对 Pilog Agent 发起的 CSR 请求进行签名。
ca 证书和 ca 私钥必须由根证书签名。
ca 证书链是 ca 证书与根证书之间的信任链。
这些证书有两种方式来创建:
1. 自动生成,这种被称为自签名证书,这是默认的方式。
2. 用户手动创建,即手动插入已存在的 CA 证书。可以在部署 Istiod 前使用已存在的证书在 istio-system 中创建名为 cacerts 的 secret,然后 istio 部署的时候会自动使用这个 secret 中的证书,具体可以参考 Istio 官方手册 Plugging in existing CA Certificates。
有 2 个函数可以用来处理 Pilot Agent 发送过来的 CSR 请求。CreateCertificate()和 HandleCSR(),其中第二个被标记为过时的。
CA Server 中涉及到了很多相关的 Kubernetes 资源,现整理如下:
istio-ca-secret secret
位于 istio-system 中,用来持久化保存自签名的 ca 私钥和 ca 证书,其它字段都为空,只由 Istiod 使用,与 Pilot Agent 没有关系。
istio-ca-root-cert configmap
每个 namespace 中都会有一个,用于保存根证书,会挂载到 Pilot Agent 的/var/run/secrets/istio 目录。
istio-security configmap
位于 istio-system 中,用来保存根证书。之前使用在 nodeagent 中,目前 nodeagent 已经集成到 Pilot Agent 中,根证书改为从 istio-ca-root-cert configmap 中获取,目前代码有注释说明保留这个只是为了向前兼容,代码中并没有实际使用,以后会从代码中完全移除。
cacerts secret
会挂载到 Istiod 的/etc/cacerts 目录,用户可以手动通过现有证书创建这个 secret,然后再部署 Istio,这样 Istio 就可以使用用户指定的证书。
三、SDS Server
Pilot Agent 中的 SDS Server 与 Istiod 内部的 CA Server 进行通信时,双方都需要有一个根证书,根据配置的不同,这个根证书有几种不同的获取方式,对应的类型名称为分别为 istiod、kubernetes 和 custom。
下面来看一下注入的 sidecar 的模板文件。
可以看出在部署的时候是通过 pilotCertProvider 这个参数来控制的,默认值是 istiod,在模板文件中会将这个参数的值设置到环境变量 PILOT_CERT_PROVIDER 中。当这个值是 istiod 的情况下,会将 istio-ca-root-cert 这个 configmap 挂载到/var/run/secrets/istio 目录中。
四、数据面证书
数据面证书是指 Envoy 与 Envoy 通信时需要的证书,这些证书是 Envoy 通过向 Pilot Agent 中的 SDS Server 发起 SDS 请求获取的,而 SDS Server 内部获取这些证书的方式其实有两种:
1. SDS Server 内部生成私钥和证书签名请求文件,然后再向 Istiod 内部的 CA Server 发起签名请求,最后将签名后的证书和私钥一起发送给 Envoy。这就是前文中一直提到的情况,也是默认值。
2. SDS Server 读取挂载的静态证书文件。下面来看一下注入的 sidecar 的模板文件:
如果是这种手动插入证书的方式,则 SDS Server 会将用户配置的证书直接返回给 Envoy,而不是像前一种情况那样本地生成私钥和证书签名请求然后向 CA Server 申请签名。
五、控制面认证
Istiod 中的 CA Server 和 Pilot Agent 中的 SDS Server 通信时,需要互相认证对方的身份。
SDS Server 对 CA Server 认证的方式是标准的 TLS 认证,即 CA Server 启动时会配置相应的证书,在交互前进行认证时,会将证书发送给 SDS Server,后者对其进行验证。
CA Server 对 SDS Server 的认证有不止一种方式。
第一种方式使用客户端证书认证进行认证,实际上这时并不会进行真正的认证,只是在当前已经通过证书认证的前提下,从证书中提取出一些对象来供后续使用。
另外需要注意的是这些认证方式如果启用多个的话,只要其中有一个认证通过,就会被认为是总体认证通过。
六、参考
https://istio.io/docs/
https://github.com/istio/istio/
评论