Qingular

网络故障排查

·CKAk8s练习

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 CrashLoopBackOffkubectl 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,
# 未在规则中明确允许的流量都会被拒绝

排错思路:

  1. 检查目标 Pod 所在命名空间是否有 NetworkPolicy
  2. 检查 NetworkPolicy 的 podSelector 是否选择了目标 Pod
  3. 检查 ingress 规则是否允许来源 Pod 的 IP/标签
  4. 检查 egress 规则是否允许目标 Pod 的 IP/标签
  5. 如果 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_vsip_vs_rrip_vs_wrrip_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 CrashLoopBackOffCNI 未正确配置 Pod 网络检查 CNI 配置
Node NotReadyCNI 插件未部署按照 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 默认拒绝所有未允许的流量,检查是否存在策略阻止

官方文档