ArchSummit深圳站7折本周截止,点击立减2640元>> 了解详情
写点什么

深入浅出 Kubernetes 实践篇 (六):服务网格证书过期问题

  • 2020 年 3 月 30 日
  • 本文字数:2488 字

    阅读完需:约 8 分钟

深入浅出Kubernetes 实践篇 (六):服务网格证书过期问题

简介:11 月 22 号半夜 2 点,被值班同学的电话打醒。了解下来,大概情况是,客户某一台 Kubernetes 集群节点重启之后,他再也无法创建 Istio 虚拟服务和 Pod 了。一来对 Istio 还不是那么熟悉,二来时间可能有点晚,脑子还在懵圈中,本来一个应该比较轻松解决掉的问题,花了几十分钟看代码,处理的惨不忍睹。


11 月 22 号半夜 2 点,被值班同学的电话打醒。了解下来,大概情况是,客户某一台 Kubernetes 集群节点重启之后,他再也无法创建 Istio 虚拟服务和 Pod 了。


一来对 Istio 还不是那么熟悉,二来时间可能有点晚,脑子还在懵圈中,本来一个应该比较轻松解决掉的问题,花了几十分钟看代码,处理的惨不忍睹。最终还是在某位大神帮助下,解决了问题。


鉴于此问题,以及相关报错,在网上找不到对应的文章,所以这里分享下这个问题,避免后来的同学,在同样的地方踩坑。另外谨以此篇致敬工作中遇到过的大神!


不断重启的 Citadel

Citadel 是 istio 的证书分发中心。证书即某个实体的身份证明,直接代表着实体本身参与信息交流活动。Citadel 作为证书分发中心,负责替服务网格中每个服务创建身份证书,方便服务之间安全交流。


这个问题的现象是,Citadel 再也无法启动了,导致无法创建新的虚拟服务和 Pod 实例。观察 Citadel,发现其不断重启,并输出以下报错信息。


2019-11-22T02:40:34.814547Z warn Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.

2019-11-22T02:40:34.815408Z info Use self-signed certificate as the CA certificate

2019-11-22T02:40:34.840128Z error Failed to create a self-signed Citadel (error: [failed to create CA KeyCertBundle (cannot verify the cert with the provided root chain and cert pool)])


通过代码分析,以及最后一行报错,可以理解问题背后的逻辑:


  1. Citadel 不能启动,是因为其无法创建自签名的证书(Failed to create a self-signed Citadel)

  2. Citadel 无法创建自签名证书的原因,又是由于它不能创建秘钥和证书(failed to create CA KeyCertBundle)

  3. 而前两条的根本的原因,是因为在验证创建的自签名证书的时候,验证失败(cannot verify the cert with the provided root chain and cert pool)


一般意义上的证书验证

证书的签发关系,会把证书连接成一棵证书签发关系树。顶部是根证书,一般由可信第三方持有,根证书都是自签名的,即其不需要其他机构来对其身份提供证明。其他层级的 CA 证书,都是由上一层 CA 证书签发。最底层的证书,是给具体应用使用的证书。



验证这棵树上的证书,分两种情况:


根证书验证。因为即是签发者,又是被签发者,所以根证书验证,只需要提供根证书本身,一般肯定验证成功。


其他证书验证。需要提供证书本身,以及其上层所有 CA 证书,包括根证书。


自签名证书验证失败 Citadel 启动失败的根本原因,是其创建的自签名的证书,无法验证通过。而这一点,也是我处理问题时,卡壳的原因。左思右想,不明白为什么刚刚新建的自签名证书,都验证不通过。


大神定理

有一条定理,就是我们绞尽脑汁,耗费大量时间无法解决的问题,在大神眼里,可能就是几秒钟的事情。11 月 22 号半夜,这条真理再次被验证。


因为实在想不通,但是用户又非常着急,所以最终还是打扰了一位大神,他只大概看了一下报错,就判断是 CA 证书过期问题。使用 istio 提供的证书验证脚本,很快证实了他的判断。相关文章见最后参考部分。


Citadel 证书体系

问题解决了,这里总结下 Citadel 证书体系。大多数用户使用 Isito 的时候,都会选择使用自签名的根证书。自签名根证书,证书,以及证书使用者 sidecar 三种之间有三种关系:



  1. 根证书和证书之间的签发关系。这种关系,保证了信任的传递性质。

  2. 证书和 sidecar 之间的持有和被持有关系。某种意义上,这是给 pod/sidecar 和证书画上了等号。

  3. 根证书和 sidecar 之间的信任关系。这与前两条加起来,sidecar 就信任所有根证书签发的证书。


以上三条,即可保证,在互相通信的时候,pod/sidecar 之间可以完成 tls 双向认证成功。


犯的错

这个问题排查中,实际上犯了两个错误。一个是代码阅读不仔细,一直盯着自签名证书新建的逻辑看。因为有了这个前提,即新建证书验证失败,所以没有办法理解,为什么新建的自签名证书也会验证失败,所以倾向于认为是底层安全库出了问题;另外一个是,只盯着 Citadel 不能启动的报错做,忽略了另外一条线索,就是 Pod 和虚拟服务创建失败。实际上后来发现,pod 和虚拟服务创建失败的报错,有更明显的证书过期错误信息。


virtualservices.networking.istio.io “xxxx” could not be patched: Internal error occurred: failed calling admission webhook “pilot.validation.istio.io”: Post https://istio-galley.istio-system.svc:443/admitpilot?timeout=30s: x509: certificate has expired or is not yet valid.


后记

在 Istio 比较早期的版本中,自签名 Ca 证书有效期只有一年时间,如果使用老版本 Istio 超过一年,就会遇到这个问题。当证书过期之后,我们创建新的虚拟服务或者 pod,都会因为 CA 证书过期而失败。而这时如果 Citadel 重启,它会读取过期证书并验证其有效性,就会出现以上 Cidatel 不能启动的问题。


这个 Ca 证书在 Kubernetes 集群中,是以 istio-ca-secret 命名的 secret,我们可以使用 openssl 解码证书来查看有效期。这个问题比较简单的处理方法,就是删除这个 Secret,并重启 Citadel,这时 Citadel 会走向新建和验证自签名 Ca 证书的逻辑并刷新 Ca 证书。或者参考以下官网处理方式。


参考

https://istio.io/docs/ops/security/root-transition/


作者简介


罗建龙(花名声东),阿里云技术专家。多年操作系统和图形显卡驱动调试和开发经验。目前专注云原生领域,容器集群和服务网格。


相关阅读


深入浅出Kubernetes 实践篇 (一):节点就绪问题之一


深入浅出Kubernetes 实践篇 (二):节点就绪问题之二


深入浅出Kubernetes 实践篇 (三):命名空间删除问题


深入浅出Kubernetes 实践篇 (四):集群安全组配置管理


深入浅出Kubernetes 实践篇 (五):二分之一活的微服务


2020 年 3 月 30 日 17:14828

评论

发布
暂无评论
发现更多内容

头号云话题:进击的开源操作系统

头号云话题:进击的开源操作系统

深入浅出Kubernetes 实践篇 (六):服务网格证书过期问题_文化 & 方法_罗建龙(声东)_InfoQ精选文章