一、当Kubernetes网络突然罢工时
想象一下这样的场景:你正喝着咖啡,突然收到告警说集群里的服务全都失联了。这时候千万别慌,我们先来做个快速检查:
# 查看所有节点的网络状态(技术栈:kubectl)
kubectl get nodes -o wide
# 如果看到某个节点状态为NotReady,可能是网络插件挂了
# 检查核心DNS服务是否正常
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 如果CoreDNS的Pod显示CrashLoopBackOff,八成是网络问题
这种情况最常见的就是Calico这类CNI插件抽风。上周我们生产环境就遇到过,某个节点的IPIP隧道莫名其妙断了。这时候可以试试这个万能重启大法:
# 暴力但有效的Calico重启方案(技术栈:kubectl+ssh)
kubectl delete pod -n kube-system -l k8s-app=calico-node
# 等2分钟后,如果还没恢复就手动ssh到问题节点
ssh node01 "systemctl restart kubelet && systemctl restart docker"
二、那些年我们踩过的Service网络坑
Service的ClusterIP突然不通了?这事儿我遇到过不下十次。先分享个诊断黄金命令组合:
# 全方位Service检查套餐(技术栈:kubectl+iptables)
kubectl describe svc your-service # 先看Endpoint对不对
iptables -t nat -L -n -v | grep your-service # 检查iptables规则
kubectl run -it --rm debug --image=busybox --restart=Never -- ping <ClusterIP>
# 如果连busybox都ping不通,基本可以确定是kube-proxy的锅
记得有次半夜被叫起来处理故障,就是因为有人手贱改了kube-proxy的配置模式:
# 错误示范:在iptables模式下强制启用IPVS(技术栈:kube-proxy配置)
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs" # 但节点内核没加载ip_vs模块
正确的做法应该是先检查内核模块:
# 正确的IPVS模式前置检查(技术栈:shell)
lsmod | grep ip_vs
# 如果没有输出,需要先加载模块:
modprobe -- ip_vs && modprobe -- ip_vs_rr
三、Pod之间怎么突然就失联了
当两个Pod明明在同一个节点却无法互相ping通时,我建议按照这个检查清单来:
- 首先确认基础网络:
# 检查Pod基础网络(技术栈:kubectl+nsenter)
kubectl exec -it pod1 -- ping <pod2_ip>
# 如果失败,进入Pod网络命名空间检查路由
PID=$(docker inspect -f '{{.State.Pid}}' <container_id>)
nsenter -t $PID -n ip route
- 然后检查网络策略:
# 查看是否有NetworkPolicy限制(技术栈:kubectl)
kubectl get networkpolicy --all-namespaces
# 特别注意带有'deny-all'标签的策略
- 最后杀手锏——直接抓包:
# 在目标节点上抓取Pod网络流量(技术栈:tcpdump)
tcpdump -i cali+ -nn -vvv host <pod_ip>
# 如果看到TCP SYN包但没回应,可能是防火墙拦截
去年我们有个经典案例:某个命名空间下的所有Pod突然无法访问数据库。最后发现是有人部署了这样的网络策略:
# 过于严格的NetworkPolicy示例(技术栈:K8s NetworkPolicy)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-deny-all
spec:
podSelector:
matchLabels:
app: mysql
policyTypes:
- Ingress
ingress: [] # 这个空数组表示拒绝所有入站!
四、DNS解析那些让人头大的事
CoreDNS抽风绝对是K8s网络故障的TOP3选手。先分享几个实用诊断命令:
# DNS问题诊断组合拳(技术栈:kubectl+busybox)
kubectl run -it --rm dns-test --image=busybox:1.28 --restart=Never -- nslookup kubernetes.default
# 如果报错,检查CoreDNS日志:
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100
常见的一个坑是NodeLocal DNSCache配置不当。有次我们集群所有Pod的解析延迟飙升到2秒,最后发现是这个配置有问题:
# NodeLocal DNSCache的错误配置示例(技术栈:K8s DNS)
apiVersion: v1
kind: ConfigMap
metadata:
name: nodelocaldns
data:
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30 # 成功缓存记录数设置过大
denial 9984 5 # 导致OOM被杀
}
}
正确的调整姿势应该是:
# 推荐的缓存配置(技术栈:K8s DNS)
cache {
success 2048 30 # 根据实际业务量调整
denial 1024 5 # 默认值通常就够用
}
五、跨节点网络通信的隐秘角落
当Pod跨节点通信出现问题时,这个检查流程能救你命:
- 先确认基础连通性:
# 跨节点网络测试(技术栈:kubectl+ping)
kubectl run -it --rm node1-pod --image=alpine --overrides='{"spec": {"nodeName": "node1"}}' -- ping <node2_ip>
kubectl run -it --rm node2-pod --image=alpine --overrides='{"spec": {"nodeName": "node2"}}' -- ping <node1_ip>
- 检查CNI插件配置:
# Calico网络检查(技术栈:calicoctl)
calicoctl get workloadendpoints -o wide
# 重点看跨节点路由是否正确发布
- MTU问题排查:
# 检查各节点MTU设置(技术栈:ip+ssh)
ip link show | grep mtu
# 如果节点间MTU不一致(特别是用了IPIP时),会导致大包被丢弃
上周刚解决一个典型案例:某金融客户的生产环境突然出现跨节点TCP连接随机失败。最后发现是安全组规则限制了VXLAN端口:
# 错误的AWS安全组配置示例(技术栈:AWS CLI)
aws ec2 describe-security-groups --group-ids sg-xxx | grep 8472
# 应该放行UDP 8472(Flannel VXLAN)和TCP 179(Calico BGP)
六、实战中的疑难杂症解决方案
分享几个压箱底的故障处理经验:
- 诡异的DNS间歇性超时:
# 检查conntrack表溢出(技术栈:Linux诊断)
sysctl net.netfilter.nf_conntrack_count
# 如果接近net.netfilter.nf_conntrack_max,需要调大限制
- Service突然不可用:
# 检查kube-proxy的sync-proxy规则延迟(技术栈:metrics)
kubectl get --raw /metrics | grep sync_proxy_rules_latency_microseconds
# 如果P99值超过1秒,考虑优化节点规格
- 大规模集群的etcd网络瓶颈:
# 检查etcd网络指标(技术栈:etcdctl)
etcdctl endpoint status --write-out=table
# 重点关注"raft term"频繁变化和"errors"计数
记得有次处理一个200节点的集群故障,最终发现是有人把Prometheus的抓取间隔设成了1秒,把apiserver打爆了:
# 错误的监控配置示例(技术栈:Prometheus)
scrape_configs:
- job_name: 'kubernetes-apiservers'
scrape_interval: 1s # 对于大集群这简直是自杀行为
metrics_path: /metrics
七、防患于未然的网络运维建议
根据多年填坑经验,总结这些最佳实践:
- 定期网络健康检查:
# 创建定时网络诊断任务(技术栈:K8s CronJob)
apiVersion: batch/v1
kind: CronJob
metadata:
name: network-check
spec:
schedule: "0 3 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: checker
image: network-tools
command: ["/bin/sh", "-c", "ping -c 3 kubernetes.default && curl -I https://google.com"]
- 关键网络组件资源预留:
# CoreDNS资源保障配置(技术栈:K8s资源管理)
resources:
limits:
memory: 256Mi
cpu: 500m
requests:
memory: 128Mi
cpu: 100m # 避免CPU饥饿导致DNS超时
- 多可用区部署的特别注意事项:
# 检查跨AZ网络延迟(技术栈:ping+分析)
kubectl run -it --rm az-test --image=alpine --overrides='{"spec": {"nodeSelector": {"topology.kubernetes.io/zone": "az1"}}}' -- ping <az2_pod_ip>
# 如果延迟>2ms,建议启用服务拓扑感知路由
八、写在最后的经验之谈
处理K8s网络问题就像侦探破案,这里分享我的"破案"心得:
- 永远先检查最基础的网络连通性,别一上来就怀疑CNI插件
- 善用临时诊断Pod,busybox/alpine/curl这些镜像就是你的瑞士军刀
- 重要变更一定要在非生产环境先验证,特别是CNI插件升级
- 监控这些关键指标:DNS查询延迟、节点网络丢包率、etcd写入延迟
- 文档!文档!文档!所有网络配置变更必须记录,血泪教训
最后送大家一个万能检查清单命令:
# K8s网络终极检查命令集(技术栈:混合)
check_k8s_network() {
echo "=== 节点状态 ==="
kubectl get nodes -o wide
echo "\n=== Pod网络 ==="
kubectl get pods -n kube-system -l k8s-app=calico-node
echo "\n=== DNS检查 ==="
kubectl run -it --rm check-dns --image=busybox --restart=Never -- nslookup kubernetes.default
echo "\n=== Service检查 ==="
kubectl get svc --all-namespaces
echo "\n=== 网络策略 ==="
kubectl get networkpolicy --all-namespaces
}
评论