一、问题场景还原
当将Kubernetes的Service类型从ClusterIP改为NodePort后,理论上应通过<节点IP>:<NodePort>
访问服务。但在实际生产环境中,常会遇到访问失败的情况。以部署Prometheus监控栈为例,Grafana服务修改为NodePort后无法访问,以下是完整的排查与解决方案。
二、基础环境检查
1. 确认Service配置正确
kubectl get svc grafana -n monitoring
期望输出:
NAME TYPE CLUSTER-IP PORT(S) AGE
grafana NodePort 10.96.112.113 3000:31735/TCP 5h
验证点:
TYPE
必须为NodePort
PORT(S)
列需显示<集群端口>:<NodePort>/<协议>
2. 检查NodePort端口范围
Kubernetes默认NodePort范围为 30000-32767。若需自定义范围,需修改kube-apiserver配置:
# 查看kube-apiserver配置
ps aux | grep kube-apiserver | grep service-node-port-range
查看和调整默认NodePort端口范围方式参考:Kubernetes生产实战:NodePort端口范围的隐藏规则与调优指南-CSDN博客
生产建议:保持默认范围,避免与系统端口冲突。
三、关键故障排查步骤
1. 节点防火墙与安全组
核心问题:云厂商安全组或节点iptables未开放NodePort端口。
验证方法:
# 在集群节点执行
nc -zv <节点IP> 31735
# 或从外部测试
telnet <节点IP> 31735
修复方案:
- 云服务器控制台:添加安全组规则,允许
31735/TCP
入站 - 本地防火墙(若有):
sudo iptables -A INPUT -p tcp --dport 31735 -j ACCEPT sudo systemctl restart iptables
2. 网络策略(NetworkPolicy)拦截
现象:当集群启用网络插件(如Calico、Cilium)时,NetworkPolicy可能限制入口流量。
诊断命令:
kubectl get networkpolicy -n monitoring
临时解决方案:
kubectl delete networkpolicy --all -n monitoring
生产环境建议:不要直接删除所有策略! 应针对性调整策略:
# grafana-networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: grafana-external-access
namespace: monitoring
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: grafana
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0 # 生产环境应限制为特定IP段
3. kube-proxy服务异常
排查方法:
# 检查kube-proxy日志
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=100
# 确认iptables规则存在
sudo iptables-save | grep 31735
典型问题:
- kube-proxy未正常运行
- iptables/nftables规则被误删
修复方案:
# 重启kube-proxy
kubectl rollout restart ds -n kube-system kube-proxy
4. Pod就绪状态与Endpoint
关键检查点:
# 确认Pod处于Running状态
kubectl get pods -n monitoring -l app.kubernetes.io/name=grafana
# 查看Endpoint是否分配
kubectl get endpoints grafana -n monitoring
异常处理:
- 若Endpoint为空,检查Service的selector是否匹配Pod标签
- Pod未就绪时排查资源限制、探针配置
四、生产环境高级优化方案
1. 使用Ingress替代直接暴露NodePort
优势:
- 统一管理外部访问
- 支持HTTPS、路由规则等
示例配置(Nginx Ingress):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: monitoring
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: grafana.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
2. 服务质量保障
就绪探针配置:
# grafana-deployment.yaml片段 readinessProbe: httpGet: path: /api/health port: 3000 initialDelaySeconds: 10 periodSeconds: 5
资源限制:
resources: limits: cpu: "1" memory: 1Gi requests: cpu: "0.5" memory: 512Mi
3. 安全加固
限制NodePort访问源:
# 使用iptables限制IP sudo iptables -A INPUT -p tcp --dport 31735 -s 192.168.1.0/24 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 31735 -j DROP
定期轮换NodePort端口:
kubectl patch svc grafana -n monitoring -p '{"spec":{"ports":[{"port":3000,"nodePort":31000}]}}'
五、总结排查流程图
六、技术冷知识
- NodePort实现原理:kube-proxy通过监听API Server,动态维护iptables/IPVS规则,将NodePort流量转发到后端Pod。
- 为什么默认端口范围是30000-32767:避免与Linux系统端口(0-1023)和用户端口(1024-29999)冲突。
- NetworkPolicy的隐藏影响:即使没有显式定义NetworkPolicy,某些CNI插件(如Calico)的默认拒绝策略也可能阻断流量。