sealos + kube1.20.12.tar.gz:内网交付Kubernetes实战指南
简介面向需要快速搭建Kubernetes环境的中高级运维与开发人员由sealos工具打包的K8s 1.20.12离线安装包内置该稳定版所需的核心组件与自动化部署脚本可显著降低手动配置集群的复杂度与出错概率。包内共59个文件涵盖shell部署脚本、Markdown使用说明、YAML网络与初始化配置、systemd服务文件以及kubeadm、kubectl、kubelet等业务二进制和containerd镜像压缩包文件类型较全整体约530.85MB目录经过归类便于离线分发和按需提取。已有226人学习下载特别适合没有外网或希望快速复现集群环境的工程师使用。借助sealos命令行流程可完成解压、初始化、安装与多节点组网内置网络策略文件还能满足跨节点通信需求初始化与主节点配置脚本进一步减少手工干预对日常升级、排错也有参考价值。通过统一封装各节点可获得一致的运行时配置便于后续扩展与维护。1. kube1.20.12.tar.gz sealos内网交付 Kubernetes 的一条命令拿到一个叫 kube1.20.12.tar.gz 的离线包再配上一个 sealos这是内网和厂商交付场景里最常见的 Kubernetes 落地组合。它的意思很直白把 Kubernetes 1.20.12 的二进制、容器镜像和配置全部装进一个 tar 包由 sealos 分发到每台机器并完成初始化全程不碰外网。很多人以为离线包解压就能用其实真正干活的是 sealos——它把 kubeadm 该做的流程串了起来。下面按交付顺序拆解先拆包看里面有什么再动手装再把最容易翻车的那几个坑过一遍最后给一条从老命令迁移到新版方案的进阶路径。适合做私有云交付、在客户内网部署 K8s以及第一次碰 sealos 的运维和实施工程师。2. 离线包里的家底kube1.20.12.tar.gz 装了什么sealos 靠它怎么装机2.1 sealos 1.x 的装机流水线SSH、拷包、load 镜像都在黑匣子里sealos 1.x 本质上是一个 SSH 驱动的安装器它没有发明新的集群创建机制而是把 kubeadm 的活按顺序替你做完。常见做法是它先读取你给的 master 和 node 的 IP 列表然后用 root 密码或私钥逐个 SSH 探测连通性之后把 kube1.20.12.tar.gz 并发拷贝到每一台节点上在节点本地解包、用 docker load 把镜像喂进运行时把 kubelet、kubeadm、kubectl 这些二进制放到标准路径接着在 master 上执行 kubeadm init、在 node 上执行 kubeadm join最后装上 CNI 插件收尾。这个流程里tar.gz 就是那个黑匣子——你不需要知道里面每个文件的精确位置也能装完但排障时必须知道它装到哪一步了。sealos 的日志会打印当前阶段我最开始排障时吃过亏看到屏幕上刷一堆输出就直接重跑 init结果更乱。后来我养成的习惯是先确认失败点是在「拷包」还是「load 镜像」还是「kubeadm join」再决定动手方向。这一点在后文第 4 章的每个坑里都会反复用到。为什么这种设计适合离线交付因为所有组件、镜像和配置文件都打包在一个文件里sealos 只负责「分发 顺序执行」任何节点都不需要访问外网仓库甚至不需要访问内网 yum 源。这也是它在客户机房、涉密环境、纯内网实验室里被用了这么久的原因。对实施工程师来说你只需要保证一件事所有节点用相同 root 凭据能 SSH 通且 tar 包是完整、未被裁剪的。2.2 装之前先拆包tar -tzvf 看清二进制、镜像和 CNI 目录我拿到任何离线包的第一件事不是执行 install 脚本而是先拆开看看。tar 包不像 zip 能随便点开目录树直接列出内容最省事tar -tzvf kube1.20.12.tar.gz | head -40这行命令只是列出不解压head -40 挡住大量镜像层文件。你会看到几类东西bin 或 shell 目录下躺着 kubelet、kubeadm、kubectl、kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy 的二进制images 目录下是一堆 docker save 出来的 tar比如 kube-apiserver.tar、etcd.tar、coredns.tar、pause.tar以及 calico-node.tar、calico-cni.tar 这类 CNI 镜像还经常有一个 sha256sum.txt 或 md5sum.txt 校验文件。先拆包能直接回答三个问题CNI 用的是 calico 还是 flannel、pause 镜像在不在、有没有绝对路径的隐患。对于 Kubernetes 1.20.x 的默认组合包里的核心组件版本大致是这样一个矩阵具体以你手里的包为准包内组件对应版本作用kubelet / kubeadm / kubectlv1.20.12节点代理与初始化工具kube-apiserver / controller-manager / schedulerv1.20.12控制面三件套etcd3.4.13-0集群存储coredns1.7.0集群 DNSpause3.2所有 Pod 的沙箱基础镜像这里要特别留意 pause。有些自裁减的离线包会把 pause 漏掉装完后 Node 上是 Ready 的但所有 Pod 一直 ContainerCreating报 sandbox 找不到镜像。拆包时 grep 一下 pause 就能提前发现。另外解压前用 -tzvf 看路径是否以 / 开头如果打包者用了绝对路径你直接在生产机上解压会覆盖系统目录。我一般会先用tar -tzf kube1.20.12.tar.gz | grep ^/检查有绝对路径就先mkdir /tmp/pkg tar -xf kube1.20.12.tar.gz -C /tmp/pkg隔离再看别硬上。2.3 1.20.12 的兼容边界运行时、内核与组件版本矩阵kube1.20.12 是 1.20 系列的一个补丁版本sealos 1.x 时代支持得最顺的也是这条线。为什么很多交付项目卡在 1.20因为它是 dockershim 被移除前相对成熟的版本容器运行时选 docker 没有心理负担sealos 默认也是用 docker load 喂镜像整条链路最简单。1.24 之后如果还要用 docker就得装 cri-dockerd 这类垫片离线包的体积和维护成本都会变高。兼容边界上我实际踩过的底线是CentOS 7.6 以上、Ubuntu 16.04 以上、内核不低于 3.10。内核版本低kubelet 会报 overlay 文件系统或 conntrack 相关的错误系统太新反而有 nftables 和 iptables 混用的问题这在一些改版 CentOS 上尤其明显后面第 4 章的防火墙坑会展开。另一点容易被忽略sealos 1.x 不会帮你清理节点上已有的 K8s 残留干净节点是「最小成功条件」。如果你在别人跑过 kubeadm 的机器上直接 init十有八九会撞上证书或端口冲突。3. 从 tar.gz 到 kubectl 就绪sealos init 的参数与四连查3.1 装机前先做三件事校验 sha256、关 swap、同步时钟这三件事我在每一套集群上都做不赌 sealos 会替你处理。先校验离线包完整性这是离线交付最便宜的一道保险sha256sum kube1.20.12.tar.gz # 把输出和包来源提供的 sha256 值逐位比对一致才继续离线包最常见的损坏来自 U 盘拷贝、FTP 文本模式传输和下载中断。tar 包可能解压成功但 sealos 的校验阶段会直接报 mismatch到时候你反而要回头查传输链路。我一般会用 rsync -P 重新拉包并保留一份校验值文件在安装机本地。接着关 swap、调内核参数这几个 sysctl 不设flannel 或 calico 的跨节点流量会静默断掉swapoff -a sed -i / swap /s/^#*/#/ /etc/fstab cat /etc/sysctl.d/k8s.conf EOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sysctl --systemswapoff 只对当前内存生效真正持久化要改 fstab否则节点重启后又开回来kubelet 会报「Running with swap on is not supported」。sysctl 配置里的 bridge-nf-call-* 是让桥接流量经过 iptables这是所有基于 VXLAN 的 CNI 能跨节点通信的前提。时钟同步是离线环境最容易漏的一项。Kubernetes 的证书签发依赖时间master 和 node 之间差距超过几分钟就可能出现「certificate has expired or is not yet valid」这种伪装成证书问题的报错。我的习惯是装之前跑一下chronyc tracking | head -5 # 观察 System time offset 那一行的绝对值超过 1 秒就先去同步有内网 NTP 就配内网源没有就指定一台节点做时间源后面所有机器以它为基准。这一步花两分钟能省掉后面一小时的玄学排障。3.2 sealos init 最小命令与 6 个必调参数动手前先做一次 SSH 预检因为 sealos init 失败的第一大原因就是密码不对或 SSH 被安全策略限制。我一般先跑这段for ip in 192.168.10.11 192.168.10.12 192.168.10.13; do sshpass -p YourRootPass ssh -o StrictHostKeyCheckingno -o ConnectTimeout5 root$ip hostname \ echo $ip OK || echo $ip 连不上先解决 SSH done这段用 sshpass 带密码批量探测-o StrictHostKeyCheckingno 避免首次连接要交互确认指纹。能全部输出 OK 再往下走哪台不通先去解决网络或 SSH 配置别让 sealos 在同一台机器上反复重试浪费时间。预检通过后最小安装命令长这样sealos init \ --passwd YourRootPass \ --master 192.168.10.11 \ --node 192.168.10.12 \ --node 192.168.10.13 \ --pkg-url /data/kube1.20.12.tar.gz \ --version v1.20.12必须说清楚的是sealos 1.x 各小版本的参数名略有差异第一次跑之前先执行一下sealos init --help过一遍选项以下参数是这套命令里最常用的几个参数作用我一般怎么填--master控制面节点 IP可重复一个控制面包就填一台高可用集群重复传多个 IP--node工作节点 IP可重复按内网网段顺序排列和后续排查日志对得上--passwd所有节点统一的 root 密码不写进 shell history用环境变量注入更稳--pkSSH 私钥路径与 passwd 二选一跳板机环境优先用私钥减少密码暴露面--pkg-url离线包本地路径或 http(s) URL提前 rsync 到 /data比网络 URL 少一层故障点--versionKubernetes 版本必须匹配包写 v1.20.12和 tar 包名不一致会直接报 mismatch关于 --pkg-url如果包在别的机器上可以直接填 http:// 开头的内网地址sealos 会自己下载。但我实际更愿意先把包 rsync 到安装机再填本地路径省得下载中断让你分不清是网络问题还是 sealos 问题。init 中途失败时不要直接重跑 init先sealos clean --all清现场否则残留的 etcd 数据和证书会污染第二次安装。提示init 执行期间保持终端不断开有些版本失败重跑时会读取上次的临时目录终端断开会留下孤儿 SSH 进程。3.3 装完的四连查Node、Pod、readyz 与 cluster-info装完别急着交付先跑一组固定命令确认集群真的健康kubectl get nodes -o wide kubectl get pods -n kube-system -o wide kubectl get --raw/readyz kubectl cluster-info第一条约 10 秒内能看到所有节点状态如果是单控制面master 短暂显示 NotReady 正常但工作节点必须在 kubelet 起来、CNI 就绪后变 Ready。第二条看 kube-system 下的 Podapiserver、controller-manager、scheduler、etcd、coredns、kube-proxy 以及 calico 相关 Pod 应该处于 Running 或 Completed出现 ImagePullBackOff 或 CrashLoopBackOff 就去第 4 章对号入座。第三条的 /readyz 在 1.20 里是控制面整体健康的权威出口返回 ok 才算通过。第四条 cluster-info 会列出控制面地址和 kube-dns 地址能确认集群信息写入正确。Node 侧我也习惯补两个检查systemctl status kubelet -l看有没有反复重启docker images | wc -l和 2.2 节拆包时看到的镜像数量对一下数量对不上说明 load 阶段有遗漏。这些检查做完集群才算从「装完了」变成「能交付了」。4. 装机常见问题与排查五个高频翻车点从现象到解法离线装机翻车通常不是某一个组件坏了而是组件之间的衔接断了。下面五条按我在交付现场遇到的频率排每条按现象、原因、解决的顺序写你可以直接对照自己的报错定位。4.1 Node 一直 NotReadyCNI 镜像根本没 load 进去现象kubectl get nodes 里 Node 长时间 NotReadydescribe node 能看到 KubeletNotReady 的 eventkube-system 命名空间下 calico-node 或 flannel 的 Pod 处于 ImagePullBackOff。原因离线包里的 CNI 镜像没被 load 到节点上。常见两个来源一是节点的 /var/lib/docker 所在磁盘空间不足docker load 半途失败二是这个 tar.gz 是别人裁过的包打包时把 CNI 目录抽掉了。sealos 不会替你补 CNI它只负责把你包里的东西装进去。解决先在 NotReady 节点上df -h /var/lib/docker看剩余空间再docker images | grep -E calico|flannel确认镜像在不在。空间不够就把 docker 数据目录迁移或清日志镜像缺失就把 images 目录里对应的 tar 单独docker load -i calico-node.tar补进去然后删掉 NotReady 的 Pod 让它重建。如果包本身没带 CNI 镜像只能找包作者补包或者从内网镜像仓库单独拉。注意别在这个阶段手动 apply 一份网上下载的 calico.yaml 去覆盖版本和包内不一致会出现二次问题。4.2 apiserver 崩溃与 etcd 证书报错残留目录与时钟漂移现象init 在 kubeadm 初始化阶段报错apiserver 崩溃循环日志里出现「certificate has expired or is not yet valid」或者 etcd Pod 一直 CrashLoopBackOff报数据目录和证书不一致。原因九成是节点上有一份之前装过的 K8s 残留/etc/kubernetes 和 /var/lib/etcd 里躺着旧证书剩下一成是节点时钟偏差导致新证书看起来「还没生效」。这两个原因在日志里长得很像都是证书报错所以很多人会误判成包的问题重下离线包。解决先sealos clean --all再手动rm -rf /etc/kubernetes /var/lib/etcd ~/.kube把残留彻底清掉。然后对每台节点执行chronyc tracking确认时间偏差差距大就统一同步到一台时间源。等所有节点时间一致、残留清空后再跑一次 sealos init。这个坑之所以让人头疼是因为信号是证书病灶却在时间和文件系统。4.3 kubelet 与 docker 的 cgroup driver 不一致现象kubelet 服务起不来journalctl -u kubelet 显示「kubelet cgroup driver: cgroupfs is different from docker cgroup driver: systemd」之类的报错或者节点能起来但 Pod 频繁重启、部分容器被 OOMKilled。原因docker 守护进程默认用 cgroupfs而 kubeadm 在 systemd 系统上生成的 kubelet 配置倾向用 systemd两边不一致kubelet 直接拒绝工作。这是 systemd 系操作系统上最典型的运行时配置冲突和离线包本身关系不大。解决改 docker 配置让驱动和 kubelet 对齐cat /etc/docker/daemon.json EOF { exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: {max-size: 100m} } EOF systemctl restart docker改完之后确认docker info | grep -i cgroup显示 systemd再 sealos clean --all 重新 init。不要只改一边就重跑kubelet 的配置是由 kubeadm 生成的你手工改 kubelet 会被下一次 init 覆盖所以正确顺序永远是先改 docker 再重装。4.4 tar 包校验失败或解压报错别硬解先查传输链路现象sealos init 在开头就报 sha256 或 md5 mismatch或者你自己 tar -xf 时出现「Unexpected EOF in archive」这类解压错误。原因包在传输过程中损坏。最常见的是 FTP 用了文本模式二进制被改坏其次是 U 盘拷贝中断、下载只拉了一半。tar 包这种格式有个迷惑性损坏不严重时能解压出一部分文件让你误以为包没问题等 sealos 跑到某一步才炸。解决不要尝试修复也不要拿一个残缺的包硬装。回到包来源重新拉取用 rsync 的 -P 参数断点续传拉完立刻sha256sum比对。如果内网有 NFS 或 HTTP 文件服务把包和校验文件放一起安装机从那里拉传输链路的稳定性会好很多。我见过有人用一个坏包反复装了三天最后换了一个传输通道一次通过——这种问题很少是 sealos 的锅别在错误的包上反复投资时间。4.5 firewalld 与 SELinux两个看不见的连接杀手现象kubeadm join 显示成功但新节点上的 Pod 之间通信断断续续kube-proxy 日志报 connect: connection refusedflannel 隧道起来了跨节点 ping Pod IP 却不通。原因firewalld 默认策略把 6443、10250、8472、4789 等端口挡了SELinux 在 enforcing 模式下拦截 kubelet 和 etcd 的文件操作表现有时候是权限拒绝有时候是诡异的连接超时。这两个问题在「看起来一切正常但就是不工作」的场景里占比极高。解决内网交付我一般直接关掉 firewalldSELinux 改成 permissive 并写进 /etc/selinux/config否则重启后又会回来systemctl disable --now firewalld setenforce 0 sed -i s/^SELINUXenforcing/SELINUXpermissive/ /etc/selinux/config如果客户安全要求严格不允许关那就至少放行这张表里的端口方向端口/协议谁在用master 入站6443/tcpkube-apiserver所有节点10250/tcpkubeletmaster 之间2379-2380/tcpetcd跨节点8472/udp 或 4789/udpflannel / calico VXLAN所有节点53/udpcoredns提示放行策略只解决防火墙层SELinux 对 kubelet 的文件访问拦截不一定能用端口规则绕开。安全要求极严的环境建议提前在测试机验证 permissive 模式下的行为差异。5. 交付前把基线固化版本矩阵、存档脚本与扩容复位5.1 一张表把版本矩阵钉死谁也别信「当时装对了就行」离线交付最怕的不是装不起来而是三个月后要扩容时没有人记得当时用的是哪个版本的 sealos、哪个版本的 docker。我现在的习惯是装完第一件事就是补一张版本矩阵进交付文档对象取值备注离线包kube1.20.12.tar.gz记录 sha256和源站比对Kubernetesv1.20.12kubectl version 输出一致sealos1.x 具体版本号init 命令行为随小版本有差异容器运行时Docker 19.03cgroupdriversystemd记录 daemon.json 内容CNICalico记录包内镜像版本决定防火墙放行端口操作系统每台节点的 OS 和内核版本记录 kernel 3.10 以上与内核参数文件这张表值多少钱值一次「客户环境重建」。很多翻车现场问题不在技术而在当时的安装者没有留下可复现的记录。特别是 sealos 版本这一行——「别人能装你不能装」的差异十次里有八次是 sealos 小版本不同导致的行为变化。把版本钉死等于给这套交付物留了后悔药。5.2 把 init 命令固化成脚本校验、密码、参数三件套我会把 3.2 节的命令存成脚本放进交付目录下次重装直接执行不靠记忆敲命令#!/usr/bin/env bash set -euo pipefail PKG_URL/data/kube1.20.12.tar.gz CHECKSUM_FILE/data/kube1.20.12.sha256 MASTER_IP192.168.10.11 NODE_IPS192.168.10.12 192.168.10.13 SEALOS_VERSIONv1.20.12 read -r -s -p root password: ROOT_PASS; echo sha256sum -c $CHECKSUM_FILE || exit 1 args(init --passwd $ROOT_PASS --master $MASTER_IP --pkg-url $PKG_URL --version $SEALOS_VERSION) for node in $NODE_IPS; do args(--node $node) done sealos ${args[]}set -euo pipefail 保证任一环节失败就停不会带着错误继续往下装read -s 让密码从终端交互输入不落进 shell history 和脚本文件sha256sum -c 在脚本入口就把校验做成强制门禁。check 文件可以先在安装机上生成sha256sum kube1.20.12.tar.gz /data/kube1.20.12.sha256脚本化之后安装从「一串容易敲错的命令」变成了「一次可重复的执行」。如果环境允许把 --passwd 换成 --pk 指向专用部署私钥密码这个东西在交付文档里出现一次就多一份泄露风险。5.3 扩容与复位join 新节点、clean 重来的正确顺序集群交付后最常遇到的维护动作是扩容。新增一台工作节点我先确认新节点满足 3.1 的前置条件然后执行sealos join --master 192.168.10.11 \ --node 192.168.10.14 \ --passwd $ROOT_PASS \ --pkg-url /data/kube1.20.12.tar.gz \ --version v1.20.12join 和 init 共用同一套参数体系说明 sealos 1.x 的设计是「一次 initN 次 join」。新节点会被自动拷包、load 镜像、执行 kubeadm join。这里提醒一句1.x 各小版本的子命令名可能有差异先sealos --help确认是 join 还是 addnode别凭记忆敲。移除节点则要按相反顺序先在 master 上把节点排空再到节点上清理kubectl drain 192.168.10.14 --ignore-daemonsets --delete-emptydir-data # 在目标节点上执行具体子命令以你的 sealos 版本为准 sealos clean --node 192.168.10.14clean --all 则是整套流程的后悔药。任何一次装到一半想重来先 clean 再 init比手动删目录干净得多。我见过有人跳过 clean 直接重装结果 etcd 成员列表里留着旧节点集群怎么都起不来。顺序这个东西在离线交付里比在在线环境里更敏感因为你的排障手段本身就少一条外网路径。6. 进阶一招把 init tar.gz 心智迁移到新版 cluster 镜像如果你手里没有历史包袱或者正在评估新项目可以了解一下 sealos 新版4.x 及以后的 cluster 镜像方案。它没有推翻 tar.gz 时代的心智模型而是把同样的思路做成了更现代的交付物镜像仍然是一个「什么都装好了的文件」但不再需要 init 命令逐台操作而是用 run 加配置声明式创建集群。对应关系大致是这样1.x tar.gz 时代4.x 及以后pkg-url 指向本地离线包sealos pull 拉取 cluster 镜像push 进内网 registrysealos init 按 IP 列表装机Clusterfile 声明式配置 sealos rundocker load 喂镜像到节点节点通过 containerd 直接从内网 registry 拉--version v1.20.12 指定版本镜像 tag 即版本语义更直观迁移的收益在于Clusterfile 把 master 数、节点数、网络插件、运行时这些参数放进了 YAML版本和配置一起管理比命令行参数更利于审计和交给客户。排障顺序和 tar.gz 时代完全一致先确认镜像/包完整性再看 sealos 日志卡在哪一步最后查 kubelet 和 CNI。也就是说你在这篇文章里建立的排查框架换到新版仍然是顺手的。我的个人习惯是老环境只有 tar.gz 就按本文路线走不折腾迁移新项目直接上 cluster 镜像别在新命令上重复投资学习成本。两条路都走过之后你会发现离线交付的核心从来不是某个工具的命令好不好记而是你有没有把「包完整、时间一致、网络放行、驱动对齐」这四件事写进自己的检查清单。这些经验我用一次记一次现在每次开工前都先把 sha256 和版本号写进文档再谈装机——这几行字帮我挡掉了不少「当时明明能装」的返工。希望帮到你。本文还有配套的精品资源点击获取