保姆级教程:手动导入Flannel镜像到K8s节点,彻底告别Docker拉取失败

深度实战:K8s集群中Flannel网络插件的离线部署全指南

1. 为什么需要离线部署Flannel?

在Kubernetes集群的搭建过程中,网络插件的部署往往是关键一步。Flannel作为最流行的CNI插件之一,其官方镜像默认从Docker Hub拉取。然而在实际生产环境中,尤其是国内网络环境下,经常会遇到镜像拉取失败、速度缓慢甚至完全无法访问的情况。这不仅会导致集群初始化失败,还可能影响后续的运维工作。

我曾经在一个金融行业客户现场遇到过这样的场景:由于安全策略限制,所有节点都无法直接访问外网,而集群又必须当天交付。通过手动导入Flannel镜像的方式,我们最终在2小时内完成了整个集群的网络部署。这种离线部署的方法后来成为了我们团队的标准操作流程。

2. 准备工作:获取离线镜像包

2.1 官方镜像下载

首先需要从官方渠道获取Flannel的镜像文件。推荐两种可靠的方式:

  1. 通过GitHub Releases下载

    wget https://github.com/flannel-io/flannel/releases/download/v0.25.1/flannel-v0.25.1-amd64.docker
  2. 使用docker save导出(如果已有可访问Docker Hub的环境):

    docker pull flannel/flannel:v0.25.1 docker save -o flannel-v0.25.1.tar flannel/flannel:v0.25.1

2.2 镜像完整性校验

下载完成后,务必进行校验以确保文件完整:

sha256sum flannel-v0.25.1-amd64.docker

对比输出结果与官方发布的校验值是否一致。这一步经常被忽略,但却是避免后续问题的关键。

3. 镜像导入:适配不同容器运行时

3.1 Docker环境下的导入

对于仍在使用Docker作为容器运行时的集群,导入过程相对简单:

docker load -i flannel-v0.25.1.tar

导入后检查镜像是否可用:

docker images | grep flannel

3.2 Containerd环境下的导入

大多数新版本K8s集群默认使用containerd,导入方式略有不同:

ctr -n k8s.io images import flannel-v0.25.1.tar

验证镜像是否成功导入:

ctr -n k8s.io images list | grep flannel

注意:containerd的k8s.io命名空间是Kubernetes专用的,必须指定-n参数

4. 配置Flannel部署文件

4.1 修改YAML的关键点

原始的Flannel部署文件需要做以下几处修改:

  1. imagePullPolicy:改为NeverIfNotPresent
  2. 镜像地址:去掉仓库前缀,直接使用镜像名称
  3. initContainers配置:确保与主容器使用相同的本地镜像

4.2 完整配置示例

apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds namespace: kube-flannel spec: template: spec: containers: - name: kube-flannel image: flannel:v0.25.1 imagePullPolicy: Never initContainers: - name: install-cni image: flannel:v0.25.1 imagePullPolicy: Never

4.3 配置参数对比表

参数原始值离线部署值说明
imagedocker.io/flannel/flannel:v0.25.1flannel:v0.25.1去掉仓库前缀
imagePullPolicyAlwaysNever禁止从远程拉取
command/opt/bin/flanneld/opt/bin/flanneld保持不变

5. 部署与验证

5.1 应用配置

kubectl apply -f kube-flannel.yml

5.2 验证部署状态

检查Pod是否正常运行:

kubectl -n kube-flannel get pods

查看日志确认无错误:

kubectl -n kube-flannel logs <pod-name>

5.3 网络连通性测试

创建一个测试Pod验证网络功能:

kubectl run -it --rm --image=alpine testpod -- sh ping 10.244.1.1 # 替换为其他节点的Pod IP

6. 常见问题排查

6.1 镜像导入失败

可能原因及解决方案:

  • 文件损坏:重新下载并校验SHA256
  • 权限不足:使用sudo或确保当前用户在docker/ctr组
  • 存储空间不足:清理旧镜像或扩容磁盘

6.2 Pod启动失败

典型错误现象:

  • ImagePullBackOff:检查imagePullPolicy是否为Never
  • CrashLoopBackOff:查看日志确认flanneld是否正常启动

6.3 网络不通

排查步骤:

  1. 确认各节点flannel Pod都正常运行
  2. 检查节点路由表是否有10.244.0.0/16相关条目
  3. 验证防火墙是否放行VXLAN流量(通常UDP 8472端口)

7. 高级技巧与优化建议

7.1 批量部署方案

对于大规模集群,可以编写自动化脚本完成所有节点的镜像分发:

for node in $(kubectl get nodes -o name | cut -d'/' -f2); do scp flannel-v0.25.1.tar $node:/tmp/ ssh $node "ctr -n k8s.io images import /tmp/flannel-v0.25.1.tar" done

7.2 版本升级策略

离线环境下的升级流程:

  1. 下载新版本镜像到管理节点
  2. 按照上述方法导入所有节点
  3. 修改Flannel YAML中的镜像版本
  4. 滚动更新DaemonSet

7.3 镜像缓存方案

建议在本地搭建镜像仓库作为缓存:

  1. 部署Harbor或简单的Docker Registry
  2. 将Flannel镜像推送到本地仓库
  3. 修改YAML使用本地仓库地址

这种方法尤其适合需要频繁部署的场景。

8. 安全注意事项

  • 镜像来源:只从官方渠道获取镜像,避免使用第三方修改版
  • 权限控制:确保flannel Pod运行在最小必要权限下
  • 网络隔离:如果环境允许,限制flannel相关端口的访问范围
  • 日志审计:定期检查flannel日志,排查异常行为

在一次政府项目部署中,我们发现直接使用离线镜像虽然解决了网络问题,但也带来了版本管理的挑战。为此我们建立了内部的镜像校验流程,每个使用的镜像都必须有对应的数字签名和版本记录。这种严谨的做法后来帮助我们快速定位和解决了一个由镜像版本不一致导致的网络故障。