网络故障排查
CKA 考试 Domain 5 — Service 不通、DNS 解析、CoreDNS、NetworkPolicy、kube-proxy、CNI 排查
← 返回 CKA 练习目录 Kubernetes 网络涉及多个层次:Pod 网络、Service 网络、DNS 解析、网络策略等。CKA 考试中网络故障是难点也是重点。
1. Service 无法访问排查步骤
# Step 1: 检查 Service 是否创建
kubectl get svc
# Step 2: 检查 Service 是否有 Endpoints
kubectl get endpoints <service-name>
# 如果 Endpoints 为空,说明 Service 的 Selector 没有匹配到 Pod
# Step 3: 检查 Service 的后端 Pod 是否正常运行
kubectl get pods -l <service-selector>
# Step 4: 检查 Pod 是否监听在正确的端口
kubectl exec -it <pod-name> -- netstat -tlnp
# Step 5: 在集群内部测试 Service 访问
kubectl run test --image=busybox -it --rm -- wget -qO- http://<service-name>.<namespace>.svc.cluster.local
# Step 6: 检查 kube-proxy
kubectl get pods -n kube-system | grep kube-proxy
排查流程图:
Service 不通
│
├─ kubectl get endpoints <svc> 是否非空?
│ ├─ 空 → Selector 不匹配 Pod
│ └─ 非空 → 继续
│
├─ 从集群内 Pod 访问 Service
│ ├─ 不通 → 检查 kube-proxy
│ └─ 通 → 检查外部访问配置
│
├─ 检查 kube-proxy 是否正常
├─ 检查 CNI 插件
└─ 检查防火墙/安全组
2. DNS 解析问题
CoreDNS Pod 状态检查
# 检查 CoreDNS Pod 是否运行
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 检查 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns
# 检查 CoreDNS 配置
kubectl get configmap -n kube-system coredns -o yaml
# 检查 CoreDNS Service
kubectl get svc -n kube-system kube-dns
DNS 解析测试
# 使用 busybox 测试 DNS 解析
kubectl run dns-test --image=busybox:1.28 --rm -it -- nslookup kubernetes.default.svc.cluster.local
# 使用 nslookup
kubectl run dns-test --image=busybox:1.28 --rm -it -- nslookup kubernetes
# 使用 dig
kubectl run dns-test --image=dig --rm -it -- dig kubernetes.default.svc.cluster.local
# 测试外部域名解析
kubectl run dns-test --image=busybox:1.28 --rm -it -- nslookup www.google.com
注意:busybox 1.28 的 nslookup 比新版 busybox 更稳定。如果使用默认 latest 版本 nslookup 可能失败。
CoreDNS 故障常见原因
| 问题 | 排查 | 解决 |
|---|---|---|
| CoreDNS Pod 未运行 | kubectl get pods -n kube-system | 检查 Pod 状态和日志 |
| CoreDNS CrashLoopBackOff | kubectl logs -n kube-system coredns-xxx | 检查 ConfigMap 配置 |
| CoreDNS 内存不足 | kubectl describe pod -n kube-system coredns-xxx | 调整资源限制 |
| DNS 超时 | 检查网络连通性 | 检查 kube-proxy 和 CNI |
| 自定义域名解析失败 | 检查 CoreDNS ConfigMap | 添加 rewrite 或 forward 规则 |
3. 网络连通性测试
# 创建测试 Pod
kubectl run test --image=busybox --rm -it -- sh
# 在测试 Pod 中:
# 测试 Service 连通性
wget -qO- http://<service-name>
wget -qO- http://<service-name>.<namespace>.svc.cluster.local
# 测试 Pod IP 连通性(需要知道 Pod IP)
wget -qO- http://<pod-ip>:<port>
# 测试节点端口
wget -qO- http://<node-ip>:<node-port>
4. NetworkPolicy 阻止流量排查
# 查看所有 NetworkPolicy
kubectl get networkpolicy
# 查看 NetworkPolicy 详情
kubectl describe networkpolicy <policy-name>
# 测试是否被 NetworkPolicy 阻止
# 开启临时 Pod 测试
kubectl run test-pod --image=busybox --rm -it -- sh
# 在 test-pod 中测试目标 Pod
wget -qO- http://<target-pod-ip>:<port>
# 查看 NetworkPolicy 的影响范围
# NetworkPolicy 是"白名单"机制,一旦有 NetworkPolicy 选择到 Pod,
# 未在规则中明确允许的流量都会被拒绝
排错思路:
- 检查目标 Pod 所在命名空间是否有 NetworkPolicy
- 检查 NetworkPolicy 的
podSelector是否选择了目标 Pod - 检查
ingress规则是否允许来源 Pod 的 IP/标签 - 检查
egress规则是否允许目标 Pod 的 IP/标签 - 如果 NetworkPolicy 存在但不允许该流量,添加对应规则
5. kube-proxy 模式与问题
# 检查 kube-proxy Pod 状态
kubectl get pods -n kube-system -l k8s-app=kube-proxy
# 查看 kube-proxy 日志
kubectl logs -n kube-system kube-proxy-<node> --tail=50
# 检查 kube-proxy 配置
kubectl get configmap -n kube-system kube-proxy -o yaml
# 检查 kube-proxy 模式(iptables / IPVS / userspace)
kubectl get configmap -n kube-system kube-proxy -o yaml | grep mode
kube-proxy 模式对比:
| 模式 | 说明 | 性能 |
|---|---|---|
iptables | 默认模式,基于 iptables 规则转发 | 中等 |
IPVS | 基于 IPVS,支持更多负载均衡算法 | 高(大规模集群) |
userspace | 用户空间代理(已弃用) | 低 |
常见问题:
- kube-proxy 未运行 → Service 的 ClusterIP 无法访问
- iptables 规则被意外修改 →
systemctl restart kube-proxy或重启 Pod - IPVS 模式下缺少内核模块 → 加载
ip_vs、ip_vs_rr、ip_vs_wrr、ip_vs_sh模块
# 检查 IPVS 内核模块
lsmod | grep ip_vs
# 检查 iptables 规则
iptables-save | grep <service-name>
6. CNI 插件问题排查
# 查看 CNI Pod 状态
kubectl get pods -n kube-system | grep -E "calico|flannel|weave|cilium"
# 查看 CNI 日志
kubectl logs -n kube-system -l k8s-app=calico-node --tail=50
# 检查 CNI 配置文件
ls /etc/cni/net.d/
# 检查 CNI 二进制文件
ls /opt/cni/bin/
# 查看节点网络接口
ip a
ip route
常见 CNI 问题:
| 问题 | 原因 | 解决 |
|---|---|---|
| Pod 间无法通信 | CNI 插件异常 | 重启 CNI DaemonSet |
| CoreDNS CrashLoopBackOff | CNI 未正确配置 Pod 网络 | 检查 CNI 配置 |
| Node NotReady | CNI 插件未部署 | 按照 CNI 文档部署 |
| Pod IP 冲突 | CNI IP 池耗尽 | 检查 IPAM 配置 |
7. 节点端口连通性测试
# 从节点本地测试
curl http://localhost:<node-port>
# 从集群内其他节点测试
curl http://<node-ip>:<node-port>
# 从集群外测试
telnet <node-ip> <node-port>
# 使用 nc 测试端口
nc -zv <node-ip> <node-port>
8. 实用命令速查
# 查看 Service 和 Endpoints
kubectl get svc,ep
# 查看所有网络策略
kubectl get netpol --all-namespaces
# 创建临时测试 Pod
kubectl run test --image=busybox -it --rm -- sh
# 测试内部 DNS
kubectl run test --image=busybox:1.28 --rm -it -- nslookup kubernetes.default
# 查看 kube-proxy 日志
kubectl logs -n kube-system -l k8s-app=kube-proxy
# 查看 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns
# 检查 kubelet 是否配置了正确的 node IP
kubectl describe node <node-name>
9. 考试要点
- Service 不通时先检查 Endpoints
- DNS 解析问题首选检查 CoreDNS Pod 状态
- 使用
busybox:1.28测试 DNS(新版 busybox nslookup 有问题) - NetworkPolicy 是白名单机制,一旦选择到 Pod,默认拒绝所有未允许的流量
- kube-proxy 异常会导致 Service 的 ClusterIP 不可达
- CNI 插件异常会导致 Pod 网络不通
🧪 完整操作实例:排查 Service 无法访问问题
场景描述
新创建一个 Service 后,从集群内部的其他 Pod 无法通过 Service 名称访问目标 Pod,完整的端到端排查过程。
前置条件
- 集群中有多个 Pod 和 Service
- 有创建临时测试 Pod 的权限
操作步骤
Step 1: 确认 Service 状态
kubectl get svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
# my-app-service ClusterIP 10.108.12.34 <none> 80/TCP 5m
kubectl describe svc my-app-service
# Name: my-app-service
# Namespace: default
# Labels: app=my-app
# Selector: app=my-app,tier=frontend
# Type: ClusterIP
# IP Family Policy: SingleStack
# IP Families: IPv4
# IP: 10.108.12.34
# Port: http 80/TCP
# TargetPort: 80/TCP
# Endpoints: <none> ← Endpoints 为空!
# Session Affinity: None
# Events: <none>
Step 2: 发现 Endpoints 为空——检查 Selector 匹配
# 查看 Service 的 Selector 选择器
# Selector: app=my-app,tier=frontend
# 检查是否存在匹配标签的 Pod
kubectl get pods -l app=my-app,tier=frontend
# No resources found in default namespace.
# 查看所有 Pod 的标签
kubectl get pods --show-labels
# NAME READY STATUS RESTARTS AGE LABELS
# my-app-6b8f9c7d8b-abc12 1/1 Running 0 10m app=my-app
# my-app-6b8f9c7d8b-def34 1/1 Running 0 10m app=my-app
# ← Pod 只有 app=my-app,缺少 tier=frontend 标签!
Step 3: 修复标签匹配问题
# 为 Pod 添加缺少的标签
kubectl label pod -l app=my-app tier=frontend --overwrite
# pod/my-app-6b8f9c7d8b-abc12 labeled
# pod/my-app-6b8f9c7d8b-def34 labeled
# 验证 Endpoints 已更新
kubectl get endpoints my-app-service
# NAME ENDPOINTS AGE
# my-app-service 10.244.1.2:80,10.244.1.3:80 6m
Step 4: 从另一个 Pod 测试 Service 连通性
# 创建测试 Pod
kubectl run test-pod --image=busybox --rm -it -- sh
# 如果进入交互式环境,执行:
# wget -qO- http://my-app-service
# 或使用非交互方式:
kubectl run test-pod --image=busybox --rm -it -- wget -qO- http://my-app-service
# <!DOCTYPE html>
# <html>...(正常返回 HTML)
Step 5: 检查 DNS 解析(如果 Service 名称解析失败)
kubectl run dns-test --image=busybox:1.28 --rm -it -- nslookup my-app-service
# Server: 10.96.0.10
# Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
#
# Name: my-app-service
# Address 1: 10.108.12.34 my-app-service.default.svc.cluster.local
# → DNS 解析正常,返回正确的 ClusterIP
Step 6: 检查 kube-proxy 是否正常(如果 Endpoints 存在但仍无法访问)
kubectl get pods -n kube-system -l k8s-app=kube-proxy
# NAME READY STATUS RESTARTS AGE
# kube-proxy-abc12 1/1 Running 0 10d
# kube-proxy-def34 1/1 Running 0 10d
# 查看 kube-proxy 日志
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=20
# 日志应无错误,否则重启对应节点上的 kube-proxy
Step 7: 检查 NetworkPolicy 是否阻止流量
kubectl get networkpolicy --all-namespaces
# NAMESPACE NAME POD-SELECTOR AGE
# default deny-all {} 5d
# → 有 NetworkPolicy 存在!
kubectl describe networkpolicy deny-all
# PodSelector: <empty> (选择所有 Pod)
# Policy Types: Ingress
# Ingress: <none> ← 没有任何入站规则,默认拒绝所有入站流量
发现有一条 deny-all 策略拒绝所有入站流量,需要添加允许规则。
# 添加允许 ingress 的 NetworkPolicy
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-service-access
spec:
podSelector:
matchLabels:
app: my-app
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
EOF
Step 8: 再次验证访问
kubectl run test-pod --image=busybox --rm -it -- wget -qO- http://my-app-service
# <!DOCTYPE html>
# <html>...(成功返回)
验证结果
# 验证 Service Endpoints
kubectl get endpoints my-app-service
# NAME ENDPOINTS AGE
# my-app-service 10.244.1.2:80,10.244.1.3:80 10m
# 验证 DNS 解析
kubectl run dns-test --image=busybox:1.28 --rm -it -- nslookup my-app-service.default.svc.cluster.local
# 验证完整通信链路 (Service → Pod)
kubectl exec test-pod -- wget -qO- http://my-app-service | head -5
考试提示
- Service 无法访问时先检查 Endpoints是否为空,空则说明 Selector 不匹配 Pod
- Selector 标签必须完全匹配(所有 label 都需存在)
- kube-proxy 异常会导致 ClusterIP 无法访问,检查
kube-system命名空间下的 kube-proxy Pod - DNS 测试使用
busybox:1.28,新版 busybox 的 nslookup 可能不可用 - NetworkPolicy 默认拒绝所有未允许的流量,检查是否存在策略阻止