1. 问题现象与背景分析
最近在维护Kubernetes集群时,发现执行kubectl top nodes或kubectl top pods命令时,系统返回了"metrics not available yet"的错误提示。这个问题直接影响了我们对集群资源使用情况的监控,也导致基于Metrics的HPA自动扩缩容功能无法正常工作。
Metrics Server作为Kubernetes集群的核心组件之一,主要负责从各节点的kubelet收集资源指标数据(CPU、内存等),并通过metrics.k8s.io API暴露给其他组件使用。当这个组件出现问题时,整个集群的资源监控体系就会瘫痪。
2. 初步排查步骤
2.1 检查Metrics Server运行状态
首先,我们需要确认metrics-server是否正常运行:
bash复制kubectl get pods -n kube-system | grep metrics-server
如果Pod状态不是Running,可能需要检查日志:
bash复制kubectl logs -n kube-system deployment/metrics-server
2.2 验证API服务注册
Metrics Server需要正确注册metrics.k8s.io API:
bash复制kubectl get apiservices v1beta1.metrics.k8s.io -o yaml
正常情况下应该看到类似这样的输出:
yaml复制apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
port: 443
version: v1beta1
versionPriority: 100
2.3 检查RBAC权限
Metrics Server需要足够的权限来访问节点指标:
bash复制kubectl get clusterrole system:metrics-server -o yaml
kubectl get clusterrolebinding metrics-server:system:metrics-server -o yaml
3. 深入问题排查
3.1 检查kubelet连接配置
Metrics Server通过kubelet的API获取指标数据,常见的连接问题包括:
- TLS证书问题:在测试环境中,可以添加
--kubelet-insecure-tls参数临时跳过证书验证 - 地址类型问题:确保配置了正确的kubelet地址类型:
yaml复制args:
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
3.2 验证指标数据链路
完整的指标数据链路是:容器运行时 → cAdvisor → kubelet → metrics-server → API server
我们可以逐步验证这个链路:
- 首先检查节点上的cAdvisor指标:
bash复制kubectl get --raw /api/v1/nodes/<node-name>/proxy/metrics/cadvisor
- 然后检查kubelet的summary API:
bash复制kubectl get --raw /api/v1/nodes/<node-name>/proxy/stats/summary
- 最后直接查询metrics API:
bash复制kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
4. cgroup相关问题的排查
4.1 检查cgroup版本
cgroup版本不匹配是常见问题之一:
bash复制stat -fc %T /sys/fs/cgroup/
- 输出
cgroup2fs表示使用cgroup v2 - 输出
tmpfs表示使用cgroup v1
4.2 确保cgroup驱动一致性
Kubernetes组件和容器运行时必须使用相同的cgroup驱动:
- 检查kubelet配置:
bash复制cat /var/lib/kubelet/config.yaml | grep cgroupDriver
- 检查containerd配置:
bash复制cat /etc/containerd/config.toml | grep SystemdCgroup
正确的配置应该是:
toml复制[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
4.3 处理cgroup v2兼容性问题
如果必须使用cgroup v1,可以修改GRUB配置:
bash复制# 编辑/etc/default/grub
GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=0"
# 更新GRUB
sudo update-grub
sudo reboot
5. 高级问题排查
5.1 PodAndContainerStatsFromCRI特性
Kubernetes 1.18+引入了PodAndContainerStatsFromCRI特性,当启用时:
yaml复制featureGates:
PodAndContainerStatsFromCRI: true
这会导致kubelet直接从容器运行时获取统计信息,绕过cAdvisor。这种情况下:
kubectl top nodes可能正常工作kubectl top pods可能失败
解决方案是禁用此特性:
yaml复制featureGates:
PodAndContainerStatsFromCRI: false
然后重启kubelet:
bash复制sudo systemctl restart kubelet
5.2 网络连接问题
检查metrics-server能否访问各节点的kubelet:
bash复制kubectl exec -n kube-system metrics-server-xxxxxx -- curl -k https://<node-ip>:10250/metrics/resource
如果连接失败,可能需要:
- 检查网络策略
- 检查节点防火墙规则
- 验证kubelet的证书配置
6. 解决方案总结
根据上述排查,常见的解决方案包括:
-
调整metrics-server启动参数:
yaml复制args: - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname -
统一cgroup驱动:
- 确保kubelet和容器运行时都使用systemd驱动
- 对于cgroup v2,确保组件版本兼容
-
禁用PodAndContainerStatsFromCRI特性:
yaml复制featureGates: PodAndContainerStatsFromCRI: false -
检查并修复RBAC权限:
bash复制
kubectl auth can-i list nodes --as=system:serviceaccount:kube-system:metrics-server -
验证网络连接:
- 确保metrics-server Pod可以访问所有节点的kubelet
- 检查网络策略和防火墙规则
7. 验证问题是否解决
执行以下命令验证指标是否可用:
bash复制kubectl top nodes
kubectl top pods -A
也可以直接查询metrics API:
bash复制kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/pods" | jq
8. 经验分享与注意事项
在实际运维中,我总结了以下几点经验:
-
生产环境慎用--kubelet-insecure-tls:
- 测试环境可以临时使用这个参数
- 生产环境应该配置正确的TLS证书
-
版本兼容性很重要:
- 确保metrics-server版本与Kubernetes版本兼容
- 特别注意cgroup v2需要较新的组件版本
-
监控metrics-server:
- 为metrics-server设置监控告警
- 定期检查日志中的错误信息
-
性能考量:
- 大型集群可能需要调整metrics-server的资源请求
- 考虑设置
--metric-resolution参数调整指标采集频率
-
备选方案:
- 可以考虑使用Prometheus + kube-state-metrics作为备用监控方案
- 对于特殊需求,可以部署自定义的metrics adapter
9. 常见问题速查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| metrics not available yet | metrics-server未运行 | 检查metrics-server Pod状态 |
| 只有节点指标没有Pod指标 | PodAndContainerStatsFromCRI启用 | 禁用该特性 |
| 部分节点指标缺失 | 网络连接问题 | 检查节点防火墙和网络策略 |
| 证书错误 | kubelet证书配置问题 | 使用--kubelet-insecure-tls或配置正确证书 |
| 权限不足 | RBAC配置错误 | 检查ClusterRole和ClusterRoleBinding |
| cgroup驱动不一致 | kubelet和容器运行时驱动不同 | 统一使用systemd驱动 |
10. 进一步优化建议
-
调整采集间隔:
yaml复制args: - --metric-resolution=30s -
资源限制:
yaml复制resources: requests: cpu: 100m memory: 200Mi limits: cpu: 200m memory: 500Mi -
高可用部署:
yaml复制strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate replicas: 2 -
日志级别调整:
yaml复制args: - --v=4 -
节点选择:
yaml复制affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: node-role.kubernetes.io/control-plane operator: DoesNotExist
通过以上全面的排查和优化,应该能够解决绝大多数"metrics not available yet"的问题,并建立一个稳定可靠的集群监控基础。在实际操作中,建议记录详细的排查过程,这对日后处理类似问题会有很大帮助。