K8s 集群证书问题记录
最近在环境中部署了一个 Virtual-Kubelet,由于它与 APIServer 的证书交互出了一些问题,导致了一些功能不可用,故去了解了下 K8s 集群的所有证书与关系,做一个梳理。
https 流程
想了解证书的关系,首先要弄清楚 https 的流程,可以先阅读这篇文章。
简单来说,完成一次 https 连接,需要有以下证书密钥互相传输:
- server 端公钥、证书
- client 端公钥、证书
问题现象
用户使用 ServiceAccoutToken 分配的证书,无法访问 Virtual-Kubelet 上的 mtrics 接口,但是可以直接访问原生 Kubelet 的 metrics 接口。
问题分析
一开始感觉是 Virtual-Kubelet 起的 TLS 服务配置问题,故先进行‘拆盲盒’,参考原生 Kubelet 配置,将 Virtual-Kubelet server 的 TLS 支持版本、支持算法等配置都进行了修改,但是没有解决问题。
后来找了环境部署相关的同事做了了解,由于安全原因,我们 K8s 集群使用两套证书配置,其中一套用于 APIServer 提供 server(称为CA1),一套用于访问 Kubelet 作为 client(称为CA2),这两套使用不同的 CA 证书签发,所以无法直接互相访问。
在两套证书的背景下,会发现理论上使用 ServiceAccoutToken 也应该访问不到原生 Kubelet 的 metrics 接口,因为 ServiceAccoutToken 是由 APIServer 的 server ca 证书(即CA1)签发的,而访问 metrics 接口的网络路由是用户 client 访问 APIServer server,然后 APIServer client 访问 Kubelet metrics 接口,Kubelet server 证书理论上应该是使用 CA2 签发的,应该无法访问。
问题根因
通过走读原生 Kubelet 代码,发现了根因。
1 | if len(kc.Authentication.X509.ClientCAFile) > 0 { |
原来 Kubelet Server 原生的配置对于 Client 证书的合法性并不做验证,只要提供了就可以访问。
解决方案
将 Virtual-Kubelet 的 ClientAuth 也 设置成 tls.RequestClientCert
。