GKE获取Pod日志时出现无效证书错误,如何解决?
我尝试从GKE集群中的Pod获取日志,执行kubectl logs pleiades-0 -c server -n pleiades时遇到了以下500错误,具体日志如下:
I0117 11:42:54.468501 96671 round_trippers.go:466] curl -v -XGET -H "Accept: application/json, */*" -H "User-Agent: kubectl/v1.26.0 (darwin/arm64) kubernetes/b46a3f8" 'https://x.x.x.x/api/v1/namespaces/pleiades/pods/pleiades-0/log?container=server' I0117 11:42:54.569122 96671 round_trippers.go:553] GET https://x.x.x.x/api/v1/namespaces/pleiades/pods/pleiades-0/log?container=server 500 Internal Server Error in 100 milliseconds I0117 11:42:54.569170 96671 round_trippers.go:570] HTTP Statistics: GetConnection 0 ms ServerProcessing 100 ms Duration 100 ms I0117 11:42:54.569186 96671 round_trippers.go:577] Response Headers: I0117 11:42:54.569202 96671 round_trippers.go:580] Content-Type: application/json I0117 11:42:54.569215 96671 round_trippers.go:580] Content-Length: 226 I0117 11:42:54.569229 96671 round_trippers.go:580] Date: Tue, 17 Jan 2023 19:42:54 GMT I0117 11:42:54.569243 96671 round_trippers.go:580] Audit-Id: a25a554f-c3f5-4f91-9711-3f2970376770 I0117 11:42:54.569332 96671 round_trippers.go:580] Cache-Control: no-cache, private I0117 11:42:54.571392 96671 request.go:1154] Response Body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Get \"https://10.6.128.40:10250/containerLogs/pleiades/pleiades-0/server\": x509: certificate is valid for 127.0.0.1, not 10.6.128.40","code":500} I0117 11:42:54.572267 96671 helpers.go:246] server response object: [{ "metadata": {}, "status": "Failure", "message": "Get \"https://10.6.128.40:10250/containerLogs/pleiades/pleiades-0/server\": x509: certificate is valid for 127.0.0.1, not 10.6.128.40", "code": 500 }]
请问如何防止这个问题再次发生?
这个错误的核心原因是:Kubernetes API Server尝试访问节点上的kubelet(端口10250)拉取容器日志时,kubelet的SSL证书仅包含127.0.0.1作为有效域名/IP,没有包含节点的内部IP(也就是错误里的10.6.128.40),导致证书验证失败。
针对GKE这个托管Kubernetes环境,以下是解决和预防这个问题的具体方案:
1. 禁用手动修改kubelet配置(推荐)
GKE默认会自动为每个节点的kubelet生成包含节点内部IP、主机名等必要SAN(Subject Alternative Names)的证书。如果您之前通过自定义节点池的启动脚本、直接登录节点修改过kubelet的参数(比如--tls-cert-file、--tls-private-key-file或--cert-dir),会覆盖GKE的默认证书生成逻辑,导致证书缺少关键的IP信息。
解决办法:
- 恢复节点的默认kubelet配置,移除所有手动添加的证书相关参数;
- 后续所有节点配置变更都通过GKE节点池的官方参数(如自定义元数据、启动脚本仅用于非核心配置)来管理,不要直接修改kubelet的核心证书配置。
2. 替换异常节点(快速临时修复)
如果只有个别节点出现这个问题,大概率是节点初始化时证书生成过程中出现了异常。您可以直接删除该节点,GKE会自动创建新的节点,并正确生成包含所有必要SAN的kubelet证书:
# 先找到Pod所在的节点名称 kubectl describe pod pleiades-0 -n pleiades | grep Node: # 删除有问题的节点 kubectl delete node <problem-node-name>
3. 验证集群CA和kubelet证书链(针对自定义CA场景)
如果您的GKE集群使用了自定义根CA(而不是GKE默认的CA),需要确保kubelet的证书是由这个自定义CA签发的,并且证书的SAN字段包含节点的内部IP和主机名。您可以通过以下命令检查节点上的kubelet证书信息:
# 登录到节点(需要GKE节点的SSH权限) gcloud compute ssh <node-name> # 查看kubelet证书的SAN信息 openssl x509 -in /var/lib/kubelet/pki/kubelet.crt -text | grep -A 1 "Subject Alternative Name"
如果证书缺少节点IP,需要重新生成kubelet证书并签署正确的SAN,或者调整自定义CA的签发逻辑。
预防措施
- 避免直接修改节点上的kubelet配置:GKE是托管服务,核心组件的配置由Google维护,手动修改容易破坏证书生成流程;
- 定期检查节点状态:使用
kubectl describe node <node-name>查看kubelet的状态,确认证书相关配置正常; - 升级到最新稳定版GKE:Google会持续修复证书生成相关的bug,新版本的集群会更可靠地处理kubelet证书的SAN配置。
内容的提问来源于stack exchange,提问作者Sienna

