在 Docker Desktop 中替换默认 CNI 为 Calico 的步骤
解读
Docker Desktop 默认使用 bridge + host-local + iptables 这一套“开箱即用”的 CNI 插件,目的是让单机开发环境一键可用。但在国内金融、运营商以及中大型企业落地云原生时,往往要求 固定 IP、NetworkPolicy 审计、跨主机 BGP 路由、HPC 场景下高性能 等能力,Calico 就成了刚需。
面试官问“怎么在 Desktop 里换掉默认 CNI”,并不是想听你背 Linux 那套 kubeadm 流程,而是考察三点:
- 是否知道 Docker Desktop 本质是运行在 Windows/Mac 上的一个轻量虚拟机(LinuxKit 或 WSL2 backend),所有容器网络都在 VM 内部完成;
- 是否理解 Desktop 并没有暴露 kubelet,也没有 systemd,所以无法像服务器那样直接改
/etc/cni/net.d; - 能否给出 最小侵入、可回滚、符合企业安全规范 的落地步骤,并解释每个命令背后的原理。
答不上这三层,基本会被判“只背过八股文”。
知识点
- Docker Desktop 网络栈:VM 内部用 containerd,CNI 配置目录
/etc/cni/net.d在 LinuxKit 的只读层,重启会被覆盖; - Calico CNI 插件组成:
calico、calico-ipam、portmap、bandwidth,以及calico-kube-controllers; - WSL2 backend 与 Hyper-V backend 差异:WSL2 的 VM 是
vmmem进程,文件系统通过\\wsl$\暴露,可直接在 Windows 侧写文件; - CNI 优先级:
00-*.conflist字典序最靠前者优先; - Desktop 的“immutable”机制:任何对
/etc的直接修改在重启后都会丢失,必须借助 Docker Desktop 的宿主机挂载点 或 WSL2 发行版自启动脚本 实现持久化; - 国内镜像加速:Calico 官方镜像
docker.io/calico/*在国内拉取经常超时,需提前同步到 阿里云 ACR、腾讯云 TCR 或自建 Harbor; - 合规要求:金融客户要求 非 root 运行 Calico Node,并关闭
FELIX_PROMETHEUSMETRICSENABLED防止信息泄露; - 回滚策略:保留原
10-docker.conflist,通过重命名顺序实现秒级回滚。
答案
步骤以 Windows 11 + Docker Desktop 4.28 + WSL2 backend 为例,Mac 仅需把路径换成 ~/Library/Containers/com.docker.docker/Data/vms/0/data/ 即可。
全程在 Windows 管理员 PowerShell 与 Ubuntu-22.04 WSL 发行版 中完成,不破坏 Desktop 一键升级能力。
-
前置检查
wsl -d docker-desktop -e cat /etc/os-release # 确认是 LinuxKit 5.15 以上内核,已自带 `xt_bpf` `ip_set` 模块 docker run --rm -it --pid=host --privileged calico/node:v3.27.0 calico-node -felix-ready # 提前验证镜像可拉取,否则先 docker tag 国内镜像 -
准备持久化目录
在 Windows 侧创建%USERPROFILE%\.docker\desktop\cni\calico目录,Desktop 会把该目录自动挂载到 VM 的/mnt/cni(只读),因此还需同步到可写路径。 -
编写 Calico CNI 配置
新建00-calico.conflist(字典序必须小于 10-docker.conflist):{ "cniVersion": "1.0.0", "name": "calico", "plugins": [ { "type": "calico", "log_level": "info", "datastore_type": "kubernetes", "nodename": "__KUBERNETES_NODE_NAME__", "ipam": { "type": "calico-ipam", "assign_ipv4": "true", "ipv4_pools": ["10.88.0.0/16"] }, "policy": {"type": "k8s"}, "kubernetes": {"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"} }, {"type": "portmap", "snat": true, "capabilities": {"portMappings": true}}, {"type": "bandwidth", "capabilities": {"bandwidth": true}} ] }把文件复制到
%USERPROFILE%\.docker\desktop\cni\calico\00-calico.conflist。 -
制作 LinuxKit 自启动脚本
在 WSL2 发行版里执行:sudo tee /usr/local/bin/calico-cni-install.sh <<'EOF' #!/bin/sh set -e mkdir -p /etc/cni/net.d # 利用 Desktop 的持久化挂载点 cp /mnt/cni/00-calico.conflist /etc/cni/net.d/ # 关闭默认 docker bridge CNI mv /etc/cni/net.d/10-docker.conflist /etc/cni/net.d/10-docker.conflist.bak # 写入 calico-kubeconfig(空文件即可,Desktop 无 kubelet) touch /etc/cni/net.d/calico-kubeconfig EOF sudo chmod +x /usr/local/bin/calico-cni-install.sh然后把它加入 LinuxKit 的
/etc/local.d/calico.start:sudo tee /etc/local.d/calico.start <<'EOF' #!/bin/sh /usr/local/bin/calico-cni-install.sh EOF sudo chmod +x /etc/local.d/calico.start由于 LinuxKit 使用 openrc,local.d 脚本会在 dockerd 启动前执行,保证 CNI 顺序正确。
-
启动 Calico Node 容器
在 Windows 侧编写calico-node.yaml:version: '3.8' services: calico-node: image: registry.cn-hangzhou.aliyuncs.com/acs/calico-node:v3.27.0 container_name: calico-node restart: always network_mode: host pid: host privileged: true environment: DATASTORE_TYPE: "kubernetes" WAIT_FOR_DATASTORE: "true" CALICO_NETWORKING_BACKEND: "bird" CALICO_IPV4POOL_CIDR: "10.88.0.0/16" CALICO_IPV4POOL_IPIP: "Never" CALICO_IPV4POOL_VXLAN: "Never" FELIX_DEFAULTENDPOINTTOHOSTACTION: "ACCEPT" FELIX_PROMETHEUSMETRICSENABLED: "false" NODENAME: "docker-desktop" volumes: - /lib/modules:/lib/modules - /var/run/calico:/var/run/calico - /var/log/calico:/var/log/calico command: ["calico-node", "-felix"]然后:
docker compose -f calico-node.yaml up -d -
验证
docker network create --driver calico --ipam-driver calico-ipam calico-net docker run --rm -it --network calico-net alpine ping -c 4 10.88.0.1能通说明 Calico CNI 已生效;再创建两条 NetworkPolicy:
apiVersion: crd.projectcalico.org/v1 kind: NetworkPolicy metadata: name: deny-all spec: selector: app == "demo" types: - Ingress - Egress通过
calicoctl下发策略,确认容器间流量被阻断,即证明 Policy 引擎工作正常。 -
回滚
若需回滚,只需在 WSL2 里执行:mv /etc/cni/net.d/10-docker.conflist.bak /etc/cni/net.d/10-docker.conflist rm -f /etc/cni/net.d/00-calico.conflist docker compose -f calico-node.yaml down重启 Docker Desktop,30 秒内恢复默认 bridge 网络。
拓展思考
- 多节点场景:Desktop 本身只模拟单机,若需验证跨主机 BGP,可在同一台 Windows 开多个 WSL2 发行版,用 L2bridge 透明网卡 打通二层,再跑两套 Calico Node,AS 号分别取 64512、64513,观察 RR(Route Reflector)自动选举 与 Typha 水平扩展 效果。
- 性能调优:国内云主机常关
ipip/vxlan,但 Windows 宿主机网卡不支持 RSS 多队列 时,Calico eBPF 模式反而下降 20%,需 绑定 CPU 隔离集 并打开FELIX_BPFENABLED=true做基准测试。 - 安全合规:证监会《容器安全指引》要求 镜像签名与 CNI 策略双审计,可把
calico-typha日志直接打到 Splunk 或阿里云 SLS,并用falco侧车检测modprobe逃逸行为。 - 升级策略:Docker Desktop 每季度大版本更新会重写 LinuxKit,本地脚本会被清空,因此要把步骤 4 的脚本做成 Windows 计划任务,每次 Desktop 启动后 30 秒自动下发,实现 “热补丁”级持久化。