k8s Calico CNI 实践与探索 – wiki基地


Kubernetes Calico CNI 实践与探索:构建高性能、安全的云原生网络

摘要:

随着 Kubernetes (k8s) 成为容器编排领域的事实标准,其网络模型的选择和实践变得至关重要。CNI (Container Network Interface) 作为 Kubernetes 网络的核心规范,涌现了众多实现方案。其中,Calico 以其高性能、丰富的网络策略和对多种网络环境的适应性脱颖而出,成为生产环境中最受欢迎的 CNI 插件之一。本文将深入探讨 Calico CNI 的核心概念、架构、工作原理,并结合实践案例,分享其安装配置、网络策略应用、高级功能探索以及故障排查经验,旨在为读者提供一份详尽的 Calico CNI 实践指南。

一、 引言:Kubernetes 网络与 CNI 的挑战

Kubernetes 极大地简化了容器化应用的部署、扩展和管理,但其网络模型相对复杂。它要求:

  1. Pod 间通信: 集群内所有 Pod 能够直接相互通信,无需 NAT。
  2. 节点与 Pod 通信: 集群内所有节点能够直接与所有 Pod 通信,反之亦然,无需 NAT。
  3. Pod IP 唯一性: Pod 看到的自身 IP 地址与其他 Pod 或节点看到的 IP 地址相同。

为了实现这些目标并提供灵活性,Kubernetes 设计了 CNI 规范。CNI 定义了一套标准的接口,允许不同的网络插件来实现容器网络的创建、配置和销毁。这使得用户可以根据自身需求(如性能、安全、功能集)选择最合适的网络解决方案。

然而,选择和实施 CNI 并非易事。不同的 CNI 插件在架构、性能、功能和运维复杂度上差异显著。例如,Flannel 提供了简单的 Overlay 网络,易于上手;而 Calico 则提供了更强大的 Layer 3 网络和精细化的网络策略,但配置和理解可能更复杂。

二、 Calico CNI 核心概念与架构

Calico 是一个开源的、高度可扩展的网络和网络安全解决方案,专为云原生环境(如 Kubernetes、OpenShift、OpenStack 等)设计。其核心设计理念是利用标准的 Layer 3 网络协议(如 BGP)来路由 Pod 流量,并提供强大的分布式防火墙能力来实现网络策略。

2.1 核心组件:

  • Felix: Calico 的核心代理,运行在每个计算节点(Kubernetes Node)上。它负责维护节点的路由表、ACL(访问控制列表)、网络接口等,以确保 Pod 网络的连通性和安全性。Felix 从 etcd 或 Kubernetes API Server 读取配置信息,并将网络策略转换为底层 Linux 内核(如 iptables、ipsets 或 eBPF)能理解的规则。
  • BIRD (BGP Client): 一个流行的开源 BGP 路由守护进程。在 Calico 中,BIRD 运行在每个节点上(通常与 Felix 一起),负责通过 BGP 协议分发路由信息。节点间的 Pod CIDR 路由通过 BGP 宣告,使得跨节点的 Pod 流量可以直接路由,无需封装。
  • Typha (可选): 为了提高大规模集群的可扩展性,Typha 作为 Felix 和数据存储(如 K8s API Server)之间的代理存在。多个 Felix 实例可以连接到同一个 Typha 实例,从而减少对 K8s API Server 的直接连接数和负载。
  • calico-cni (CNI 插件): 符合 CNI 规范的二进制文件。当 Kubelet 创建或删除 Pod 时,它会调用 calico-cni 插件。该插件负责为 Pod 创建网络命名空间、分配 IP 地址(通过 Calico IPAM)、设置 veth pair 并将其一端连接到 Pod,另一端连接到宿主机的网络命名空间,并调用 Felix 配置相应的路由和策略。
  • calicoctl: Calico 的命令行工具,用于查看 Calico 状态、配置资源(如 IP 池、网络策略、BGP 配置等)以及进行故障排查。
  • 数据存储: Calico 需要一个数据存储来持久化其配置和状态信息。最常用的方式是直接使用 Kubernetes API Server (etcd) 作为数据存储,这简化了部署。也可以使用独立的 etcd 集群。

2.2 网络模型:

Calico 主要支持以下几种网络模型:

  1. BGP 模式 (No Overlay / Native Layer 3): 这是 Calico 最具特色的模式。每个节点运行 BGP 客户端 (BIRD),并将分配给本节点 Pod 的 IP 地址段(Pod CIDR)通过 BGP 协议宣告给集群中的其他节点或网络路由器。

    • Node-to-Node Mesh (默认): 每个 Calico 节点都与其他所有 Calico 节点建立 BGP 对等连接(Peer)。适用于中小型集群。
    • Route Reflector (路由反射器): 对于大型集群,Node-to-Node Mesh 会导致 BGP 连接数过多。可以配置一或多个节点作为 BGP Route Reflector,其他节点只与 Route Reflector 建立 BGP 连接,由 Route Reflector 负责将路由信息反射给其他对等体。
    • Peering with Network Infrastructure: Calico 节点可以直接与物理网络设备(如 ToR 交换机、路由器)建立 BGP 连接,将 Pod IP 路由直接发布到物理网络,实现 Pod 与物理网络的无缝集成。

    优点:
    * 高性能: 流量通常直接路由,没有封装/解封装的开销。
    * 网络可见性: Pod IP 在网络中是可路由的,便于监控和故障排查。
    * 标准化: 使用标准的 BGP 协议,易于与现有网络集成。
    缺点:
    * 依赖底层网络: 要求底层网络支持 Calico 节点间的 IP 可达(通常是二层可达),并且能够承载 BGP 流量。对于不支持 BGP 或有严格限制的网络环境(如某些公有云 VPC 的子网间路由限制),可能需要额外配置或无法使用。

  2. IP-in-IP 模式 (Overlay): 当底层网络不支持 BGP 或节点间无法直接路由时,可以使用 IP-in-IP 封装。跨节点 Pod 流量会被封装在一个外部 IP 头(源/目的为节点 IP)中进行传输。
    优点:

    • 兼容性好: 对底层网络要求低,几乎可以在任何 IP 网络上运行。
      缺点:
    • 性能损耗: 存在封装/解封装开销,略低于 BGP 模式。
    • MTU 问题: 封装会增加包头大小,可能需要调整 Pod 和节点的 MTU (Maximum Transmission Unit) 以避免分片。
  3. VXLAN 模式 (Overlay): 另一种流行的 Overlay 网络技术。VXLAN 将 L2 帧封装在 UDP 包中进行传输,可以跨越 L3 网络。
    优点:

    • 兼容性好: 同样对底层网络要求低。
    • 功能特性: 支持更大的网络规模(VNI),更容易穿透某些防火墙。
      缺点:
    • 性能损耗: 同样存在封装/解封装开销。
    • MTU 问题: 封装开销比 IP-in-IP 更大,MTU 调整更需注意。
  4. 混合模式: Calico 也支持根据需要混合使用不同的模式,例如,在同一集群内,某些节点间使用 BGP,而与其他节点间使用 Overlay。

2.3 网络策略:

Calico 的网络策略是其核心优势之一。它不仅完全兼容 Kubernetes 原生的 NetworkPolicy API,还提供了更强大、更灵活的扩展策略:

  • Kubernetes NetworkPolicy: 基于 Namespace、Pod Label Selector 和 IP Block 定义 L3/L4 的访问控制规则(Ingress/Egress)。
  • Calico GlobalNetworkPolicy: 作用域是整个集群,不限于特定 Namespace。可以用于定义全局的默认策略(如默认拒绝所有流量)或控制对集群范围资源(如 KubeDNS)的访问。
  • Calico NetworkPolicy: 功能上与 Kubernetes NetworkPolicy 类似,但提供了更多高级特性,如:
    • 更丰富的匹配条件(Service Account、HTTP 属性等,需配合特定集成)。
    • 策略执行顺序 (Order 字段)。
    • deny 规则的显式支持。
    • log 动作的支持,方便审计。
  • HostEndpoint: Calico 可以将策略应用于宿主机节点本身的网卡接口。这使得可以控制节点与 Pod 之间、节点与外部网络之间的流量,甚至保护节点本身的服务端口。

Calico 网络策略通过 Felix 在每个节点上转换为高效的防火墙规则(如 iptables 或 eBPF),实现分布式的策略执行,避免了流量集中处理的瓶颈。

三、 Calico CNI 实践:安装与配置

3.1 环境准备:

  • 一个正常运行的 Kubernetes 集群。
  • 确保 Kubelet 配置了 --network-plugin=cni
  • 如果使用 BGP 模式,确保节点间 IP 可达。
  • 如果选择使用 Kubernetes API Server 作为数据存储,确保 Calico 组件有访问 API Server 的权限(通过 ServiceAccount 和 RBAC)。

3.2 安装 Calico:

推荐使用 Calico 官方提供的 Manifest 文件或 Operator 进行安装。

  • 使用 Manifest:

    1. 从 Calico 官方文档下载适用于你的 Kubernetes 版本和所选数据存储(K8s API 或 etcd)的 Manifest 文件(通常是一个 YAML 文件,如 calico.yamltigera-operator.yaml + custom-resources.yaml)。
    2. (可选) 根据需要修改 Manifest 文件中的配置,例如:
      • CALICO_IPV4POOL_CIDR: 设置 Pod 的 IP 地址池范围。
      • CALICO_IPV4POOL_IPIP: 配置 IP-in-IP 模式(AlwaysNeverCrossSubnet)。
      • CALICO_IPV4POOL_VXLAN: 配置 VXLAN 模式(AlwaysNeverCrossSubnet)。
      • FELIX_IPV6SUPPORT: 启用 IPv6 支持。
      • 配置 Typha (如果需要)。
    3. 使用 kubectl apply -f <manifest_file.yaml> 应用配置。
  • 使用 Tigera Operator:

    1. 安装 Tigera Operator: kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/vX.Y.Z/manifests/tigera-operator.yaml (替换 X.Y.Z 为目标版本)。
    2. 创建一个 Installation Custom Resource (CR) 文件(如 custom-resources.yaml),在其中定义 Calico 的配置,例如:
      yaml
      apiVersion: operator.tigera.io/v1
      kind: Installation
      metadata:
      name: default
      spec:
      calicoNetwork:
      ipPools:
      - cidr: 192.168.0.0/16 # Pod IP 地址池
      encapsulation: VXLANCrossSubnet # 跨子网时使用 VXLAN
      natOutgoing: Enabled
      nodeSelector: all()
      # ... 其他配置,如 CNI 插件类型 (Calico), 组件资源限制等
    3. 应用 CR: kubectl apply -f custom-resources.yaml

3.3 验证安装:

“`bash

检查 Calico 相关 Pod 是否都处于 Running 状态

kubectl get pods -n calico-system # 或 tigera-operator 命名空间

检查 Calico 节点状态

需要先安装 calicoctl 工具: https://docs.tigera.io/calico/latest/operations/calicoctl/install

sudo calicoctl node status

部署测试 Pod,检查 Pod 是否能获取 IP 地址并相互通信

kubectl run busybox –image=busybox –restart=Never — sleep 3600
kubectl run nginx –image=nginx –restart=Never –labels app=nginx
kubectl exec busybox — ping
“`

3.4 常见配置调整:

  • IPAM (IP Address Management):

    • IP Pool: Calico 使用 IP Pool 来管理 Pod 的 IP 地址。可以创建多个 IP Pool,并使用 nodeSelector 将特定的 Pool 关联到特定的节点。
      “`bash
      # 查看 IP Pool
      sudo calicoctl get ippool default-ipv4-ippool -o yaml

    # 创建新的 IP Pool
    cat <<EOF | sudo calicoctl create -f –
    apiVersion: projectcalico.org/v3
    kind: IPPool
    metadata:
    name: new-ippool
    spec:
    cidr: 10.20.0.0/16
    ipipMode: Never
    vxlanMode: Always
    natOutgoing: true
    nodeSelector: “rack == ‘frontend'” # 只用于打了 rack=frontend 标签的节点
    EOF
    “`
    * IP 地址块大小 (Block Size): Calico IPAM 以块 (Block) 为单位向节点分配 IP 地址段。默认块大小通常是 /26。可以调整块大小以平衡 IP 地址利用率和 IPAM 分配开销。

  • MTU 自动检测: Calico 通常会自动检测底层网络的 MTU 并相应调整 Pod 接口的 MTU(特别是在使用 Overlay 时)。如果自动检测不准确,可以通过 FELIX_IPINIPMTUFELIX_VXLANMTU 等环境变量手动设置。

  • BGP 配置:

    • ASN (Autonomous System Number): 默认情况下,所有 Calico 节点共享同一个私有 ASN (如 64512)。可以为每个节点或节点组配置不同的 ASN。
    • BGP Peerings: 使用 BGPConfigurationBGPPeer 资源来配置 BGP 设置,如 Route Reflector 或与外部路由器建立 Peering。
      “`yaml
      # 示例:将某个节点配置为 Route Reflector
      apiVersion: projectcalico.org/v3
      kind: Node
      metadata:
      name: k8s-node-rr-1 # 路由反射器节点名
      spec:
      bgp:
      routeReflectorClusterID: “224.0.0.1” # 集群 ID

    # 示例:与外部路由器建立 Peering
    apiVersion: projectcalico.org/v3
    kind: BGPPeer
    metadata:
    name: peer-with-tor-router
    spec:
    peerIP: 192.168.1.1 # 外部路由器 IP
    asNumber: 65001 # 外部路由器的 ASN
    nodeSelector: “all()” # 所有 Calico 节点都与其 Peering
    ``
    * **查看 BGP 状态:**
    sudo calicoctl node status` 会显示 BGP Peer 的连接状态。

四、 Calico 网络策略实践

网络策略是保障 Kubernetes 集群安全的关键。

4.1 默认策略:

最佳实践是实施“默认拒绝”策略,然后显式允许必要的流量。

“`yaml

示例:默认拒绝所有 Ingress 流量 (Kubernetes NetworkPolicy)

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: my-namespace # 应用到特定命名空间
spec:
podSelector: {} # 选择该命名空间下的所有 Pod
policyTypes:
– Ingress

示例:全局默认拒绝 (Calico GlobalNetworkPolicy)

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: default-deny-all
spec:
order: 100 # 较高的 order 值,使其在其他允许策略之后评估(如果需要先拒绝)
selector: “all()” # 应用于所有 Pod 和 HostEndpoint
types:
– Ingress
– Egress
# 没有 ingress 或 egress 规则,意味着拒绝所有
“`

4.2 允许特定流量:

在默认拒绝的基础上,创建策略允许必要的通信。

“`yaml

示例:允许同一命名空间内 app=frontend 的 Pod 访问 app=backend 的 Pod 的 80 端口

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

示例:允许特定 Namespace (e.g., monitoring) 访问所有 Pod 的 metrics 端口 (9100)

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-monitoring-access
spec:
order: 50 # 较低的 order 值,优先评估
selector: “all()” # 应用于所有 Pod
ingress:
– action: Allow
protocol: TCP
source:
namespaceSelector: “projectcalico.org/name == ‘monitoring'” # 选择 monitoring 命名空间
destination:
ports:
– 9100
types:
– Ingress
“`

4.3 保护 HostEndpoint:

保护节点本身的网络接口和端口。

“`bash

为节点创建 HostEndpoint 资源

sudo calicoctl create -f – <<EOF
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: k8s-node-1-eth0 # 自定义名称
labels:
node-role: worker
environment: production
spec:
interfaceName: eth0 # 节点上的网卡名
node: k8s-node-1 # 节点名称
expectedIPs: [“10.0.0.10”] # 节点 IP (可选,用于校验)
EOF

创建策略,只允许特定 IP 访问节点的 SSH 端口 (22)

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-ssh-from-bastion
spec:
order: 10
selector: “has(node-role)” # 选择所有定义了 HostEndpoint 的节点
ingress:
– action: Allow
protocol: TCP
source:
nets: [“/32″] # 堡垒机 IP
destination:
ports:
– 22
types:
– Ingress
“`

4.4 策略验证与日志:

  • 使用 calicoctl get networkpolicy, calicoctl get globalnetworkpolicy 查看策略。
  • 利用 Calico 策略的 log action 来记录被匹配(允许或拒绝)的流量,方便调试和审计。
    “`yaml
    # … policy definition …
    ingress:

    • action: Log # 记录匹配的流量

    … rest of the rule …

    • action: Allow

    … rest of the rule …

    “`
    日志通常输出到节点的 syslog 或指定文件中,具体取决于 Felix 的配置。

五、 高级功能探索

5.1 eBPF 数据平面:

Calico 支持使用 eBPF (Extended Berkeley Packet Filter) 作为其数据平面,替代传统的 iptables/ipsets。eBPF 在 Linux 内核中提供了一个高效、可编程的钩子点,用于网络数据包处理。

优点:

  • 更高性能: 通常比 iptables 具有更低的 CPU 开销和更高的吞吐量。
  • 更优的 Service 处理: 可以绕过 Kube-proxy,直接在 eBPF 中实现 Service 负载均衡(需要特定配置)。
  • 源 IP 保留: 在某些模式下更容易保留客户端源 IP。

启用方式: 通常在 Calico 安装配置中设置 spec.calicoNetwork.linuxDataplane: BPF (使用 Operator) 或设置 FELIX_DATAPLANE DRIVER=bpf 环境变量 (使用 Manifest)。

注意事项: 需要较新版本的 Linux 内核支持 (通常 >= 4.18,具体依赖特性)。切换数据平面可能需要重启节点或 Pod。

5.2 双栈 (IPv4/IPv6):

Calico 对 IPv4/IPv6 双栈提供良好支持。需要在 Kubernetes 集群和 Calico 配置中同时启用 IPv6:

  • Kubernetes API Server、Controller Manager、Kubelet 需配置 --feature-gates=IPv6DualStack=true 及相应的 --cluster-cidr--service-cluster-ip-range (包含 IPv4 和 IPv6 地址段)。
  • Calico 配置中需启用 IPv6 (FELIX_IPV6SUPPORT=true) 并创建 IPv6 的 IP Pool。

5.3 与 Service Mesh 集成 (如 Istio):

Calico 的网络策略可以在 L3/L4 层提供基础安全,而 Service Mesh (如 Istio) 则在 L7 层提供更丰富的流量管理和安全特性(mTLS, HTTP 路由, 重试等)。两者可以协同工作:

  • Calico 负责 Pod 网络连通性和基础网络隔离。
  • Istio 通过 Sidecar 代理接管应用流量,实施 L7 策略。
  • 可以使用 Calico 策略来保护 Istio 控制平面组件,或限制哪些 Pod 可以加入 Mesh。
  • 某些场景下,Calico 的 HostEndpoint 策略可以用于控制进出 Sidecar 的流量。

六、 故障排查与监控

6.1 常用排查工具与命令:

  • kubectl: 检查 Pod 状态、日志 (kubectl logs <pod> -n calico-system)、事件 (kubectl get events)。
  • calicoctl:
    • calicoctl node status: 查看节点和 BGP 状态。
    • calicoctl ipam show [--show-blocks]: 查看 IP 地址分配情况。
    • calicoctl get <resource_type> [<resource_name>] [-o yaml/wide]: 查看 Calico 资源(ippool, networkpolicy, hostendpoint, bgppeer 等)。
    • calicoctl node diags: 收集节点的诊断信息。
  • 节点内部工具:
    • ip route / ip -6 route: 查看节点路由表。
    • ip link: 查看网络接口(包括 veth pair)。
    • iptables-save / nft list ruleset: 查看防火墙规则(取决于使用的后端)。
    • tcpdump / ping / traceroute: 进行网络连通性测试。
    • 查看 Felix/BIRD 日志 (通常在 /var/log/calico 或通过 journalctl)。

6.2 常见问题场景:

  • Pod 无法启动/获取 IP:
    • 检查 calico-node Pod 是否运行正常。
    • 检查 IP Pool 是否耗尽 (calicoctl ipam show)。
    • 检查 CNI 插件配置 (/etc/cni/net.d/) 是否正确。
  • Pod 间无法通信:
    • 同节点: 检查节点内部路由、veth pair、iptables/eBPF 规则。
    • 跨节点:
      • 检查节点间 BGP Peering 状态 (calicoctl node status)。
      • 检查节点路由表是否包含目标 Pod CIDR 的路由。
      • 如果是 Overlay 模式,检查封装是否正常,MTU 是否配置正确。
      • 检查是否有 Network Policy 阻止了流量(尝试临时移除策略测试)。
      • 检查底层网络连通性(节点 IP 互 Ping)。
  • Pod 无法访问外部网络:
    • 检查 IP Pool 的 natOutgoing 配置是否为 Enabled
    • 检查节点的 IP Masquerade 规则 (iptables nat 表的 POSTROUTING 链)。
    • 检查节点的默认路由和网络配置。
  • Network Policy 不生效:
    • 确认策略已正确应用 (calicoctl get networkpolicy ...)。
    • 检查策略的 selector 是否准确匹配了目标 Pod。
    • 检查策略的 order 字段,确保评估顺序符合预期。
    • 检查 policyTypes (Ingress/Egress) 是否指定正确。
    • 使用 log action 辅助调试。
    • 确认 Felix 是否正常运行并在更新防火墙规则。

6.3 监控与告警:

  • Metrics: Calico 组件(Felix, Typha, BIRD)会暴露 Prometheus 格式的 Metrics。可以配置 Prometheus 抓取这些指标,监控关键状态,如:
    • Felix 活动状态、策略规则数、iptables/eBPF 执行时间。
    • BGP Peer 连接状态、路由收发数量。
    • IPAM 地址池使用情况。
  • 日志: 收集 Calico 组件的日志到集中的日志系统(如 EFK/Loki),设置告警规则监控错误和异常。
  • 健康检查: 利用 Kubernetes 的 Liveness/Readiness Probe 监控 Calico Pod 的健康状况。

七、 总结与展望

Calico 作为 Kubernetes 生态中功能强大且成熟的 CNI 插件,凭借其高性能的 Layer 3 网络模型、灵活的 BGP 路由能力以及业界领先的网络策略功能,为构建安全、高效、可扩展的云原生网络提供了坚实的基础。虽然其 BGP 相关配置和网络策略的理解可能需要一定的学习曲线,但其带来的性能优势和安全保障在许多生产环境中是值得的。

通过本文的实践与探索,我们了解了 Calico 的核心架构、不同的网络模型选择、安装配置步骤、强大的网络策略应用,以及 eBPF、双栈等高级特性。掌握 Calico 的运维和故障排查技巧对于保障 Kubernetes 集群网络的稳定性和安全性至关重要。

未来,随着 eBPF 技术的进一步成熟和普及,Calico 的 eBPF 数据平面有望带来更极致的性能和更丰富的功能。同时,Calico 社区也在持续演进,不断增强其在安全性、可观测性、易用性方面的能力,以更好地适应日益复杂的云原生应用场景。对于需要高性能网络和精细化访问控制的 Kubernetes 用户来说,深入理解和实践 Calico CNI 无疑是一项有价值的投入。


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部