Skip to content

第一部分 K8s 网络进阶

网络是 Kubernetes 中最复杂的部分之一。本部分深入讲解 CNI 原理、Service 实现细节、CoreDNS 机制、Ingress 控制器和网络策略。


第 1 章 Kubernetes 网络模型与 CNI 原理

1.1 K8s 网络模型要求

K8s 网络模型要求:

  1. 所有 Pod 可以直接通信,无需 NAT
  2. 节点上的 Agent 可以与所有 Pod 通信
  3. Pod 看到的自己的 IP 与其他 Pod 看到的一致

这意味着 Pod IP 必须是可路由的,或者通过 Overlay 网络实现逻辑直连。

1.2 CNI 简介

CNI(Container Network Interface)是容器网络接口标准,定义了容器如何获取网络配置。

CNI 工作流程:

容器运行时(containerd/CRI-O)
    |
    v
调用 CNI 插件(如 bridge、calico、cilium)
    |
    v
创建 veth pair,分配 IP,设置路由

1.3 常见 CNI 对比

CNI特点适用场景
Flannel简单,使用 VXLAN 或 host-gw中小型集群
Calico支持 BGP、NetworkPolicy、WireGuard中大型集群,需要网络策略
Cilium基于 eBPF,高性能,可观测性强大规模集群,安全要求高
Weave易用,自动发现小型集群
AntreaVMware 出品,基于 OVS与 NSX-T 集成

1.4 Calico 网络模式

Calico 支持三种数据面:

模式说明
BGP与物理网络交换路由,Pod IP 可直接路由
VXLANOverlay 网络,无需底层网络支持
WireGuard加密 Overlay
bash
# 查看 Calico 节点状态
kubectl get nodes -o wide
kubectl get pods -n calico-system -o wide

# 查看 BGP 对等体
kubectl exec -it calico-node-xxx -n calico-system -- calicoctl node status

1.5 Cilium 与 eBPF

Cilium 使用 eBPF 替代 iptables 实现网络、安全和可观测性。

优势:

  • 高性能(绕过 netfilter)
  • 强大的安全策略(L3/L4/L7)
  • 内置 Hubble 可观测性
  • 支持 WireGuard 加密
bash
# 安装 Cilium
helm install cilium cilium/cilium --namespace kube-system

# 查看 Cilium 状态
cilium status

1.6 本章实验

实验 1-1:查看 Pod 网络命名空间

bash
# 找到 Pod 所在节点和容器 ID
kubectl get pod <POD> -o wide
kubectl describe pod <POD> | grep -i "Container ID"

# 在节点上查看网络命名空间
ls /var/run/netns/

# 使用 nsenter 进入 Pod 网络命名空间
nsenter -t <PID> -n ip addr

1.7 本章练习

  1. 解释 K8s 网络模型的三个要求。
  2. 比较 Flannel、Calico、Cilium 的优缺点。
  3. 在实验集群中部署 Calico 或 Cilium。
  4. 查看一个 Pod 的 veth pair 和路由表。

第 2 章 Service 实现原理深度解析

2.1 Service 的本质

Service 不是真实存在的网络实体,而是一组 iptables/ipvs/eBPF 规则的集合。

2.2 ClusterIP 的 IP 分配

ClusterIP 从 --service-cluster-ip-range 指定的 CIDR 中分配。

bash
# 查看 API Server 配置
ps aux | grep kube-apiserver | grep service-cluster-ip-range
# --service-cluster-ip-range=10.96.0.0/12

2.3 kube-proxy 的三种模式

模式实现特点
userspacekube-proxy 作为用户态代理已废弃
iptables使用 iptables DNAT稳定,适合中小规模
ipvs使用 IPVS高性能,适合大规模

2.4 iptables 模式详解

访问 ClusterIP 时的数据流:

Pod A (10.244.1.2) -> Service nginx (10.96.123.45:80)
    |
    v
iptables KUBE-SERVICES 链
    |
    v
KUBE-SVC-XXX 链(Service 链)
    |
    v
KUBE-SEP-XXX 链(Endpoint 链)
    |
    v
DNAT 到 Pod IP: 10.244.2.5:80

查看规则:

bash
# 查看 Service 规则
iptables -t nat -L KUBE-SERVICES | grep nginx

# 查看 Endpoint 规则
iptables -t nat -L KUBE-SVC-XXX

2.5 ipvs 模式详解

bash
# 查看 ipvs 规则
ipvsadm -Ln

# 输出示例
# TCP  10.96.123.45:80 rr
#   -> 10.244.1.5:80              Masq    1      0          0
#   -> 10.244.2.7:80              Masq    1      0          0

ipvs 支持算法:

  • rr:轮询
  • lc:最少连接
  • dh:目标地址哈希
  • sh:源地址哈希
  • sed:最短预期延迟
  • nq:永不排队

2.6 无头服务(Headless Service)

Headless Service 不分配 ClusterIP,DNS 直接返回后端 Pod IP。

yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-headless
spec:
  selector:
    app: nginx
  clusterIP: None
  ports:
  - port: 80

DNS 解析结果:

bash
nslookup nginx-headless
# 返回所有 Pod IP:10.244.1.5, 10.244.2.7

适用于:

  • StatefulSet 的服务发现
  • 客户端负载均衡
  • 需要直接访问 Pod 的场景

2.7 Service 的会话亲和性

yaml
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

2.8 本章实验

实验 2-1:追踪 Service 流量路径

bash
# 1. 创建 Deployment 和 Service
kubectl create deployment nginx --image=nginx:1.25 --replicas=2
kubectl expose deployment nginx --port=80 --target-port=80

# 2. 查看 Service ClusterIP
kubectl get svc nginx

# 3. 查看 Endpoints
kubectl get endpoints nginx

# 4. 切换到 ipvs 模式(如果当前是 iptables)
kubectl edit configmap kube-proxy -n kube-system
# 修改 mode: "ipvs"
kubectl rollout restart daemonset kube-proxy -n kube-system

# 5. 查看 ipvs 规则
ipvsadm -Ln | grep nginx

# 6. 从 Pod 内多次访问 Service,观察流量分发
kubectl run test --image=busybox:1.36 -it --rm --restart=Never -- sh
for i in $(seq 1 10); do wget -qO- http://nginx; done

2.9 本章练习

  1. 解释 iptables 模式和 ipvs 模式的区别。
  2. 查看你集群中 kube-proxy 的工作模式。
  3. 创建一个 Headless Service 并观察 DNS 解析结果。
  4. 配置 Service 的会话亲和性并测试。

第 3 章 CoreDNS 与 K8s DNS

3.1 K8s DNS 架构

Pod 发起 DNS 查询
    |
    v
/etc/resolv.conf 中的 nameserver: 10.96.0.10
    |
    v
CoreDNS Service (kube-dns)
    |
    v
CoreDNS Pod 处理查询
    |
    v
返回 Service/Pod IP 或转发到上游 DNS

3.2 CoreDNS 配置

yaml
# CoreDNS ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }

3.3 DNS 解析规则

名称解析结果
service同命名空间 Service 的 ClusterIP
service.namespace其他命名空间 Service 的 ClusterIP
service.namespace.svc.cluster.localFQDN 解析
pod-ip.namespace.pod.cluster.localPod IP

3.4 CoreDNS 性能调优

  • 增加 CoreDNS 副本数
  • 使用 NodeLocal DNSCache
  • 调整缓存 TTL
  • 优化上游 DNS
bash
# 部署 NodeLocal DNSCache
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml

3.5 常见 DNS 问题排查

bash
# 测试 DNS
kubectl run -it --rm debug --image=busybox:1.36 -- nslookup kubernetes.default

# 查看 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns

# 查看 /etc/resolv.conf
kubectl run -it --rm debug --image=busybox:1.36 -- cat /etc/resolv.conf

3.6 本章练习

  1. 查看 CoreDNS 的 ConfigMap 配置。
  2. 测试不同格式的 Service DNS 解析。
  3. 部署 NodeLocal DNSCache 并观察效果。
  4. 模拟一个 DNS 解析失败场景并排查。

第 4 章 Ingress 控制器深度解析

4.1 Ingress 控制器种类

控制器特点
NGINX Ingress Controller最常用,功能全面
Traefik云原生,动态配置
HAProxy Ingress高性能
KongAPI 网关能力
Istio Ingress Gateway服务网格集成
Emissary基于 Envoy

4.2 NGINX Ingress Controller 架构

外部流量
    |
    v
LoadBalancer/NodePort Service
    |
    v
NGINX Ingress Controller Pod
    |
    v
根据 Ingress 规则路由到后端 Service
    |
    v
后端 Pod

4.3 Ingress 高级配置

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

4.4 IngressClass

IngressClass 用于指定使用哪个 Ingress 控制器。

yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx

4.5 Gateway API

Gateway API 是 Ingress 的下一代标准,提供更强大的流量管理能力。

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
spec:
  gatewayClassName: example-gateway-class
  listeners:
  - name: http
    protocol: HTTP
    port: 80

4.6 本章练习

  1. 部署 NGINX Ingress Controller。
  2. 配置基于路径和域名的路由规则。
  3. 配置 HTTPS 证书。
  4. 了解 Gateway API 与 Ingress 的区别。

第 5 章 网络策略(NetworkPolicy)实战

5.1 NetworkPolicy 基础

NetworkPolicy 用于控制 Pod 之间的网络流量。

默认行为:

  • 没有 NetworkPolicy 时,所有 Pod 之间允许互通
  • 一旦某个 Pod 被 NetworkPolicy 选中,只有策略允许的流量才能通过

5.2 默认拒绝策略

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

5.3 允许特定流量

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

5.4 Cilium 的 L7 策略

Cilium 支持基于 HTTP/HTTP2/gRPC 的 L7 策略:

yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: l7-policy
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:
        - method: GET
          path: "/api/.*"

5.5 本章练习

  1. 在命名空间内实施默认拒绝策略。
  2. 只允许 frontend Pod 访问 backend Pod 的 8080 端口。
  3. 使用 Cilium 配置 HTTP 级别的访问控制。
  4. 测试策略是否生效。

第一部分总结

完成本阶段学习后,你应该能够:

  • 理解 K8s 网络模型和 CNI 原理
  • 对比不同 CNI 的实现和适用场景
  • 深入理解 Service 的 iptables/ipvs 实现
  • 排查 CoreDNS 和 DNS 问题
  • 部署和配置 Ingress 控制器
  • 使用 NetworkPolicy 实现网络隔离

进入第二部分:高级调度与资源管理