欢迎光临
我们一直在努力

Kubernetes - Calico 网络插件的部署与基础配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

在这里插入图片描述

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Kubernetes这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • Kubernetes – Calico 网络插件的部署与基础配置 🌐🧩
    • 一、Kubernetes 网络模型基础:为什么我们需要 CNI? 🤔
    • 二、Calico 架构解析:BGP、Felix、BIRD 与 IP Pool 🧠
      • 2.1 核心组件概览
      • 2.2 数据流示意图:Pod 通信是如何发生的?
      • 2.3 IP Pool 与子网分配
      • 2.4 NetworkPolicy:微服务的防火墙 🛡️
    • 三、环境准备:构建你的 Kubernetes 集群 🛠️
      • 3.1 系统要求
      • 3.2 初始化 Kubernetes 集群
    • 四、部署 Calico 网络插件 🚀
      • 4.1 下载并应用 Calico 配置
      • 4.2 验证 Calico 是否正常运行
      • 4.3 自定义 Calico 配置:使用 IPIP 模式
    • 五、实战:Java 应用部署与 Pod 通信测试 🐘
      • 5.1 创建一个简单的 Java Web 服务
        • Java 代码示例:`HelloController.java`
        • Maven 依赖(`pom.xml`)
        • 构建 Docker 镜像
      • 5.2 部署 Java 应用到 Kubernetes
      • 5.3 测试 Pod 间通信
      • 5.4 使用 Java 客户端程序测试连通性(进阶)
    • 六、NetworkPolicy 实战:隔离与安全策略 🛡️
      • 6.1 部署两个应用
      • 6.2 创建默认拒绝策略
      • 6.3 创建允许策略:仅允许 frontend 访问 backend
      • 6.4 验证网络策略是否由 Calico 实现
    • 七、高级配置:BGP 与 AS Number 配置 🌐
      • 7.1 配置 Calico 使用 BGP 与外部路由器通信
      • 7.2 使用 Bird 配置查看 BGP 状态
    • 八、故障排查:常见问题与解决方案 🔧
      • 8.1 Pod 无法获取 IP 地址
      • 8.2 跨节点通信失败
      • 8.3 NetworkPolicy 不生效
    • 九、性能优化建议 ⚡
      • 9.1 使用 BGP 替代 IPIP(性能最佳)
      • 9.2 调整 MTU
      • 9.3 使用 BIRD2 替代 BIRD1(Calico v3.20+)
      • 9.4 启用 Felix 快速路径
    • 十、与其他 CNI 的对比:为什么选 Calico? 🆚
    • 十一、总结:你已经掌握了什么? 🎯
    • 十二、延伸阅读与资源 📚
    • 十三、结语:网络,是云原生的基石 🏗️

Kubernetes – Calico 网络插件的部署与基础配置 🌐🧩

在现代云原生架构中,Kubernetes 已成为容器编排的事实标准。然而,Kubernetes 本身并不提供网络实现,它仅定义了网络模型——即每个 Pod 都应拥有一个唯一的 IP 地址,且所有 Pod 之间应能直接通信,无需 NAT。实现这一模型的重任,就落在了 CNI(Container Network Interface)插件身上。

在众多 CNI 插件中,Calico 凭借其高性能、高可扩展性、原生支持 BGP 协议、强大的网络策略(NetworkPolicy)功能,成为生产环境中最受欢迎的网络解决方案之一。无论是公有云、私有云,还是混合环境,Calico 都能提供一致、稳定、安全的网络体验。

本篇博客将带你从零开始,完整部署 Calico 网络插件,并深入理解其核心机制。我们将结合真实场景,使用 Java 应用作为示例,演示 Pod 间通信、网络策略控制、跨节点连通性等关键能力。你将看到 Mermaid 图表直观展示 Calico 的数据流架构,也会接触到实际可运行的 Java 代码片段,帮助你将理论转化为实践。

准备好,让我们一起揭开 Calico 的神秘面纱 🔍✨


一、Kubernetes 网络模型基础:为什么我们需要 CNI? 🤔

在深入 Calico 之前,我们必须先理解 Kubernetes 的网络模型设计哲学。

Kubernetes 假设:

  • 每个 Pod 拥有一个唯一的 IP 地址;
  • 所有 Pod 可以在不经过 NAT 的情况下互相通信;
  • Node 可以与所有 Pod 通信;
  • 所有 Pod 可以与所有 Node 通信。

这个模型被称为 “Flat Network”(扁平网络),它极大简化了服务发现、负载均衡和调试流程。想象一下,如果每个 Pod 都要通过端口映射才能访问其他服务,那微服务之间的调用将变得极其复杂。

但问题是:Kubernetes 并不实现网络。它只定义了“应该怎样”,而“如何实现”则交给 CNI 插件。

CNI 是一个标准接口,允许容器运行时(如 containerd、Docker)在 Pod 创建或销毁时调用插件来配置网络。CNI 插件负责:

  • 为 Pod 分配 IP;
  • 设置网络接口(如 veth pair);
  • 配置路由规则;
  • 实现网络策略(可选)。

常见的 CNI 插件包括:

插件特点适用场景
Calico BGP + IPIP/ VXLAN,原生 NetworkPolicy 生产环境,大规模集群
Flannel 简单的 VXLAN/Host-GW 小型集群,快速部署
Cilium eBPF,高性能,安全策略强大 高性能、安全敏感场景
Weave Net 自动发现,加密传输 开发测试环境

👉 为什么选 Calico?

  • ✅ 原生支持 Kubernetes NetworkPolicy(比 Flannel 更强大);
  • ✅ 使用 BGP 协议实现高效路由,避免封装开销(如 VXLAN);
  • ✅ 支持 IPIP 和 VXLAN 模式,适应不同网络环境;
  • ✅ 可扩展性强,支持 BGP 路由聚合、AS 配置;
  • ✅ 社区活跃,文档完善,企业广泛采用。

📌 小贴士:如果你的集群节点位于同一二层网络(如局域网),Calico 的 BGP 模式性能最佳;若跨公网或云厂商 VPC,则推荐使用 IPIP 模式。


二、Calico 架构解析:BGP、Felix、BIRD 与 IP Pool 🧠

Calico 的架构由几个核心组件构成,它们协同工作,实现 Pod 网络的连通与隔离。

2.1 核心组件概览

组件作用运行位置
calico-node 在每个 Node 上运行,负责配置网络接口、路由、安全策略 DaemonSet
Felix Calico 的本地代理,负责编程内核路由表、iptables/ipset 规则 内置于 calico-node
BIRD BGP 客户端,与集群内其他节点交换路由信息 内置于 calico-node
kube-controllers 监听 Kubernetes API,同步 Pod、Namespace、NetworkPolicy 到 Calico Deployment
etcd(可选) 存储 Calico 的配置和状态(若使用 etcd 模式) 外部或内嵌

💡 注意:在 Kubernetes 集群中,Calico 默认使用 Kubernetes API 作为数据存储(kdd 模式),而非 etcd,因此无需额外部署 etcd。

2.2 数据流示意图:Pod 通信是如何发生的?

让我们用一张 Mermaid 图表来展示当 Pod A(在 Node1)访问 Pod B(在 Node2)时,Calico 的数据流:

#mermaid-svg-Ur7z8D30nj7V1C4e{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ur7z8D30nj7V1C4e .error-icon{fill:#552222;}#mermaid-svg-Ur7z8D30nj7V1C4e .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ur7z8D30nj7V1C4e .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ur7z8D30nj7V1C4e .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ur7z8D30nj7V1C4e .marker.cross{stroke:#333333;}#mermaid-svg-Ur7z8D30nj7V1C4e svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ur7z8D30nj7V1C4e p{margin:0;}#mermaid-svg-Ur7z8D30nj7V1C4e .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e .cluster-label text{fill:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e .cluster-label span{color:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e .cluster-label span p{background-color:transparent;}#mermaid-svg-Ur7z8D30nj7V1C4e .label text,#mermaid-svg-Ur7z8D30nj7V1C4e span{fill:#333;color:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e .node rect,#mermaid-svg-Ur7z8D30nj7V1C4e .node circle,#mermaid-svg-Ur7z8D30nj7V1C4e .node ellipse,#mermaid-svg-Ur7z8D30nj7V1C4e .node polygon,#mermaid-svg-Ur7z8D30nj7V1C4e .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ur7z8D30nj7V1C4e .rough-node .label text,#mermaid-svg-Ur7z8D30nj7V1C4e .node .label text,#mermaid-svg-Ur7z8D30nj7V1C4e .image-shape .label,#mermaid-svg-Ur7z8D30nj7V1C4e .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ur7z8D30nj7V1C4e .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ur7z8D30nj7V1C4e .rough-node .label,#mermaid-svg-Ur7z8D30nj7V1C4e .node .label,#mermaid-svg-Ur7z8D30nj7V1C4e .image-shape .label,#mermaid-svg-Ur7z8D30nj7V1C4e .icon-shape .label{text-align:center;}#mermaid-svg-Ur7z8D30nj7V1C4e .node.clickable{cursor:pointer;}#mermaid-svg-Ur7z8D30nj7V1C4e .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ur7z8D30nj7V1C4e .arrowheadPath{fill:#333333;}#mermaid-svg-Ur7z8D30nj7V1C4e .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ur7z8D30nj7V1C4e .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ur7z8D30nj7V1C4e .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ur7z8D30nj7V1C4e .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ur7z8D30nj7V1C4e .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ur7z8D30nj7V1C4e .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ur7z8D30nj7V1C4e .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ur7z8D30nj7V1C4e .cluster text{fill:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e .cluster span{color:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ur7z8D30nj7V1C4e .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ur7z8D30nj7V1C4e rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ur7z8D30nj7V1C4e .icon-shape,#mermaid-svg-Ur7z8D30nj7V1C4e .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ur7z8D30nj7V1C4e .icon-shape p,#mermaid-svg-Ur7z8D30nj7V1C4e .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ur7z8D30nj7V1C4e .icon-shape .label rect,#mermaid-svg-Ur7z8D30nj7V1C4e .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ur7z8D30nj7V1C4e .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ur7z8D30nj7V1C4e .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ur7z8D30nj7V1C4e :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

发包

本地子网

跨节点

响应

封装

Pod A: 192.168.1.2

calico-node on Node1

Felix 检查路由表

Pod B: 192.168.1.3 on Node1

通过 BGP 学习到 Node2 的路由: 192.168.2.0/26

封装为 IPIP 包(或直接 BGP)

Node2

calico-node on Node2

Felix 解封装

Pod B: 192.168.2.5

这个流程说明了:

  • 当两个 Pod 在同一 Node 上 → 直接通过 Linux bridge 通信(性能最高);
  • 当两个 Pod 在不同 Node 上 → 通过 BGP 交换路由,使用 IPIP 或 VXLAN 封装数据包;
  • 所有通信都受 Felix 编程的 iptables 规则保护,支持 NetworkPolicy。

2.3 IP Pool 与子网分配

Calico 使用 IP Pool 来管理整个集群的 Pod IP 地址空间。默认情况下,Calico 会创建一个 192.168.0.0/16 的 IP 池,每个 Node 会从中分配一个子网(如 /26),即每个 Node 可分配 64 个 Pod IP。

你可以自定义 IP Pool,例如:

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: custom–ippool
spec:
cidr: 10.244.0.0/16
ipipMode: Always
natOutgoing: true
nodeSelector: all()

✅ ipipMode: Always:强制使用 IPIP 封装,适合非二层网络环境(如公有云) ✅ natOutgoing: true:允许 Pod 访问外网时做 SNAT(默认开启)

2.4 NetworkPolicy:微服务的防火墙 🛡️

Calico 的最大亮点之一是其对 Kubernetes NetworkPolicy 的完整实现。它不仅支持 podSelector 和 namespaceSelector,还支持:

  • 基于标签的流量控制;
  • 端口级精细控制;
  • 多策略叠加;
  • 入站(ingress)与出站(egress)双向控制。

这使得你可以在不依赖传统防火墙的情况下,实现“零信任”网络架构。


三、环境准备:构建你的 Kubernetes 集群 🛠️

在部署 Calico 之前,你需要一个正常运行的 Kubernetes 集群。如果你还没有,可以使用 kubeadm 快速搭建一个单节点测试集群(推荐用于学习)。

3.1 系统要求

  • 2 个或以上节点(建议至少 2 个 Node,便于测试跨节点通信);
  • 操作系统:Ubuntu 20.04/22.04 或 CentOS 7/8;
  • Docker/containerd 容器运行时;
  • kubeadm、kubelet、kubectl 已安装;
  • 关闭 swap(swapoff -a);
  • 开放必要端口(见下表)。
端口方向说明
6443 TCP Kubernetes API Server
2379-2380 TCP etcd server
10250 TCP Kubelet API
179 TCP BGP(Calico)
4789 UDP VXLAN(若启用)
51820 UDP WireGuard(可选)

📌 注意:如果你在云厂商(如 AWS、阿里云)上部署,需确保安全组允许节点间 TCP 179 和 UDP 4789 通信。

3.2 初始化 Kubernetes 集群

# 在 master 节点执行
sudo kubeadm init –pod-network-cidr=192.168.0.0/16

# 设置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 加入工作节点(在 node 节点执行)
sudo kubeadm join <master-ip>:6443 –token <token> –discovery-token-ca-cert-hash sha256:<hash>

✅ –pod-network-cidr 是关键参数,它必须与 Calico 的 IP Pool 一致。我们这里使用 192.168.0.0/16,与 Calico 默认一致。

部署完成后,检查节点状态:

kubectl get nodes

你应该看到所有节点状态为 Ready。

🚫 重要:不要在初始化时使用 Flannel 或其他 CNI!否则会导致冲突。我们将在下一节部署 Calico 作为第一个 CNI。


四、部署 Calico 网络插件 🚀

现在,我们正式部署 Calico。官方推荐使用 YAML 清单部署。

4.1 下载并应用 Calico 配置

# 下载官方推荐的 Calico 配置(使用 kdd 模式)
curl https://docs.projectcalico.org/manifests/calico.yaml -o calico.yaml

# 应用配置
kubectl apply -f calico.yaml

🔍 查看 calico.yaml 内容,你会发现其中定义了:

  • DaemonSet:calico-node
  • Deployment:calico-kube-controllers
  • ClusterRole、ServiceAccount 等 RBAC 资源

4.2 验证 Calico 是否正常运行

# 查看所有 Pod 是否 Running
kubectl get pods -n kube-system -l k8s-app=calico-node

# 查看 Calico 的 Node 状态
kubectl get nodes -o wide

# 查看 Calico 的 IP Pool
kubectl get ippools.crd.projectcalico.org -o wide

输出示例:

NAME AGE
default-ipv4-ippool 5m

再检查 calico-node 的日志:

kubectl logs -n kube-system calico-node-xxxxx -c calico-node

如果看到类似日志:

BIRD: BGP state changed to Established
Felix: Configured with 192.168.1.0/26

恭喜你!Calico 已成功启动并开始交换路由。

4.3 自定义 Calico 配置:使用 IPIP 模式

如果你在云环境(如 AWS、阿里云)中部署,建议启用 IPIP 模式,因为这些环境通常不支持二层 BGP 通信。

修改 calico.yaml 文件,搜索 CALICO_IPV4POOL_IPIP,将其值从 Never 改为 Always:

– name: CALICO_IPV4POOL_IPIP
value: "Always"

或者,如果你希望完全自定义 IP Pool,可以删除默认的 ippool,并创建自定义配置:

# custom-ippool.yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: custom–ippool
spec:
cidr: 10.244.0.0/16
ipipMode: Always
natOutgoing: true
nodeSelector: all()

应用它:

kubectl apply -f custom-ippool.yaml

⚠️ 注意:一旦 Pod 已经创建,修改 IP Pool 不会自动影响已有 Pod。建议在集群初始化时配置好。


五、实战:Java 应用部署与 Pod 通信测试 🐘

现在我们有了网络,让我们部署一个 Java 应用来测试 Pod 间的通信。

5.1 创建一个简单的 Java Web 服务

我们使用 Spring Boot 创建一个极简的 REST 服务,返回当前 Pod 的 IP 和主机名。

Java 代码示例:HelloController.java

package com.example.calicotest;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

@RestController
public class HelloController {

@GetMapping("/hello")
public String hello(HttpServletRequest request) {
try {
String podIp = InetAddress.getLocalHost().getHostAddress();
String hostname = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
return String.format(
"👋 Hello from Pod! 🐳\\n" +
"Pod IP: %s\\n" +
"Hostname: %s\\n" +
"Request from: %s\\n",
podIp,
hostname,
request.getRemoteAddr()
);
} catch (UnknownHostException e) {
return "❌ Failed to resolve host: " + e.getMessage();
}
}

@GetMapping("/health")
public String health() {
return "✅ OK";
}
}

Maven 依赖(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>calico-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-boot.version>3.1.0</spring-boot.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

构建 Docker 镜像

# 构建 JAR
mvn clean package

# 创建 Dockerfile
cat > Dockerfile <<EOF
FROM eclipse-temurin:11-jre-slim
COPY target/calico-test-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
EXPOSE 8080
EOF

# 构建镜像
docker build -t calico-test-app:latest .

# 推送到私有仓库(或使用本地集群时跳过)
# docker push your-registry/calico-test-app:latest

💡 如果你没有私有仓库,可以直接使用 kind 或 minikube,它们支持本地镜像。

5.2 部署 Java 应用到 Kubernetes

创建 Deployment 和 Service:

# calico-java-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: calico–java–app
labels:
app: calico–java–app
spec:
replicas: 3
selector:
matchLabels:
app: calico–java–app
template:
metadata:
labels:
app: calico–java–app
spec:
containers:
– name: app
image: calico–test–app:latest
ports:
– containerPort: 8080
resources:
limits:
memory: "256Mi"
cpu: "200m"
requests:
memory: "128Mi"
cpu: "100m"
—
apiVersion: v1
kind: Service
metadata:
name: calico–java–svc
spec:
selector:
app: calico–java–app
ports:
– protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP

部署:

kubectl apply -f calico-java-app.yaml

等待 Pod 启动:

kubectl get pods -l app=calico-java-app -o wide

输出示例:

NAME READY STATUS RESTARTS AGE IP NODE
calico-java-app-6b7d9f5c9f-2x9zq 1/1 Running 0 2m 192.168.1.10 node1
calico-java-app-6b7d9f5c9f-8m2p7 1/1 Running 0 2m 192.168.2.5 node2
calico-java-app-6b7d9f5c9f-r9n4q 1/1 Running 0 2m 192.168.1.11 node1

5.3 测试 Pod 间通信

进入一个 Pod,尝试访问其他 Pod:

# 进入第一个 Pod
kubectl exec -it calico-java-app-6b7d9f5c9f-2x9zq — sh

# 在 Pod 内部执行 curl
curl http://calico-java-svc:80/hello

你应该看到类似输出:

👋 Hello from Pod! 🐳
Pod IP: 192.168.2.5
Hostname: calico-java-app-6b7d9f5c9f-8m2p7
Request from: 192.168.1.10

✅ 成功!说明:

  • Pod 192.168.1.10 能访问 192.168.2.5(跨 Node);
  • Service calico-java-svc 正常解析;
  • Calico 的 BGP 路由和 IPIP 封装正常工作。

5.4 使用 Java 客户端程序测试连通性(进阶)

我们写一个 Java 客户端,模拟微服务间调用:

// JavaClient.java
package com.example.calicotest;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class JavaClient {

public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();

List<String> targets = List.of(
"http://calico-java-svc:80/hello",
"http://calico-java-svc:80/health"
);

for (String target : targets) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(target))
.GET()
.build();

CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());

HttpResponse<String> response = future.join();
System.out.println("✅ Request to: " + target);
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body().substring(0, 100) + "…");
System.out.println("—");
}
}
}

将这个客户端打包成镜像,部署为 Job:

# java-client-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: calico–test–client
spec:
template:
spec:
containers:
– name: client
image: your–registry/java–client:latest
imagePullPolicy: IfNotPresent
restartPolicy: Never
backoffLimit: 3

执行:

kubectl apply -f java-client-job.yaml
kubectl logs job/calico-test-client

输出:

✅ Request to: http://calico-java-svc:80/hello
Status: 200
Body: 👋 Hello from Pod! 🐳
Pod IP: 192.168.1.11
Hostname: calico-java-app-6b7d9f5c9f-r9n4q
Request from: 192.168.1.12
—
✅ Request to: http://calico-java-svc:80/health
Status: 200
Body: ✅ OK
—

✅ 证明 Java 应用能通过 Service 名称解析并跨节点访问其他 Pod —— Calico 网络完全正常!


六、NetworkPolicy 实战:隔离与安全策略 🛡️

现在,我们来体验 Calico 最强大的功能之一:网络策略。

假设你有一个前端应用(frontend)和一个后端数据库(backend),你希望:

  • 只允许 frontend 访问 backend 的 8080 端口;
  • 禁止其他所有流量。

6.1 部署两个应用

# frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
– name: nginx
image: nginx:alpine
ports:
– containerPort: 80
—
apiVersion: v1
kind: Service
metadata:
name: frontend–svc
spec:
selector:
app: frontend
ports:
– protocol: TCP
port: 80
targetPort: 80
type: ClusterIP

# backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
labels:
app: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
– name: nginx
image: nginx:alpine
ports:
– containerPort: 80
—
apiVersion: v1
kind: Service
metadata:
name: backend–svc
spec:
selector:
app: backend
ports:
– protocol: TCP
port: 80
targetPort: 80
type: ClusterIP

应用:

kubectl apply -f frontend.yaml
kubectl apply -f backend.yaml

6.2 创建默认拒绝策略

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

⚠️ 此策略会阻止所有入站和出站流量,除非被其他策略允许。

应用:

kubectl apply -f default-deny.yaml

现在,测试访问:

# 进入 frontend Pod
kubectl exec -it frontend-xxxxx — sh

# 尝试访问 backend
curl http://backend-svc

你应该收到:

curl: (52) Empty reply from server

说明:流量被阻止了!🎉

6.3 创建允许策略:仅允许 frontend 访问 backend

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

💡 这个策略的意思是:

  • 目标 Pod:带有 app=backend 标签的;
  • 允许来源:namespace=default 中,app=frontend 的 Pod;
  • 允许端口:80/TCP。

应用:

kubectl apply -f allow-frontend-to-backend.yaml

再次测试:

kubectl exec -it frontend-xxxxx — sh
curl http://backend-svc

这次你应该看到:

<!DOCTYPE html>
<html>
<head><title>Welcome to nginx!</title></head>
…

✅ 成功!只有 frontend 能访问 backend,其他任何流量(包括其他命名空间或 Pod)都被阻断。

6.4 验证网络策略是否由 Calico 实现

查看 Calico 的 NetworkPolicy 状态:

kubectl get networkpolicies.networking.k8s.io

输出:

NAME POD-SELECTOR AGE
allow-frontend-to-backend app=backend 2m
default-deny <none> 5m

Calico 将这些策略转化为 iptables 规则,你可以在 Node 上查看:

# 在任意 Node 上执行
iptables -L -n -v | grep -A5 -B5 "cali"

你会看到大量以 cali 开头的链,这就是 Calico 的“网络防火墙”。


七、高级配置:BGP 与 AS Number 配置 🌐

如果你在私有数据中心部署,且网络支持 BGP,你可以让 Calico 与你的物理路由器交换路由,实现真正的“Pod 网络无缝融入数据中心”。

7.1 配置 Calico 使用 BGP 与外部路由器通信

首先,编辑 calico-node 的 ConfigMap:

kubectl edit configmap -n kube-system calico-config

找到 BGP peers 部分,添加:

data:
# …
calico_backend: "bird"
bird_config: |
protocol bgp bgp1 {
local as 64512;
neighbor 192.168.10.1 as 65000;
import all;
export all;
}

📌 64512 是 Calico Node 的 AS Number(私有 AS) 📌 192.168.10.1 是你的边界路由器 IP 📌 65000 是路由器的 AS Number

重启 calico-node:

kubectl rollout restart daemonset/calico-node -n kube-system

现在,你的每个 Node 都会向路由器宣告自己的 Pod 子网(如 192.168.1.0/26),路由器会学习到这些路由,外部系统可以直接通过 IP 访问 Pod,无需 Service 或 Ingress!

🌟 这在金融、电信等对网络性能要求极高的场景中非常有用。

7.2 使用 Bird 配置查看 BGP 状态

进入任意 calico-node Pod:

kubectl exec -it -n kube-system calico-node-xxxxx -c calico-node — birdc show protocols

输出示例:

name proto table state since info
bgp1 BGP master up 00:05:12 Established

如果看到 Established,说明 BGP 邻居连接成功!


八、故障排查:常见问题与解决方案 🔧

即使 Calico 非常成熟,部署中仍可能出现问题。以下是几个高频问题:

8.1 Pod 无法获取 IP 地址

现象:Pod 一直处于 ContainerCreating,kubectl describe pod 显示:

Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox

原因:Calico 未正常启动,或 IP Pool 冲突。

解决:

# 检查 calico-node 是否 Running
kubectl get pods -n kube-system -l k8s-app=calico-node

# 查看日志
kubectl logs -n kube-system calico-node-xxxxx -c calico-node

# 检查 IP Pool 是否冲突
kubectl get ippools.crd.projectcalico.org -o yaml

修复:删除冲突的 IP Pool 并重新创建。

8.2 跨节点通信失败

现象:同节点 Pod 能通信,跨节点不能。

原因:IPIP 未启用,或防火墙阻止了 UDP 4789 / TCP 179。

解决:

  • 确保 ipipMode: Always;
  • 检查云安全组/防火墙是否开放端口;
  • 在 Node 上测试 BGP 连通性:

telnet <other-node-ip> 179

8.3 NetworkPolicy 不生效

现象:策略已创建,但流量仍能通过。

原因:CNI 插件未正确加载,或策略语法错误。

验证:

# 查看策略是否被 Calico 接收
kubectl get networkpolicies -o yaml

# 查看 Felix 是否加载了策略
kubectl logs -n kube-system calico-node-xxxxx -c felix | grep "policy"

如果看到 Applying policy,说明已生效。


九、性能优化建议 ⚡

9.1 使用 BGP 替代 IPIP(性能最佳)

在支持 BGP 的网络中,关闭 IPIP,直接使用原生路由,可减少 5~10% 的延迟。

ipipMode: Never

9.2 调整 MTU

在 IPIP 模式下,建议将 MTU 设置为 1440(默认 1500 会导致分片):

– name: CALICO_IPV4POOL_IPIP_MTU
value: "1440"

9.3 使用 BIRD2 替代 BIRD1(Calico v3.20+)

新版本 Calico 使用 BIRD2,支持更高效的路由聚合。

calico_backend: "bird2"

9.4 启用 Felix 快速路径

在 calico-config 中启用:

– name: FELIX_IPTABLESBACKEND
value: "NFT"

NFTables 比 iptables 更高效,尤其在高规则数场景下。


十、与其他 CNI 的对比:为什么选 Calico? 🆚

对比项CalicoFlannelCilium
网络模式 BGP + IPIP/VXLAN VXLAN/Host-GW eBPF + BPF
性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
NetworkPolicy ✅ 完整支持 ❌ 有限支持 ✅ 完整 + L7
跨云支持 ✅ IPIP 模式完美 ✅ ✅
安全性 ✅ 基于 iptables ❌ ✅ eBPF 深度检测
复杂度 中等 简单 高
社区支持 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐

📌 结论:

  • 生产推荐:Calico(稳定、安全、企业级);
  • 学习/测试:Flannel(简单);
  • 高性能/安全场景:Cilium(eBPF 黑科技)。

🔗 想深入了解 Cilium?推荐阅读:https://cilium.io


十一、总结:你已经掌握了什么? 🎯

今天我们系统性地完成了:

✅ 理解了 Kubernetes 网络模型与 CNI 的角色 ✅ 部署了 Calico 网络插件并验证其运行 ✅ 使用 Java 应用测试了跨节点 Pod 通信 ✅ 实现了基于标签的 NetworkPolicy 策略 ✅ 配置了 BGP 与外部路由器集成 ✅ 掌握了常见故障排查方法 ✅ 对比了主流 CNI 插件的优劣

你不再是“只会用 kubeadm”的新手,而是能独立设计安全、高性能网络架构的云原生工程师!


十二、延伸阅读与资源 📚

  • Calico 官方文档:https://docs.projectcalico.org
  • Kubernetes 网络模型详解:https://kubernetes.io/docs/concepts/services-networking/pods/
  • BGP 协议入门:https://www.bgp4.as/
  • eBPF 技术介绍:https://ebpf.io
  • Kubernetes 网络策略最佳实践:https://kubernetes.io/docs/concepts/services-networking/network-policies/

十三、结语:网络,是云原生的基石 🏗️

在微服务、Serverless、Service Mesh 的世界里,网络不再是“后台基础设施”,而是应用架构的核心组成部分。

Calico 不仅是一个 CNI 插件,它是一个可编程的网络平台。它让你能像控制代码一样控制网络策略,像管理服务一样管理路由,像保护应用一样保护通信。

当你部署一个 Java 微服务时,你不仅在运行代码,你正在编织一张由 IP、端口、标签和策略构成的数字神经网络。

而 Calico,就是这张网络的神经突触。

愿你在云原生的征途中,网络无阻,服务无忧,安全如盾,敏捷如风。🚀


🙏 感谢你读完这篇深度指南。如果你觉得有帮助,欢迎分享给你的团队。 有任何疑问?欢迎在评论区留言,我会一一回复。 下一篇,我们将探讨:Calico + Istio 如何实现 L7 流量控制 —— 敬请期待!


🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨

赞(0)
未经允许不得转载:171主机测评 » Kubernetes - Calico 网络插件的部署与基础配置
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址