跳转至

4. 集群网络配置

网络是 Kubernetes 的核心,也是最容易出问题的地方。本章将详细介绍 K3s 的默认网络方案 (Flannel),以及如何通过 NetworkPolicy 进行网络隔离。

4.1 网络模型基础

K3s 默认使用 Flannel 作为 CNI (Container Network Interface) 插件,采用 VXLAN 模式进行节点间通信。

  • Pod CIDR: 10.42.0.0/16 (每个节点分配一个子网,如 Node1 用 10.42.0.0/24)
  • Service CIDR: 10.43.0.0/16 (服务的虚拟 IP 地址段)

4.1.1 常用启动参数解析

在安装 K3s 时,可以通过参数自定义网络网段。这对避免与宿主机内网冲突至关重要。

curl -sfL https://get.k3s.io | sh -s - server \
  --cluster-cidr=10.42.0.0/16 \
  --service-cidr=10.43.0.0/16 \
  --flannel-backend=vxlan

参数详解: * --cluster-cidr: Pod 的 IP 地址范围。 * 注意:不能与物理机所在的内网网段冲突。 * --service-cidr: Service 的虚拟 IP 地址范围。 * --flannel-backend: Flannel 的后端模式。 * vxlan (默认): 将二层以太网帧封装在 UDP 包中。兼容性好,无需特殊网络设备支持。 * host-gw: 通过主机路由表转发。性能更好(无封装开销),但要求所有节点在同一二层网络(同网段)。 * wireguard-native: 使用 WireGuard 协议加密节点间流量。适合跨公网组网。

4.2 NetworkPolicy 网络策略

默认情况下,K3s 集群内所有 Pod 都可以相互访问(全通)。为了安全,我们需要限制访问。K3s 内置了 Kube-Router 来实施网络策略。

4.2.1 拒绝所有流量 (默认拒绝)

首先,我们创建一个策略,拒绝某个命名空间下的所有入站流量。

创建 manifests/04-network/deny-all.yaml:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {} # 空选择器匹配所有 Pod
  policyTypes:
  - Ingress # 限制入站流量

配置详解: * podSelector: {}: 这是一个通配符,表示该 Namespace 下的所有 Pod 都受此策略影响。 * policyTypes: ["Ingress"]: 声明该策略仅控制入站流量(Ingress),不影响出站(Egress)。

4.2.2 允许特定服务访问

假设我们有一个 backend 服务,只允许 frontend 服务访问。

创建 manifests/04-network/allow-frontend.yaml:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-access
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend # 目标:保护 backend 应用
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend # 来源:只允许 frontend 标签的 Pod
    ports:
    - protocol: TCP
      port: 80 # 端口:只开放 80 端口

参数详解: * spec.podSelector: 定义策略作用于谁(这里是 app: backend)。 * ingress.from: 定义流量来源白名单。 * podSelector: 基于 Pod 标签选择源。 * namespaceSelector: 基于 Namespace 标签选择源(例如允许来自 prod 命名空间的流量)。 * ipBlock: 基于 IP CIDR 允许外部流量。

4.3 故障排查:网络不通怎么办?

当遇到 Pod 间无法 ping 通或 Service 无法访问时,按以下步骤排查:

  1. 检查节点状态

    kubectl get nodes -o wide
    # 确保 Internal-IP 正确,且状态为 Ready
    

  2. 检查 Flannel 接口: 在节点上执行 ip addr,确认是否存在 flannel.1cni0 接口。

    • cni0: 容器网桥,Pod 的 veth 对连接到这里。
    • flannel.1: VXLAN 隧道接口。
  3. 检查 IP 冲突: 查看日志 journalctl -u k3s | grep "Failed to allocate"。如果 Cluster CIDR 与宿主机网络重叠,会导致路由混乱。

  4. 抓包分析

    # 在 Flannel 接口抓包 UDP 8472 (VXLAN 端口)
    tcpdump -i any udp port 8472 -nn