首页 / 资讯中心 / 文章详情

Calico v3.20.6 离线网络部署实战:镜像导入、参数调优与故障排查

Calico v3.20.6 离线网络部署实战:镜像导入、参数调优与故障排查 ★ FEATURED ARTICLE
简介Calico v3.20.6 容器镜像与配置文件包面向需要在 Kubernetes 集群中部署容器网络插件并实施网络策略的运维、开发及架构人员解决跨节点通信、Pod 地址分配和多租户隔离等场景问题。包内共5个文件以4个 tar 镜像和1个 calico.yaml 核心配置为主镜像分别对应 Calico Node、CNI 插件、kube-controllers 与 pod2daemon-flexvol 组件各自承担路由与策略执行、Pod 网络接入、控制器管理和配置卷挂载功能yaml 文件则内置 DaemonSet、BGP 及安全策略定义可直接通过 kubectl apply 完成集成。整个压缩包约96.68MB体积紧凑便于离线环境部署和版本固化。目前已有1083人学习下载适用于需要快速搭建 Calico 网络或对集群网络行为进行深度定制的工程师可帮助读者理解组件协作关系并提升排障效率。1. calico-v3.20.6 容器镜像与 calico.yaml离线集群网络方案的第一道坎在内网环境装 Kubernetes十次有八次卡在同一个地方网络组件起不来。尤其是手上有 calico-v3.20.6 版本容器镜像和 calico.yaml 文件时照着教程kubectl apply下去Pod 全在 ImagePullBackOff报错说拉不到镜像可节点上明明已经导入了。这不是镜像没拷对而是对这份清单的理解差了最后一层。calico.yaml 是 Calico 在 Kubernetes 上落地的核心清单里面同时声明了 DaemonSet、Deployment、RBAC、CRD 和一批以calico/开头的镜像引用。v3.20.6 是一个被大量离线交付项目验证过的版本功能稳定、参数直观网上能查到的资料也最全。它适合那种要打包交付、内网部署、后续长期维护的集群。这篇就把这条链路完整走一遍从读清单、拉镜像、导入 containerd、改封装参数到部署完怎么验证数据面。适合正在做离线交付的平台工程师以及在内网维护 K8s 集群、被 calico-node 状态折磨过的运维。2. 从 calico.yaml 反推部署对象v3.20.6 清单里的镜像、资源与最小命令拿到 calico.yaml 先别急着kubectl apply。这份文件是个多文档 YAML里面既有 Kubernetes 原生资源又有 Calico 自己的 CRD还有一批镜像引用。先把里面引了哪些镜像、建了哪些资源摸清楚后面所有排障才有依据否则出了问题你连去哪个日志里翻都不知道。2.1 版本锁定v3.20.6 的镜像必须跟着清单走Calico 每次发布calico.yaml 里的镜像 tag 和 CRD 定义是配套的。v3.20.6 的清单里cni、node、kube-controllers、pod2daemon-flexvol 这四类镜像全锁在 v3.20.6 上。不要混版本拿 v3.23 的 node 镜像配 v3.20.6 的 CRDfelix 启动时会因为字段不认识直接退出日志里全是 unknown field 报错那是真难定位。先提取镜像列表# 从 calico.yaml 里提取所有 image: 引用的值去重排序 grep -E image: .* calico.yaml | sed s/^[[:space:]]*// | sort -ugrep-E image: .*匹配所有镜像行sed 把行首空格去掉sort -u去重。输出应该是四行calico/cni:v3.20.6、calico/node:v3.20.6、calico/kube-controllers:v3.20.6、calico/pod2daemon-flexvol:v3.20.6。默认不带仓库前缀隐式的docker.io就是拉取地址。这四类镜像是整套网络组件的地基。calico/cni负责把 CNI 插件二进制装进宿主机的/opt/cni/bin并写好/etc/cni/net.d配置calico/node是核心 agent里面同时跑着 Felix策略与数据面和 BIRDBGP 路由calico/kube-controllers是个 Deployment管 IPAM 回收和 NetworkPolicy 联动它挂了不影响现网流量但 Pod 删除后 IP 会泄漏pod2daemon-flexvol是给 FlexVolume 挂载用的即便新集群用不上 CSI清单里有它的 DaemonSet 就得把镜像备齐少一个就 ImagePullBackOff。2.2 资源对象拆解DaemonSet、Deployment、CRD 各自管什么清单里除了镜像还有一批 Kubernetes 资源。理解它的结构排障时才知道去哪看日志、去哪改配置。资源类型名称作用DaemonSetcalico-node每节点一个负责 CNI 安装、路由同步与策略执行Deploymentcalico-kube-controllers全局控制器处理 IPAM 与网络策略联动ServiceAccount / ClusterRolecalico-*给组件授权让它们能读 Node、Pod 信息CRDippools / felixconfigurations 等以 Kubernetes 资源方式存储 Calico 自身配置CRD 这块最容易被忽略。kubectl apply -f calico.yaml会把ippools.crd.projectcalico.org、bgpconfigurations.crd.projectcalico.org、felixconfigurations.crd.projectcalico.org等一批 CRD 注册进集群。之后你改配置就是对着这些 CRD 打补丁。v3.20.6 里最常操作的是两个IPPool 决定 Pod 网段和封装模式FelixConfiguration 决定日志级别和网卡检测策略。# 看 CRD 是否注册成功 kubectl get crd | grep projectcalico # 看默认 IPPool 的实际配置后面改网段就改这里 kubectl get ippool default-ipv4-ippool -o yaml第一条命令确认 CRD 已注册第二条命令直接看 Calico 的底层配置对象。注意 IPPool 不是 namespace 资源它在集群全局生效所以别指望用-n去过滤。改完 CRD 之后calico-node 会自动感知并更新配置不需要重启整个 DaemonSet。2.3 最小落地命令与状态判定镜像和资源都确认了才执行安装# 应用完整清单 kubectl apply -f calico.yaml # 等待 calico-node DaemonSet 滚动完成 kubectl -n kube-system rollout status ds/calico-node --timeout300s # 确认控制器 kubectl -n kube-system get deploy calico-kube-controllersapply 之后不要急着看节点状态先看 Pod 是否 ready。calico-node 是 hostNetwork 模式启动很快但它在 ready 之前kubelet 会一直把节点标记为 NotReady这是正常过程。如果rollout status超时基本可以断定是镜像没导对或者网络模式有问题直接跳到第 5 章对照现象排查。3. 镜像离线导入从 docker save 到 containerd 与私有仓库两条通道离线环境里镜像准备是第一步也是翻车最多的一步。v3.20.6 的四个镜像缺哪一个都不行缺了 Pod 就 ImagePullBackOff。下面两条路一条把 tar 包直接导入节点一条推到私有仓库再让集群拉按你的交付方式选一条走通即可。3.1 在联网机器上一次性拉全镜像并打包拿一台有外网的机器把四个镜像拉下来打成 tar# 定义 v3.20.6 镜像清单逐一下载并保存为 tar 包 images( calico/cni:v3.20.6 calico/node:v3.20.6 calico/kube-controllers:v3.20.6 calico/pod2daemon-flexvol:v3.20.6 ) mkdir -p calico-offline cd calico-offline for img in ${images[]}; do docker pull docker.io/${img} docker save docker.io/${img} -o $(echo ${img} | tr / _ | tr : _).tar done ls -lh *.tardocker pull前面显式写docker.io/是为了避免某些机器上配置了默认镜像仓库把镜像拉到别处。docker save保留完整的分层结构文件名转换把/和:换成下划线主要是为了在老旧文件系统上可读。打包机架构必须和目标节点一致arm64 的 tar 不能在 amd64 集群用混架构是离线交付最常见的坑装之前先确认节点 CPU 架构。3.2 通过 tar 包导入 containerd 节点目标节点如果是 containerd 运行时用 ctr 导入# 在目标节点执行把 tar 导入 kubelet 使用的 k8s.io 命名空间 ctr -n k8s.io images import calico_node_v3.20.6.tar # 用 crictl 验证 kubelet 视角能看到镜像 crictl images | grep calicoctr 是 containerd 的原生命令必须指定-n k8s.io命名空间kubelet 才认。crictl 走的是 CRI 接口它看到的就是 kubelet 能看到的镜像列表。很多翻车现场是用户在 containerd 节点上执行docker load然后报镜像不存在——load 只能进 docker 的存储目录containerd 根本不读那里。如果节点用的是 docker 运行时那就在每个节点docker load对应 tar。混合运行时集群部分 containerd、部分 docker建议装前先kubectl get nodes -o wide确认每台节点的运行时类型别凭印象猜。3.3 走私有仓库中转tag、push 与清单替换集群节点多、镜像要反复升级的场景tar 逐个导不现实推到私有仓库更省事# 以 registry.local:5000 为例统一重打 tag 并推送 for img in ${images[]}; do docker tag docker.io/${img} registry.local:5000/${img} docker push registry.local:5000/${img} done # 替换 calico.yaml 里的镜像仓库前缀 sed -i s#docker.io/calico/#registry.local:5000/calico/#g calico.yaml # 确认替换结果 grep -E image: .*calico calico.yaml | sort -used 里用#当分隔符是因为路径里/太多用#省掉转义。替换完成后务必 grep 检查一遍防止误改到别的字段。改完仓库前缀后所有节点必须能访问registry.local:5000离线集群常见做法是把仓库地址写进/etc/hosts和 containerd 的 registry 配置。imagePullPolicy 这块值得多说一句v3.20.6 清单里的镜像 tag 都带版本号kubelet 对非 latest 的 tag 默认 IfNotPresent本地有就不拉。但节点上没导入镜像时它还是会按镜像地址去拉所以离线环境要么把镜像导进节点要么把仓库地址改到位两条路至少走通一条否则 apply 下去就是一个小时的 ImagePullBackOff。4. 按网络环境裁剪 calico.yamlIPIP、VXLAN 与三组必调参数默认的 calico.yaml 能 apply 成功但网络能通只是起点。v3.20.6 默认用 IPIP 封装、Pod 网段写死192.168.0.0/16这两个默认值在真实机房至少一半环境会出问题。部署前按你自己的网络拓扑改三处参数能躲掉后面所有路由层面的坑。4.1 默认清单里的 IP 池与封装模式打开 v3.20.6 的 calico.yaml靠后有一段 IPPool 定义默认值长这样apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: default-ipv4-ippool spec: cidr: 192.168.0.0/16 ipipMode: Always natOutgoing: truecidr是 Pod 网段ipipMode: Always表示跨节点流量一律走 IP-in-IP 封装natOutgoing表示 Pod 访问集群外部时做 SNAT。三个字段决定了数据面的转发路径。其中cidr和ipipMode是部署前必须确认的natOutgoing一般保持默认即可关闭它只在极少数对源地址有审计要求的场景。4.2 三组必调参数与选型依据第一组是 calico-node DaemonSet 的环境变量控制 Pod 网段和节点 IP 检测# 在 calico-node 的 env 里修改 - name: CALICO_IPV4POOL_CIDR value: 10.244.0.0/16 # 必须与集群规划的 Pod CIDR 一致 - name: IP_AUTODETECTION_METHOD value: interfaceeth.* # 按网卡名选 IP比 first-found 稳CALICO_IPV4POOL_CIDR的值要和 kubeadm 初始化时--pod-network-cidr保持一致不一致会导致 kubelet 管理的 Pod 网段和 Calico 分配的不在一个段里流量直接路由黑洞。IP_AUTODETECTION_METHOD默认是first-found在只有一块网卡的机器上没问题但多网卡机器上经常选错网卡后面第 5 章有专门一条坑讲这个。第二组是 IPPool 里的封装模式切换。从 IPIP 换到 VXLAN改这两个字段spec: cidr: 10.244.0.0/16 ipipMode: Never # 关闭 IPIP 封装 vxlanMode: Always # 开启 VXLAN 封装 natOutgoing: true选哪种封装核心只看一个因素节点之间的网络中间有没有防火墙或安全组。模式封装依赖的端口/协议适用场景IPIPIP-in-IPIP 协议号 4机房直连、底层网络不限制协议VXLANUDP/VXLANUDP 4789云环境安全组、隔离网络无封装无TCP 179同二层网络、延迟敏感场景在云上开 VPC默认安全组通常不认 IP-in-IP 协议选 VXLAN 最省事只需要放行 UDP 4789。自建机房二层直连关掉封装走纯 BGP 性能最好但需要放行 TCP 179。拿不准就选 VXLAN能踩的坑最少。第三组是可选的如果你的集群规模超过 50 个节点建议关注 Typha。v3.20.6 的默认清单里没启用 Typha它是独立组件作用是代理 calico-node 与 API Server 之间的通信减少大规模集群的连接压力。离线部署多一个组件就要多备一组镜像小规模集群先不碰它。4.3 网段冲突检查清单改参数之前先做三件事# 查节点实际网段 kubectl get nodes -o wide | awk {print $1, $6} # 查本机路由里已有的网段确认与 Pod 网段不重叠 ip route | head -20如果机房服务器网段本身就在192.168.0.0/16里而你没改默认值calico-node 会把节点地址也当成 Pod 地址来处理表现为路由错乱、跨节点时通时不通。这类问题定位至少半小时起但预防只需要部署前查一次路由。还有一个容易忽略的点IPPool 创建之后直接改cidr是不生效的需要删除旧 IPPool 重新创建存量 Pod 全部重建。所以网段规划必须放在部署前上线后再改的成本很高。检查时顺手确认 Service CIDR 也不和 Pod CIDR 重叠比如 kubeadm 默认的 Service CIDR 是10.96.0.0/12Pod CIDR 就用10.244.0.0/16这种完全不搭边的段。5. calico v3.20.6 部署避坑五个高频故障的现象、原因与解法离线部署 calico 的报错翻来覆去就那几个。这一章把我在交付和帮别人排查时遇到最多的五条列出来按出现频率排序。每条按现象、原因、解决的顺序写方便你对着排查。5.1 镜像本地已有却一直 ImagePullBackOff现象crictl images能看到calico/node:v3.20.6apply 之后 Pod 还是 ImagePullBackOffdescribe 里除了拉镜像失败没有更多详情。原因三种最可能——tar 导错了 containerd 命名空间清单里的 tag 和导入的不一致比如你导入的是带_amd64后缀的 tag节点容器运行时是 docker但镜像导进了 containerd。解决先把两边对齐。# 看 kubelet 视角的镜像列表 crictl images | grep calico # 看清单里期望的镜像地址 grep -E image: .*calico calico.yaml | sort -u两边 tag 对不上就重新导入ctr -n k8s.io images rm删掉旧镜像再ctr -n k8s.io images import导入避免同名 tag 覆盖导致异常。还有一个根治习惯在清单里的容器模板显式加imagePullPolicy: IfNotPresent断了 kubelet 去远端拉的可能离线环境里这个策略最省心。5.2 calico-node 已 Running节点却一直 NotReady现象calico-node Pod 显示 Running但 Ready 列是 0/1节点一直 NotReady。日志里 BGP session 反复 established 然后 resetfelix 报 failed to establish 之类的错误。原因跨节点的 TCP 179 或 IP-in-IP 协议被防火墙/安全组拦截。Felix 的数据面起不来BIRD 的 BGP 对等体握手失败节点状态就一直拉不起来。解决先把 calico.yaml 改成 VXLAN 模式重装一遍。如果立刻恢复就证明是协议被封这时候再回头决定到底是放行还是继续用 VXLAN。放行的话IPIP 需要放行 IP 协议号 4BGP 需要放行 TCP 179别只放行端口很多防火墙面板上协议号这个选项特别隐蔽。5.3 Pod 网段和节点网段重叠路由黑洞现象集群能建起来但部分 Pod 跨节点访问间歇性失败ping 丢包严重。某节点路由表里出现指向自身网段的奇怪路由。原因默认 CIDR192.168.0.0/16和机房服务器网段重叠IPAM 把节点 IP 也当成 Pod IP 处理了。解决规划阶段就改成10.244.0.0/16这类机房未使用的私有段。如果已经建了默认 IPPool需要先删掉再重新应用# 注意存量 Pod 会重建操作前确认业务可接受 kubectl delete ippool default-ipv4-ippool # 修改 calico.yaml 里的 CIDR 后重新应用 kubectl apply -f calico.yaml # 重启 calico-node 让新配置生效 kubectl -n kube-system rollout restart ds/calico-node这个操作有数据面抖动必须挑业务低峰期。升级教训是网段冲突的排查成本远高于安装前查一次ip route这条建议放在部署清单第一行。5.4 多网卡机器上 node IP 误检现象机器有 eth0 管理网、eth1 业务网calico-node 起来了但 BGP peer 地址全是错的跨节点业务不通。单看每个节点自己的 IP 还都是正常的。原因默认IP_AUTODETECTION_METHODfirst-found检测顺序只认第一个可用的网卡不一定是你期望的那块。解决显式指定检测方法- name: IP_AUTODETECTION_METHOD value: can-reach10.1.1.254 # 用能 ping 到网关的网卡 IPcan-reach比interfaceeth.*更准它会对指定地址做一次探测直接测出哪块网卡真正可用。这个参数在安装前确认比装完再逐台改省事太多。5.5 卸载重装后 iptables 残留把新数据面带崩现象kubectl delete -f calico.yaml之后重新 apply新 calico-node 是 Running但 Pod 访问全被策略挡住Felix 日志里一直有规则 sync 超时。原因felix 往 iptables 写了cali-开头和KUBE-NWPLCY的自定义链删除 DaemonSet 时这些链不会自动清掉。新旧规则叠加策略判断全乱。解决重装前在每个节点清理# 节点排空后执行低峰期操作 iptables -F iptables -t nat -F iptables -t mangle -F ip link del tunl0 2/dev/null || true systemctl restart kubelet第一行清空 iptables 的三个常用表这是最暴力的做法却也是离线环境重装时最省事的。ip link del tunl0删掉 IPIP 隧道接口2/dev/null || true做兜底防止节点本来没起 IPIP 时报错。这不是官方推荐动作生产环境要谨慎先 drain 节点再做。但比起手动逐条删cali-链这个方案实践下来快得多。6. 用 calicoctl 验证数据面连通性、NetworkPolicy 与版本一致性装完不等于网络好了最后花十分钟做一轮验证确认 v3.20.6 这套东西真在工作。6.1 版本一致性核对calicoctl version kubectl -n kube-system get ds calico-node -o yaml | grep image: | sort -ucalicoctl 的版本要和节点镜像一致用 v3.20.6 的客户端查 v3.20.6 的 CRD 最稳。版本不一致可能出现字段解析异常一度被我当成玄学问题其实是客户端版本不匹配。6.2 跨节点连通性验证kubectl run net-a --imagebusybox --restartNever -- sleep 3600 # 记录 net-a 所在节点再起 net-b 并记录其所在节点和 Pod IP kubectl get pods -o wide kubectl exec net-a -- ping -c 3 net-b的Pod IP两条 Pod 不在同一节点时 ping 通说明 BGP 或 VXLAN 数据面正常。ping 不通就回头查第 5 章的节点状态和路由。6.3 NetworkPolicy 生效验证网络通只是数据面策略面也要验apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all namespace: default spec: podSelector: {} policyTypes: [Ingress]kubectl apply -f deny-all.yaml kubectl exec net-a -- wget -T 3 http://net-b的IP || echo blocked kubectl delete -f deny-all.yamlwget超时被 block 住说明策略下发成功删掉策略后恢复说明 kube-controllers 的控制器逻辑在正常工作。我的习惯是每次部署 v3.20.6 之前先把第 4 章的三组参数写成一行备忘贴到部署文档第一页Pod CIDR、网卡检测、封装模式。这三样定下来离线部署基本不会翻大车剩下 ImagePullBackOff 和 NotReady 都在这五个坑的射程之内半小时内能定位。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站