Kubernetes 证书、kubeconfig 与 API Server 的关系

This article is extracted from the chat log with AI. Please identify it with caution.

本文边界:本文聚焦 API Server 的 TLS 连接、证书链、kubeconfig 与 SAN 匹配;认证后的权限判定和 RBAC 配置请阅读授权专题。

推荐深读RBAC 与 kubeconfig 详解:从身份到授权

说明:本文由 Codex 根据作者提供的主题、素材与公开资料辅助生成,属于 AI 生成/整理内容,非作者原创。请读者自行甄别并交叉验证。

先说结论#

在 Kubernetes 里,证书、kubeconfig 和 API Server 的关系可以这样理解:

API Server 是 HTTPS 服务端;
证书负责证明“谁在和谁通信”;
kubeconfig 是客户端连接 API Server 时使用的一组配置。

更具体一点:

  • API Server 暴露 Kubernetes API,默认监听 6443
  • API Server 的服务端证书证明“这个地址上的服务确实是目标 API Server”。
  • 客户端证书、Token 或其他认证方式证明“发起请求的用户或组件是谁”。
  • kubeconfig 记录集群地址、CA 证书、用户凭据和当前上下文。

所以,当 kubectl 报 TLS、证书、x509certificate is valid for ... not ... 这类错误时,本质上是在说:

客户端想连接的 server 地址,
和 API Server 证书里声明可信的名字或 IP,
没有匹配上。

API Server 是什么角色#

API Server 是 Kubernetes 控制平面的入口。

所有集群操作最终都会变成对 API Server 的请求:

  • kubectl get pods 是读 API Server。
  • kubectl apply -f app.yaml 是写 API Server。
  • kubelet 上报 Node 和 Pod 状态,也是调用 API Server。
  • scheduler、controller-manager 监听资源变化,也通过 API Server。

从客户端视角看,API Server 就是一个 HTTPS API:

https://<api-server-address>:6443

因此它和普通 HTTPS 服务一样,需要 TLS 证书来保证通信安全。

Kubernetes 为什么需要证书#

Kubernetes 集群内部存在大量组件间通信:

  • kubectl 到 API Server。
  • kubelet 到 API Server。
  • controller-manager 到 API Server。
  • scheduler 到 API Server。
  • API Server 到 kubelet。
  • API Server 聚合层到 extension API Server。

这些通信通常都基于 TLS。

TLS 在这里解决两个问题:

  1. 加密:网络中的第三方不能直接读取通信内容。
  2. 身份:通信双方能确认对方是谁。

Kubernetes 官方文档也强调,Kubernetes 需要 PKI 证书来完成 TLS 认证;使用 kubeadm 安装时,所需证书默认会自动生成。

CA、服务端证书和客户端证书#

Kubernetes 证书体系里最关键的是 CA。

CA 可以理解为集群内部的“信任根”。只要某个证书是由可信 CA 签发的,客户端或服务端就可以通过 CA 验证它。

常见证书可以粗略分成三类。

CA 证书#

CA 证书用于签发其他证书。

在 kubeadm 集群里,常见路径是:

/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key

其中:

  • ca.crt 是公开证书,可以放到客户端用于验证。
  • ca.key 是私钥,必须严格保护。

如果 CA 私钥泄露,攻击者就可能签发看似可信的组件证书。

API Server 服务端证书#

API Server 服务端证书通常包括:

/etc/kubernetes/pki/apiserver.crt
/etc/kubernetes/pki/apiserver.key

这个证书用于证明:

客户端正在访问的 HTTPS 服务,
确实是由集群 CA 签发的 API Server。

客户端连接 API Server 时,会检查:

  • 证书是否由可信 CA 签发。
  • 证书是否过期。
  • 证书里的 DNS 名称或 IP 是否包含当前访问的地址。

第三点就是很多 x509 错误的来源。

客户端证书#

客户端证书用于证明请求方身份。

例如管理员 kubeconfig 里通常会包含:

users:
  - name: kubernetes-admin
    user:
      client-certificate-data: ...
      client-key-data: ...

API Server 收到请求后,会先完成 TLS 层的客户端认证,再结合 Kubernetes 的认证、授权链路判断这个身份能做什么。

SAN 为什么重要#

SAN 是 Subject Alternative Name,即证书里声明的可用 DNS 名称或 IP 地址。

现代 TLS 客户端主要看 SAN,而不是只看证书的 Common Name。

假设 API Server 证书只包含:

10.0.0.10
kubernetes
kubernetes.default
kubernetes.default.svc

这时如果 kubeconfig 里的 server 写成:

server: https://api.example.com:6443

客户端就会报错,因为证书没有声明 api.example.com 是可信名称。

典型错误类似:

x509: certificate is valid for 10.0.0.10, kubernetes, kubernetes.default,
not api.example.com

这不是 API Server 没启动,也不一定是网络不通,而是 TLS 身份校验失败。

kubeconfig 到底是什么#

kubeconfig 不是一个固定文件名,而是一类用于配置 Kubernetes 访问方式的文件。

默认情况下,kubectl 会读取:

$HOME/.kube/config

也可以通过环境变量或命令行参数指定:

KUBECONFIG=/path/to/config kubectl get nodes
kubectl --kubeconfig=/path/to/config get nodes

一个 kubeconfig 主要包含三部分:

clusters:
  - name: demo
    cluster:
      server: https://api.example.com:6443
      certificate-authority-data: ...

users:
  - name: admin
    user:
      client-certificate-data: ...
      client-key-data: ...

contexts:
  - name: demo-admin
    context:
      cluster: demo
      user: admin
      namespace: default

current-context: demo-admin

可以这样理解:

字段作用
clusters[].cluster.serverAPI Server 地址
certificate-authority-data用于验证 API Server 服务端证书的 CA
users[].user客户端认证凭据,如证书、Token、exec 插件
contexts[]把集群、用户、命名空间组合成一个使用场景
current-context默认使用哪个上下文

所以 kubeconfig 本身不是证书,但它通常内嵌或引用证书。

kubeconfig 里的 server 可以随便改吗#

不能随便改。

server 字段必须同时满足两个条件:

  1. 网络上能连到 API Server。
  2. 这个地址出现在 API Server 服务端证书的 SAN 里,或者被客户端信任。

例如把:

server: https://10.0.0.10:6443

改成:

server: https://api.example.com:6443

如果 api.example.com 指向同一个 API Server,但 API Server 证书没有包含这个 DNS 名称,仍然会失败。

如果只是为了临时验证,可以使用不安全参数跳过 TLS 校验,但这不应该作为正式方案。

正式方案应该是:

  • 在初始化集群时把稳定入口写入 API Server 证书 SAN。
  • 或者重新签发包含新地址的 API Server 证书。
  • 并确保 kubeconfigserver 使用同一个稳定入口。

kubeadm 里几个关键参数#

使用 kubeadm 初始化集群时,和证书/API Server 地址关系最密切的是这些参数。

--control-plane-endpoint#

这个参数指定控制平面的稳定访问入口。

它通常应该是:

  • 负载均衡器地址。
  • 稳定 DNS 名称。
  • 高可用控制平面的虚拟 IP。

示例:

kubeadm init \
  --control-plane-endpoint api.example.com:6443

它解决的问题是:

客户端和新加入的节点应该通过哪个稳定地址找控制平面?

--apiserver-advertise-address#

这个参数指定 API Server 对外声明自己监听在哪个本机地址上。

它通常是当前控制平面节点的内网 IP。

示例:

kubeadm init \
  --apiserver-advertise-address 10.0.0.10

它更偏节点本地视角,不等同于集群外部访问入口。

--apiserver-cert-extra-sans#

这个参数给 API Server 服务端证书增加额外 SAN。

如果希望通过某个额外 DNS 或 IP 访问 API Server,就应该把它放进来:

kubeadm init \
  --control-plane-endpoint api.example.com:6443 \
  --apiserver-cert-extra-sans api.example.com \
  --apiserver-cert-extra-sans 203.0.113.10

它解决的问题是:

TLS 客户端校验证书时,哪些地址可以被认为是这个 API Server?

三个地址不要混淆#

Kubernetes 集群里经常同时出现多个 API Server 相关地址:

地址类型常见位置含义
本机监听地址--apiserver-advertise-address控制平面节点本身的 API Server 地址
稳定控制平面入口--control-plane-endpoint客户端和节点加入集群时使用的稳定入口
kubeconfig serverclusters[].cluster.server当前客户端实际访问的 API Server 地址

理想情况下:

kubeconfig server 使用稳定入口;
稳定入口能路由到 API Server;
API Server 证书 SAN 包含这个稳定入口。

这样集群后续扩容、迁移、负载均衡调整时,客户端配置才不容易散掉。

kubeadm 生成了哪些配置#

kubeadm init 会生成一批 kubeconfig 文件,通常位于:

/etc/kubernetes/admin.conf
/etc/kubernetes/controller-manager.conf
/etc/kubernetes/scheduler.conf
/etc/kubernetes/kubelet.conf

这些文件服务于不同身份:

文件主要用途
admin.conf管理员访问集群
controller-manager.confcontroller-manager 访问 API Server
scheduler.confscheduler 访问 API Server
kubelet.confkubelet 访问 API Server

它们都属于 kubeconfig,只是使用者不同。

证书过期和续期#

kubeadm 支持查看和续期证书。

查看证书过期时间:

kubeadm certs check-expiration

手动续期:

kubeadm certs renew all

需要注意:

  • 续期通常需要在每个控制平面节点上处理。
  • 证书续期后,相关静态 Pod 或组件需要重新加载证书。
  • kubeadm certs renew 会以现有证书属性作为权威来源,包括 CN、组织和 SAN。

因此,如果一开始证书 SAN 就缺少某个外部访问域名,单纯续期不一定能自动补上这个域名。

常见排查思路#

1. 先看 kubeconfig server#

kubectl config view --minify

重点看:

clusters:
  - cluster:
      server: https://...

确认它到底在连哪个地址。

2. 再看网络是否可达#

curl -vk https://api.example.com:6443/readyz

如果完全连不上,先查网络、负载均衡、安全组、防火墙、端口监听。

如果能连上但 TLS 报错,再看证书。

3. 检查 API Server 证书 SAN#

在控制平面节点上:

openssl x509 \
  -in /etc/kubernetes/pki/apiserver.crt \
  -noout \
  -text | grep -A1 "Subject Alternative Name"

确认 kubeconfig 里的 server 地址是否出现在 SAN 中。

4. 确认 CA 是否匹配#

如果 kubeconfig 里的 CA 不是签发 API Server 证书的 CA,也会失败。

可以用 opensslkubectl config view --raw 检查内嵌证书内容。

一个稳定的实践模型#

生产或长期使用的集群,建议一开始就确定稳定控制平面入口。

例如:

api.example.com -> LB/VIP -> control-plane nodes:6443

初始化时:

kubeadm init \
  --control-plane-endpoint api.example.com:6443 \
  --apiserver-cert-extra-sans api.example.com

然后对外分发的 kubeconfig 使用:

server: https://api.example.com:6443

这样三件事对齐:

  • DNS 或 VIP 是稳定入口。
  • API Server 证书信任这个入口。
  • 客户端通过这个入口访问。

常见误解#

误解一:能 ping 通就说明 API Server 可以访问#

不是。

API Server 是 HTTPS 服务,关键是 TCP 6443 和 TLS 校验。

很多负载均衡器或云服务域名本身也不一定响应 ICMP,所以 ping 不通不代表 API Server 不可用。

误解二:改 kubeconfig server 就能切换到新入口#

不一定。

新入口必须在网络上可达,并且 API Server 证书 SAN 覆盖这个地址。

误解三:证书只是加密,和地址没关系#

不对。

服务端证书不仅用于加密,还用于证明当前访问的 DNS 或 IP 属于这个服务。

误解四:证书续期一定会修复 SAN 问题#

不一定。

续期通常沿用现有证书属性。如果要新增 SAN,需要按 kubeadm 证书管理方式重新生成或调整配置后处理。

小结#

可以把这条链路记成一句话:

kubeconfig 选择地址和身份;
API Server 证书证明这个地址可信;
CA 决定客户端是否信任这张证书;
API Server 再根据认证和授权决定请求能做什么。

排查 API Server 连接问题时,先分层:

  1. 地址是否正确。
  2. 网络是否可达。
  3. 证书 SAN 是否匹配。
  4. CA 是否匹配。
  5. 用户身份是否有权限。

这样就不会把网络问题、TLS 问题和 RBAC 问题混在一起。

参考资料#

本文共 3720 字,创建于 May 6, 2026

相关标签: Kubernetes, DevOps, ByAI