Kops创建的AWS Kubernetes集群Prometheus监控证书IP SANs验证失败
你遇到的问题核心是Prometheus用IP访问kubelet的10250端口时,kubelet的证书不包含该IP作为Subject Alternative Name(SAN),导致x509证书验证失败。而且你的Prometheus配置存在一些混淆点,我来一步步帮你理清并解决:
1. 先明确目标:你抓取的是kubelet,不是API Server
报错里的x.x.x.x:10250/metrics是kubelet的指标端口,而非Kubernetes API Server的默认端口(6443)。你配置里的role: node是用来发现集群节点并抓取kubelet指标的,但api_server字段在这里其实是多余的——这个配置项通常用于API Server自身的指标抓取,而非node角色的自动发现场景。
2. 解决证书IP SAN缺失的问题
kops自动生成的kubelet证书默认只会包含节点的主机名作为SAN,不会自动添加节点IP。所以当Prometheus用IP访问时,证书验证就会失败。你有几个可行的解决方向:
方法一:修改kops配置,让kubelet证书包含节点IP
通过kops更新集群配置,强制kubelet证书生成时包含节点IP:
- 编辑集群配置:
kops edit cluster <你的集群名称> - 在配置中添加或修改kubelet的
certificateSANs字段(如果没有则新增):kubelet: certificateSANs: - "<节点IP>" # 多节点场景可逐个添加IP;若使用自动扩缩容节点,也可配置`additionalSANs`让kops自动注入节点IP - 应用配置更新并滚动重启节点:
滚动更新完成后,kubelet的证书就会包含节点IP作为SAN,此时用IP访问就能通过验证。kops update cluster <你的集群名称> --yes kops rolling-update cluster <你的集群名称> --yes
方法二:让Prometheus用节点主机名访问kubelet
既然kubelet证书里有节点的主机名SAN,那可以修改Prometheus的配置,用节点的FQDN而非IP来访问:
- 如果你用Kubernetes服务发现(
kubernetes_sd_configs: [{role: node}]),Prometheus默认会获取节点的主机名,只需确保tls_config里的server_name匹配节点主机名,或者直接去掉server_name让Prometheus自动匹配目标主机名。 - 如果是静态配置targets,把IP换成节点的FQDN即可。
方法三:临时绕过证书验证(不推荐生产环境)
如果只是测试场景,可以在tls_config里添加insecure_skip_verify: true跳过证书验证,但这会带来安全风险,生产环境绝对不建议这么做:
tls_config: ca_file: '/opt/prometheus-2.1.0.linux-amd64/ca.crt' server_name: kubernetes insecure_skip_verify: true
3. 检查kubelet证书的SAN信息
你之前查看的是CA证书(ca.crt),但报错是针对kubelet的服务端证书。可以登录到节点上,查看kubelet的证书内容确认SAN:
openssl x509 -text -noout -in /var/lib/kubelet/pki/kubelet-server.crt
找到Subject Alternative Name字段,确认是否包含节点的IP或主机名——这能帮你验证证书是否符合预期。
4. 修正Prometheus的节点抓取配置
给你一个更标准的Prometheus节点抓取配置示例,用Kubernetes服务发现自动获取节点,并使用service account token认证(kubelet默认支持这种方式,比basic_auth更安全):
- job_name: 'kubernetes-nodes' kubernetes_sd_configs: - role: node scheme: https tls_config: ca_file: '/opt/prometheus-2.1.0.linux-amd64/ca.crt' bearer_token_file: '/var/run/secrets/kubernetes.io/serviceaccount/token' relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+)
内容的提问来源于stack exchange,提问作者vinodh

