十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Calico v3.25.0离线包制作与部署指南:内网Kubernetes集群网络实践

Calico v3.25.0离线包制作与部署指南:内网Kubernetes集群网络实践 简介Calico是Kubernetes集群常用的网络插件其v3.25.0离线安装包面向需要在内网或完全离线环境中部署网络方案的K8s管理员解决在线拉取镜像频繁失败、插件无法启动的问题。压缩包共3个文件其中tar文件保存了Felix、BIRD、Typha等完整镜像yaml文件定义部署所需的工作负载与策略模板txt文档则提供环境准备和校验指引整体大小187.24MB携带和分发都很方便。目前已有449人学习/下载特别适合网络受限但需要搭建或扩展集群的运维工程师。使用时可先导入tar镜像再按文档调整Pod网段、IP池等参数应用yaml即可完成Calico部署同时能借此熟悉各组件在路由发布和策略执行中的分工理解BGP模式下的容器跨节点通信原理。文档还提供了常见参数调整与排错提示便于团队快速落地并保障集群网络策略的稳定执行整体上是一份可直接使用的离线交付组件。1. 为什么需要自己打一个calico离线包做Kubernetes集群部署尤其是政企、运营商、制造这些内网隔离环境大家早晚都会遇到一个绕不过去的坎集群节点没有外网镜像拉不下来所有组件都得靠离线包搬运。我在帮客户搭生产集群的时候几乎每次都会卡在同一个环节——网络插件Calico。先说下这个需求的普遍程度。Kubernetes集群里最常用的网络方案就是Calico它基于BGP路由协议转发pod流量性能和可扩展性在CNI插件里都是第一梯队的。v3.25.0这个版本在2023年发布对应Kubernetes 1.24到1.27的版本区间是目前生产环境里使用率很高的一版。问题是Calico的组件依赖容器镜像运行而这些镜像默认都托管在Docker Hub和quay.io这类外网仓库内网环境根本拉不到。更尴尬的是网上流传的所谓离线包很多只打包了镜像文件yaml清单、版本配套关系、导入方法全都没有照搬下来部署大概率踩坑。所以这篇博文就把我实际做过的v3.25.0离线包完整流程拆开讲清楚镜像清单怎么定、导入内网仓库用什么姿势、calico.yaml哪些字段必须改、部署后常见报错怎么排查。内容基于我一个客户项目的真实操作记录是经过生产环境验证的可以放心抄作业。需要提前说明一点不同环境下网络隔离策略、镜像仓库方案各不相同所以文中的具体步骤我尽量写得通用一些凡是涉及环境差异的部分会单独标注你照着改就行。2. v3.25.0的离线包该装什么镜像清单与版本配套2.1 哪些组件镜像缺一不可Calico v3.25.0部署到Kubernetes集群上默认需要用到下面这几个镜像一个都不能少calico/cni: v3.25.0 —— CNI插件本体负责处理pod网卡创建和网络配置calico/node: v3.25.0 —— agent组件运行在每个节点上负责路由宣告和策略执行calico/kube-controllers: v3.25.0 —— 控制器处理IPAM分配、策略同步等逻辑calico/typha: v3.25.0 —— 扩展组件节点数量多时用来减轻API Server压力calico/pod2daemon-flexvol: v3.25.0 —— flexvolume插件驱动只有启用CSI或flexvolume存储能力时才需要如果是小规模集群节点少于50个typha可以不开但镜像最好一并打包进去免得后面扩容时手忙脚乱。pod2daemon-flexvol这个镜像最容易被漏掉因为它要等某些pod调度到节点上才被拉取而等真正需要时内网已经来不及下载了。还有一个细节Calico v3.25.0的镜像tag是完整的“v3.25.0”但个别镜像可能带后缀比如calico/cni对应的tag是v3.25.0而有的版本会同时存在v3.25.0-0.dev这样的开发tag。做离线包时务必以官方v3.25.0 release的manifests为准不要凭感觉抄网上的镜像列表。2.2 版本配套关系必须先确认很多新手栽的第一个跟头就是版本配套。Calico v3.25.0和Kubernetes的兼容范围是1.24到1.27也就是说如果你的K8s版本不在这个区间要么升级集群要么换对应版本的Calico。此外还需要确认etcd的版本Calico v3.25.0使用的是Kubernetes datastoreKDD模式不再像v2.x那样依赖独立的etcd集群这点倒是不用担心。我建议打包离线包以前先执行下面这个命令确认当前K8s版本kubectl version --short或者看服务端版本kubectl get node -o wide版本确认好后去GitHub上找对应release的yaml清单。v3.25.0版本的官方清单文件名是calico.yaml里面包含了所有需要创建的CRD、RBAC、DaemonSet和Deployment。但要注意官方清单默认从docker.io拉镜像离线环境下必须先把所有镜像导入到内网仓库然后修改yaml里所有image字段。2.3 镜像下载与打包的具体操作在一台能访问公网的机器上先把镜像拉下来。我习惯用docker来拉因为后面导入到内网仓库时操作最直观docker pull docker.io/calico/cni:v3.25.0 docker pull docker.io/calico/node:v3.25.0 docker pull docker.io/calico/kube-controllers:v3.25.0 docker pull docker.io/calico/typha:v3.25.0 docker pull docker.io/calico/pod2daemon-flexvol:v3.25.0拉完后统一打tag并推送到内网registry也可以先保存成tar包再拷贝进内网。两种方式我都试过如果是跨网段传输tar包更稳如果内网有可用镜像仓库直接打tag推送更省事。这里先演示打tag推送的做法docker tag calico/cni:v3.25.0 registry.internal.lan/calico/cni:v3.25.0 docker push registry.internal.lan/calico/cni:v3.25.0其他几个镜像照葫芦画瓢改对应的镜像名就行。如果要保存成tar包命令是docker save calico/cni:v3.25.0 calico/node:v3.25.0 calico/kube-controllers:v3.25.0 calico/typha:v3.25.0 calico/pod2daemon-flexvol:v3.25.0 -o calico-images-v3.25.0.tar拷贝到内网机器上导入docker load -i calico-images-v3.25.0.tar如果内网节点用的是containerd而不是docker那导入命令要换成ctr或crictl这个后面专门讲。3. 镜像导入内网仓库时最容易踩的三个坑3.1 坑一用ctr导入到错误命名空间很多K8s集群用的是containerd运行时这时候你可能会用ctr命令导入镜像。但containerd有一个“命名空间”的概念默认情况下ctr看到的命名空间是default而kubelet实际使用的命名空间是k8s.io。如果你直接ctr -nk8s.io images import calico-images-v3.25.0.tar这没问题但你要知道加了-nk8s.io才是在给kubelet准备的。不少教程没写这个参数结果镜像导入后显示成功pod启动时仍然报ImagePullBackOff就是因为镜像根本没导入到kubelet认识的那个命名空间里。最终生产中我建议干脆直接把镜像推到内网Harbor仓库让kubelet从仓库拉取避免绕这一层。除非你的环境连内网仓库都没有只能用ctr手动导入。3.2 坑二镜像tag被截断或不一致镜像从外网仓库同步到内网时很多人喜欢用Harbor的proxy cache功能或者skopeo同步结果同步完发现镜像tag变成了一长串带hash的地址或者多了个sha256:的digest。Calico的yaml里写的是具体tag比如calico/cni:v3.25.0Harbor proxy cache拉下来的镜像在本地仓库里显示的tag可能就是v3.25.0这没问题。但如果你手动docker tag的时候多打了一个前缀比如registry.internal.lan/calico/cni:v3.25.0那yaml里也必须同步改成这个完整地址不能只改一半。最好在导入后验证一下docker images | grep calico确保镜像REPOSITORY和TAG跟你接下来要改的yaml字段完全一致。3.3 坑三忽略了镜像签名或私有仓库认证有些内网Harbor仓库开启了镜像签名或者匿名拉取限制。Calico默认的manifest里没有写imagePullSecrets如果你的仓库需要在拉取时认证所有使用了Calico组件的命名空间都得配置对应的secret。最典型的报错就是在描述pod时看到类似这种信息Failed to pull image registry.internal.lan/calico/node:v3.25.0: rpc error: code Unknown desc failed to pull and unpack image: unable to retrieve some image pull secrets (user-1-registrysecret); attempting to pull may succeed...遇到这种错误处理办法就是在calico.yaml所在的命名空间一般是kube-system创建imagePullSecret然后把secret名称加到DaemonSet或Deployment的template里。如果只是临时测试也可以把所有节点的containerd配置里加上registry的认证信息这个看实际情况。但生产环境我还是建议直接在yaml里写secret可维护性好一些。4. 部署前必须改的calico.yaml配置项4.1 镜像地址替换拿到官方calico.yaml后第一步就是把所有image字段替换成内网仓库地址。手动改容易漏这里推荐用sed批量处理sed -i s#docker.io/calico#registry.internal.lan/calico#g calico.yaml注意有些版本默认镜像地址是calico/cni前面没有docker.io前缀那么替换规则要稍微调整sed -i s#calico/cni#registry.internal.lan/calico/cni#g calico.yaml sed -i s#calico/node#registry.internal.lan/calico/node#g calico.yaml sed -i s#calico/kube-controllers#registry.internal.lan/calico/kube-controllers#g calico.yaml替换完一定要检查一下grep -E image: calico.yaml确保没有一个漏网的。4.2 IP池配置pod CIDR和IPIP模式Calico默认的IP池用的是192.168.0.0/16很多公司的K8s集群为了跟办公网、业务网段区分通常会自定义Pod网段比如10.244.0.0/16。如果你不修改默认网段可能跟内网已有网段冲突导致路由不通。改IP池有两种方式一种是在calico.yaml里直接改IPPool的cidr字段一种是部署完成后再用calicoctl修改。建议部署前一次性改好因为IPPool创建后修改CIDR要重建很多pod麻烦得很。找到calico.yaml里类似下面这段apiVersion: crd.projectcalico.org/v1 kind: IPPool metadata: name: default-ipv4-ippool spec: cidr: 192.168.0.0/16 ipipMode: Always natOutgoing: true把cidr改成你的自定义网段比如10.244.0.0/16。ipipMode要根据你的网络环境决定如果所有节点都在同一个二层网络里推荐用Never即纯BGP模式转发效率更高报文也更小如果节点跨网段或者网络设备不支持BGP就用Always。最稳的做法是先看客户网络环境否则默认IPIP容易导致MTU问题这个下面会说到。4.3 MTU调整内网环境最容易忽视的问题Calico默认MTU是1500很多内网环境的主机网卡MTU就是1500这没问题。但如果你用的是VXLAN或IPIP封装实际的报文头会额外增加20字节左右如果底层网络设备支持巨型帧MTU设置为9000那就要把Calico的MTU调成比物理网卡小几十字节的值否则大包传输会被静默丢弃表现就是ping小包通、ssh正常但大文件传输、pod互访大规模流量时异常卡顿。v3.25.0版本里MTU在ConfigMap里设置kind: ConfigMap apiVersion: v1 metadata: name: calico-config namespace: kube-system data: veth_mtu: 1500如果主机网卡MTU是1500那veth_mtu保持1500即可如果主机网卡是9000建议改成8980左右。这个参数配错不会让Calico启动失败但会让整体网络表现非常诡异排查起来相当费劲。4.4 开启或关闭BGP对等Calico默认会为每个节点自动建立BGP mesh连接。如果你的集群节点数量少于100默认的full mesh够用节点多了就建议配置Route Reflector。v3.25.0里如果不想让Calico自动起BGP可以给节点打标签kubectl label node node-name route-reflectortrue然后把calico.yaml里的环境变量CALICO_NETWORKING_BACKEND改成none或vxlan。这个要看具体需求不展开太多。5. calico/node is not ready的完整排查链路热词里反复出现number of node(s) with BGP peering established 0和calico/node is not ready这是Calico部署后最常见的两个报错。我把实际排查过程完整写出来。5.1 先看calico-node这个pod的状态部署完Calico后第一时间看pod状态kubectl get pods -n kube-system -o wide | grep calico如果看到类似这样的状态说明有问题calico-node-xxxxx 0/1 Running 0 5mpod虽然在Running但READY是0/1说明容器里的进程起来了但尚未就绪。这时必须看日志kubectl logs -n kube-system calico-node-xxxxx -c calico-node最常见的日志是BGP peering established 0这就是BGP邻居没建立起来注意“established 0”是统计信息真正要看的是它前面的error信息。5.2 从日志顺序定位故障点我实际遇到过导致这个报错的原因按排查优先级排列节点间网络不通或防火墙拦截179端口BGP默认使用TCP 179端口内网环境经常有防火墙策略限制节点间通信。先测试telnet 目标节点IP 179如果telnet不通需要协调网络侧放行该端口。还有一个隐蔽问题云环境安全组一般只放行常用端口179端口很容易被漏掉。BGP mesh模式下节点IP不对Calico默认使用节点的内网IP作为BGP peer地址如果你的节点有多个网卡它可能选到了错误的IP。排查命令kubectl get nodes -o wide如果节点的INTERNAL-IP不是预期的内网网段需要给节点加annotation指定BGP地址。IPPool配置错误导致Felix收不到路由如果IPPool里指定的网段和节点实际不在同一网络BGP邻居可能建立了但路由无法同步。日志里会出现类似Failed to apply routes或Could not find container ID的提示。MTU问题导致的连接超时BGP peering建立后如果MTU不匹配大包握手会失败表现为BGP邻居反复up/down。这跟前面说的MTU配置密切相关。5.3 calico/node is not ready的另类原因除了BGP问题还有一种情况比较隐蔽节点的时间不同步。Calico的BGP会话对时间偏移很敏感节点间时间差超过几秒就会反复断开。我排查过几次生产环境的诡异问题最后发现都是ntp没配置。所以在部署Calico之前先保证所有节点时间一致date再配合chronyc或ntpq检查同步状态。这是很多文档不会提到的坑但确实真实存在。5.4 初始化检查的快捷方式v3.25.0的Calico部署完成后可以用calicoctl做整体体检kubectl exec -n kube-system calico-node-xxxxx -- calicoctl node status如果输出里每个节点都有BGP peer状态是Established那基本就成功了。如果是0个established按上面几类原因逐一排查。更简单的方式是直接跑一个测试pod验证kubectl run test-pod --imagebusybox -- sleep 3600 kubectl exec -it test-pod -- ping 另一个节点的podIP如果ping不通再回头看BGP状态。6. 验证离线包是否真正可用的标准方法6.1 集群内的连通性验证部署完Calico不等于离线包就合格了。我的习惯是分三步验证第一步检查所有calico-node pod都处于Running且READY为1/1kubectl get pods -n kube-system -o wide | grep calico第二步创建一个跨节点测试pod验证跨主机容器网络kubectl create deployment nettest --imagebusybox -- sleep 3600 kubectl scale deployment nettest --replicas2 kubectl get pods -o wide从其中一个pod ping另一个pod的IP如果通了说明BGP路由正常工作。这一步能直接检验IPIP或VXLAN封装是否正确、MTU是否匹配。第三步验证service网络创建nginx服务并跨节点访问ClusterIPkubectl create deployment nginx --imagenginx kubectl expose deployment nginx --port80 --target-port80 kubectl run testpod --imagebusybox -- sleep 3600 kubectl exec -it testpod -- wget -qO- http://ClusterIP6.2 离线包内镜像的完整性核对建议在导入镜像后用镜像仓库的API或docker images命令核对所有镜像的digest是否跟官方一致。v3.25.0的镜像可以从quay.io或docker.io上查看到对应的digest值离线包制作完成后最好把digest也记录下来后续安全审计或复现时用得上。比如docker inspect registry.internal.lan/calico/node:v3.25.0 --format {{index .RepoDigests 0}}拿到digest后跟官方仓库对比。这一步很多人不做但真出了问题比如镜像被篡改或传输损坏能有据可查。6.3 升级场景里的额外注意事项如果你是在已有Calico旧版本的集群上升级比如从v3.20升到v3.25.0那离线包还需要额外检查旧版本的CRD在v3.25.0里是否有废弃或改名。比如v3.25.0对GlobalNetworkPolicy、NetworkPolicy等CRD做了兼容性调整跨大版本升级时最好先看官方release notes不要直接在旧数据上硬上。最稳的做法是先在测试集群验证一遍确认没问题再上生产。别急着在生产环境直接升级除非你有一颗强大的心脏。7. 一个日常维护的小技巧最后分享一个我常做的维护动作Calico部署好以后建议把calico.yaml这个文件留存好并且在集群里用Git管理。以后不管是谁要重新部署、扩容或迁移集群直接拿这份yaml就能复现不用再到网上去翻官方文档拼拼凑凑。我一直觉得离线包不只是几个镜像的简单打包它应该包括一整套可重复执行的部署方案——镜像清单、配置清单、验证清单缺一不可。按照这套思路做出来的离线包才是真正能落地的离线包。本文还有配套的精品资源点击获取
返回列表