如果你最近在折腾 Kubernetes 集群部署,大概率已经听过 Sealos 这个名字。我上个月在 Rocky Linux 9 上重新搭了一套 K8s 1.33.6 高可用集群,三台 master、两台 node,从环境准备到集群 Ready 用了不到二十分钟,其中真正执行sealos run的时间可能也就十分钟出头。这篇文章就把我从规划到落地的完整过程、背后原理和踩坑记录都摊开讲一遍。
这篇文章适合几类人:正在给团队搭测试环境但不想手动蹚 kubeadm 流程的运维同学,被多节点 etcd 和证书问题折磨过的平台工程师,以及想快速拿到一套生产级高可用集群做业务验证的后端开发者。即便你之前对 Sealos 完全没概念,按着下面的步骤走,也能把集群拉起来。
1. 内容整体设计与思路拆解
1.1 为什么我不再手动拼 kubeadm 高可用集群
早期我用 kubeadm 手动搭高可用集群,流程是固定的:先准备三台机器做 etcd,再装 HAProxy 或 Keepalived 做 apiserver 入口,接着生成证书、改 kubeadm 配置、初始化第一个 master,然后逐个 join 剩下的 master 和 node。整套下来一个小时起步,一旦中途出错,排查成本非常高。
最常见的问题是证书 SAN 没加全。apiserver 的证书默认只包含第一个 master 的 IP,等你把外部负载均衡地址或者 VIP 加进去之后,才发现集群外部访问时证书校验失败,只能重新生成证书并分发到所有节点。这个过程我已经重复过太多次,所以这次直接换成 Sealos。
Sealos 的设计思路是把整个 Kubernetes 集群看作一个“镜像”,通过sealos run一条命令完成之前所有手工步骤。它不是简单调用 kubeadm,而是把证书生成、etcd 集群构建、控制面组件启动、节点加群、网络插件安装全部封装成可复现的流程。对于运维来说,这意味着部署从“操作序列”变成了“状态描述”。
1.2 Sealos 高可用是怎么实现的:VIP、etcd 与组件多副本
很多人担心“一条命令装出来的集群会不会不够生产级”,我一开始也有这个顾虑,但拆开看它做的事情就放心了。Sealos 的高可用核心由三块组成。
第一块是 etcd 的多节点集群。每台 master 上都会跑一个 etcd 实例,三个节点组成一个标准 Raft 集群,数据自动复制。任意一台 master 宕机,只要剩余节点满足多数派(3 节点中至少 2 个存活),数据读写就不受影响。这也是为什么高可用集群至少需要三台 master,两台的话只要挂一台,etcd 就只剩一个节点,不满足多数派要求,集群会变成只读状态。
第二块是 apiserver 的接入层。Sealos 默认支持两种方式:一种是内置 VIP 方案,在三台 master 上自动部署基于 LVS 的负载均衡组件,VIP 会漂移到当前健康的 master 上;另一种是配置外部负载均衡器,比如公司已有的 HAProxy、云平台 LB。生产环境我建议优先考虑外部 LB,因为它不依赖节点上的 LVS 组件,故障域更小。
第三块是控制面组件的高可用。kube-controller-manager 和 kube-scheduler 都是多副本运行,通过参数指定 leader 选举,同一时间只有一个实例在工作,其他实例待命。Sealos 在创建集群时会把这一套配置全部下发到位,不需要再手工调整。
1.3 Sealos / kubeadm / Kubespray / RKE2 怎么选
我在调研阶段对比过几个主流方案,各有各的适用场景,这里简单列个对比:
| 方案 | 部署方式 | 高可用支持 | 离线安装 | 学习成本 | 适合场景 |
|---|---|---|---|---|---|
| kubeadm | 手工分步 | 需自行配置 etcd/LB | 不友好 | 较高 | 学习原理、深度定制 |
| Kubespray | Ansible 批量 | 内置 | 支持 | 较高 | 大规模批量部署、多环境标准化 |
| RKE2 | 单二进制 + 配置文件 | 内置 | 支持 | 中等 | Rancher 生态、边缘场景 |
| Sealos | 一条命令 + 集群镜像 | 内置 VIP/LB | 支持离线包 | 低 | 快速交付、中小规模生产集群 |
如果你的目标是彻底搞懂 K8s 内部机制,kubeadm 是很好的学习材料;但如果你是想在半天内交付一套能用的高可用集群,Sealos 的效率优势非常明显。Kubespray 更适合几十上百台机器的批量编排,但相对的,它的 Playbook 结构和变量体系本身就有一大套学习成本。RKE2 也不错,不过它和 Rancher 绑定得比较紧,如果你没有用 Rancher 做管理面,单纯为了装集群引入它反而多了一层东西。
1.4 适合什么场景,不适合什么场景
Sealos 特别适合这几类场景:企业内部需要快速交付一套稳定的基础环境;离线环境通过 Sealos 离线包完成部署;多套环境需要版本保持一致;以及团队里没有专职 K8s 运维,希望把维护成本降到最低。
当然它也有不适合的场景。如果你需要非常深度的定制,比如替换默认网络插件为自研 CNI,或者对控制面参数有特殊要求,可能还是要回到 kubeadm 手工部署。另外,Sealos 对集群的管理是“黑盒 + 可控命令”的模式,如果你倾向于所有资源都用 GitOps 声明式管理,那么集群本身这一层还是需要另外建立运维规范。
2. 环境准备与主机规划:前期不省事,后期省大心
2.1 硬件要求与主机规划
我这次用的是五台 Rocky Linux 9.4 服务器,具体规划如下:
| 角色 | 主机名 | 配置 | 数量 | 用途 |
|---|---|---|---|---|
| Master | k8s-master01 ~ 03 | 8C16G | 3 | 控制平面 + etcd |
| Node | k8s-node01 ~ 02 | 16C32G | 2 | 运行业务负载 |
如果是测试环境,Master 节点 4C8G 也能跑起来,但生产环境我建议 Master 不低于 8C16G。etcd 对磁盘 IO 比较敏感,有条件的话给 etcd 单独配一块 SSD,没有条件的话至少保证系统盘不是机械硬盘,否则集群负载上来之后容易出现 etcd 响应超时。
还需要注意一点:所有节点之间网络要互通,主机名解析要统一。我习惯把/etc/hosts写好,避免依赖内网 DNS,因为部署过程中 Sealos 要频繁通过主机名或 IP 连接各个节点,解析不稳定会导致初始化中断。
2.2 端口规划:哪几个端口是绝对不能省的
Kubernetes 集群涉及的端口比较多,我在好几个项目里都遇到过因为端口没放行导致节点 Join 失败的情况。这里整理一份最小端口清单:
| 端口 | 服务 | 说明 |
|---|---|---|
| 6443 | kube-apiserver | 所有客户端访问入口 |
| 2379/2380 | etcd client/peer | 2379 客户端,2380 节点间通信 |
| 10250 | kubelet | 控制面与节点通信 |
| 10257 | kube-controller-manager | 安全端口 |
| 10259 | kube-scheduler | 安全端口 |
| 179 | Calico BGP | 使用 Calico 时放开 |
| 30000-32767 | NodePort | 对外暴露服务 |
我在测试环境图省事直接关掉了 firewalld,生产环境还是建议按端口放行。如果你用的是云厂商安全组,这些端口也要同步配好。最容易漏的是 2379 和 2380,它们只用在 master 之间,但一旦漏配,后加入的 master 连不上 etcd 成员,集群会卡在初始化阶段。
2.3 Rocky Linux 9 初始化配置实操
所有节点都需要执行一遍基础配置,这里给出一套我在 Rocky Linux 9 上实测没问题的操作序列。
# 设置主机名(每台机器改成对应名字) hostnamectl set-hostname k8s-master01 # 统一 hosts 解析 cat >> /etc/hosts <<EOF 192.168.1.11 k8s-master01 192.168.1.12 k8s-master02 192.168.1.13 k8s-master03 192.168.1.14 k8s-node01 192.168.1.15 k8s-node02 EOF # 关闭防火墙(测试环境),生产环境建议放行端口而非全部关闭 systemctl stop firewalld systemctl disable firewalld # 关闭 SELinux sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config setenforce 0 # 关闭 swap swapoff -a sed -i '/ swap / s/^/#/' /etc/fstab # 加载内核模块 modprobe overlay modprobe br_netfilter # 配置 sysctl cat > /etc/sysctl.d/99-kubernetes.conf <<EOF net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system # 同步时间(etcd 对时钟敏感) dnf install -y chrony systemctl enable --now chronyd chronyc sources -v关于 swap,Kubernetes 从 1.22 之后虽然开始支持 swap 配置,但默认行为仍然是建议关闭,而且 Sealos 在预检查阶段也会检测 swap 状态。把它关掉能减少很多不确定因素。SELinux 同理,虽然理论上可以配置成 enforcing 模式,但主流安装工具默认按 permissive 处理,没必要在这里给自己增加排障负担。
时间同步这条我要多说一句:etcd 的 Raft 协议依赖稳定的网络延迟评估,节点间时钟偏差超过 100ms,就会出现频繁的 leader 切换,表现是集群响应变慢、日志里刷apply request took too long。我之前吃过这个亏,后来强制所有节点启用 chronyd 并配置好上游时间源,问题才消失。
2.4 安装 Sealos 与准备 SSH 连接
Sealos 本身只需要在一台机器上安装即可,这个节点被称为执行节点,它通过 SSH 去管控其他所有机器。执行节点可以是单独一台运维跳板机,也可以是第一台 master。我习惯用 k8s-master01 做执行节点。
安装方式很简单,官方提供了一键脚本:
curl -fsSL https://sealos.run/install.sh | sh sealos version如果网络环境不允许访问外网,也可以直接下载二进制文件放到/usr/local/bin,或者使用离线安装包把 Sealos 传进去。需要注意,Sealos 连接目标节点时支持两种认证方式:--passwd指定密码,或者--pk指定私钥文件。我生产环境用的是私钥方式,因为密码在命令行里会被 shell history 记录,存在泄漏风险。
# 在每台目标节点上创建部署用户并加入 sudoers useradd k8s echo 'k8s ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers # 然后把公钥拷贝到目标节点的 ~/.ssh/authorized_keys如果是测试环境,直接 root 登录 + 密码认证最简单,少配置一层。但不管用哪种方式,一定要确保执行节点能免密或者用密码自动登录到所有 master 和 node,这是 Sealos 能自动工作的前提。初始化之前我一般会先手动ssh root@192.168.1.11跑一遍,确认每台机器都能连通,避免 Sealos 跑到一半卡在 SSH 交互上。
3. 基于 Sealos 创建 K8s v1.33.6 高可用集群
3.1 一条命令创建集群:参数拆解
环境准备好之后,创建集群的命令其实只有一行:
sealos run kubernetes:v1.33.6 \ --masters 192.168.1.11,192.168.1.12,192.168.1.13 \ --nodes 192.168.1.14,192.168.1.15 \ --vip 192.168.1.100 \ --passwd 'YourStrongPassword'这里逐个参数说明:
| 参数 | 含义 | 说明 |
|---|---|---|
kubernetes:v1.33.6 | 集群镜像名 | 指定要安装的 K8s 版本 |
--masters | 控制平面节点列表 | 多个 IP 用逗号分隔,数量≥3 时自动搭高可用 |
--nodes | 工作节点列表 | 可省略,后续再添加 |
--vip | 虚拟 IP | 所有客户端访问 apiserver 的统一入口 |
--passwd | SSH 密码 | 或使用--pk指定私钥 |
--port | SSH 端口 | 默认 22,修改过端口时需指定 |
--vip这个参数是高可用集群的关键。它要求是一个和所有节点在同一二层网络、且未被占用的 IP。Sealos 会在 master 节点上部署基于 LVS 的负载均衡,把 VIP 绑定到当前健康的 apiserver 上。当某个 master 宕机,VIP 会自动漂移到其他 master。
如果你已经有一个外部负载均衡器,比如 HAProxy 或云厂商 SLB,可以不用--vip,在初始化之后通过修改 kubeconfig 和 kube-proxy 配置,让所有组件走外部 LB 地址。不过这样会多一层手工配置,为了省事我这次直接用 Sealos 内置 VIP 方案。
3.2 执行过程中发生了什么
执行命令之后,终端会输出类似这样的阶段信息:
[init] using kubernetes version: v1.33.6 [preflight] running pre-flight checks [init] pulling cluster images [init] generating certificates and kubeconfigs [init] starting etcd cluster [init] starting control-plane components [init] joining node(s) to the cluster [init] installing network plugin这段输出值得仔细看一眼,它对应了 Sealos 内部的完整流程:
预检查阶段,Sealos 会 SSH 到所有目标节点,检查操作系统版本、CPU 架构、swap 状态、磁盘空间和网络连通性。这一步如果报错,通常是某个节点 SSH 配置不对或者防火墙没关。
接着是拉取集群镜像。Sealos 会把 etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、coredns、Calico 等组件的容器镜像全部拉取到各个节点上。这一步占用时间最长,如果网络不好会卡很久。我在内网环境通常先把kubernetes:v1.33.6镜像导入到本地 registry,再用离线方式部署。
之后是生成证书。Sealos 生成 apiserver 证书时会自动把 VIP、所有 master 的 IP、Service CIDR 里的 cluster IP 都加进 SAN。这意味着后续通过 VIP 访问 apiserver,证书校验是必然通过的,不需要手工补 SAN。这也是相比 kubeadm 手装最省心的一个点。
再往后是启动 etcd 集群和控制面组件。所有组件都以静态 Pod 或容器方式运行,Sealos 把 manifest 文件写入/etc/kubernetes/manifests。如果是用 kubeadm 装过的老手,会发现目录结构非常眼熟,它本质上仍然是标准 Kubernetes 组件布局。
最后是节点加入和安装网络插件。node 节点会自动获取 kubeconfig 并加入集群,同时集群内部安装 Calico 作为默认 CNI。Sealos 整个流程跑完,终端会提示集群创建成功,并输出获取 kubeconfig 的路径。
3.3 验证集群状态
集群创建完成后,第一件事是验证各组件是否真的健康。在 k8s-master01 上执行:
kubectl get nodes预期看到五台节点全部是Ready状态,master 节点角色显示control-plane,node 节点角色显示<none>。如果某个节点一直卡在NotReady,大概率是网络插件没起来,往下看kubectl get pods -A确认calico-node的状态。
再检查系统组件:
kubectl get pods -n kube-system -o widecoredns、calico-kube-controllers、calico-node都应该是Running。这里还要注意 pod 分布,calico-node应该在每个节点上都有一份。
最后验证 apiserver 健康状态,通过 VIP 访问:
curl -k https://192.168.1.100:6443/healthz返回ok就说明 VIP 接入层工作正常。如果这里失败,问题大概率出在 LVS 组件或防火墙规则上,后面排查部分会细说。
3.4 模拟一台 Master 宕机的实测效果
我在测试环境做了一次故障演练:直接shutdown掉 k8s-master02,观察集群是否还能正常服务。结果符合预期,kubectl get nodes依然能返回信息,master02 状态变成NotReady,但其他节点的 pod 没有受到影响。
原因是 apiserver 有三个实例,客户端走 VIP 访问,VIP 漂移到了其他健康 master 上;etcd 集群在失去一个节点后仍然满足多数派条件;controller-manager 和 scheduler 通过 leader 选举机制自动切换到存活实例。整个切换过程在几十秒内完成,期间业务流量没有中断。
这里面有一个值得注意的点:kubectl默认读取的 kubeconfig 如果指向的是某一个具体 master 的 IP 而不是 VIP,那么在故障期间客户端可能连不上。所以我一般都把 kubeconfig 里的 apiserver 地址改成 VIP,这样客户端本身就具备故障转移能力。Sealos 在生成 kubeconfig 时默认写的是 VIP 地址,如果你发现不是,手动替换一下server字段即可。
3.5 后续扩容 Master 与 Node
集群跑了一段时间,要加一台工作节点,命令同样简单:
sealos add --nodes 192.168.1.16加 master 节点同理:
sealos add --masters 192.168.1.16Sealos 会自动完成新节点的初始化、证书签发和 etcd 成员加入。加 master 时它会自动把新节点加入 etcd 集群,并重新配置 LVS 组件。扩容之后记得执行kubectl get nodes确认新节点状态。
删除节点时要注意顺序:先从集群移除,再关停物理机。用sealos delete --nodes 192.168.1.16,它会自动从 etcd 和集群中摘除该节点。如果直接关机再删除,可能会留下 etcd 的隐患数据,虽然不会立刻出问题,但后续加节点可能导致 etcd 成员列表不一致。
4. 集群生命周期与日常运维
4.1 证书更新与自动化巡检
Kubernetes 的 apiserver 证书默认有效期是一年。这个时间看着很长,但如果集群是半年前建的,你可能已经开始接近证书到期时间了。证书过期后,kubelet 无法连接 apiserver,节点会变成NotReady,控制面其他组件也会报证书错误。
Sealos 管理的集群底层仍然是标准的证书体系,因此更新思路与 kubeadm 一致。可以在 master 节点上执行:
kubeadm certs renew all更新完成后,需要重启控制面组件让新证书生效:
kubectl -n kube-system rollout restart deployment/coredns但手工巡检很容易遗漏,我建议直接写一个脚本,每天检查证书剩余天数,低于 30 天就告警。证书文件路径是/etc/kubernetes/pki/apiserver.crt,检查命令:
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -enddate把这条命令放进 CronJob,输出结果通过企业微信或钉钉机器人推送,基本可以杜绝证书到期导致的事故。
4.2 版本升级要小心
Sealos 支持升级集群版本,命令是sealos upgrade --image kubernetes:v1.33.6。但升级这件事我想多说两句:不要在业务高峰期做,不要在没有任何备份的情况下做,不要跳大版本。
我见过有人从 1.28 直接跳到 1.31,结果第三方 Controller 版本不兼容,整个集群的异常告警刷了一整屏。Kubernetes 的版本升级有严格的兼容路径,一般建议小版本逐个升。Sealos 的upgrade命令正好支持指定目标版本,你完全可以把升级路径拆成v1.29.0 -> v1.30.0 -> v1.31.0,每步验证后再继续。
升级前最重要的备份工作是 etcd,只要 etcd 数据可恢复,集群就有退路。下面一节单独说备份。
4.3 网络插件与存储方案取舍
Sealos 默认安装 Calico,但如果你初始化时指定了其他网络插件也可以。比如:
sealos run kubernetes:v1.33.6 --network flannel # 或者 sealos run kubernetes:v1.33.6 --network cilium三种插件我简单对比一下:Calico 是默认之王,基于 BGP 路由,支持 NetworkPolicy,大规模集群表现稳定;Flannel 简单轻量,适合网络环境单一、不需要 NetworkPolicy 的场景;Cilium 基于 eBPF,功能最丰富,适合想体验新技术并且有足够排查能力的团队。生产环境我在没有特殊需求时永远选 Calico,因为它的生态最成熟,文档最多,遇到问题能搜到大量案例。
存储方面,如果你跑的是无状态业务,可以暂时不装存储插件,用 hostPath 或 emptyDir 顶着。但一旦要部署有状态应用,就需要 CSI 插件。物理机部署我推荐 Longhorn,它对硬件要求低、内置快照和备份能力;如果公司有成熟的 Ceph,那 Rook-Ceph 也是可靠选择。
4.4 备份必须做:etcd 快照方案
etcd 是 K8s 集群的数据库,所有资源状态都存在里面。一旦 etcd 数据损坏,集群基本就废了。我在每个项目里都会强制要求配置 etcd 自动备份。
Sealos 把 etcd 做成静态 Pod,这并不影响我们用标准的etcdctl做快照。在任意一台 master 上执行:
ETCDCTL_API=3 \ etcdctl --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db把这条命令封装成脚本,每天凌晨执行一次,保留最近七天的快照,存放目录建议挂载独立磁盘或者直接推送到对象存储。恢复的时候也简单:停掉所有 etcd 实例,用etcdctl snapshot restore恢复到临时目录,再把数据目录替换回去。虽然平时用不上,但真出事的时候这套备份就是救命稻草。
5. 常见问题与排查技巧实录
5.1 问题速查表
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 节点状态一直 NotReady | 网络插件异常、kubelet 证书过期 | 检查 calico pod 日志,确认 kubelet 时间是否正常 |
| 访问 VIP:6443 超时 | LVS 组件未启动、防火墙未放行 | 检查 lvscare 服务,确认 6443 端口放行 |
| join 第二台 master 失败 | etcd 端口未放通、时钟漂移 | 在目标节点测试 2379/2380 连通性,同步 chrony |
| apiserver 频繁重启 | etcd 响应慢、磁盘 IO 差 | 检查 etcd 日志,迁移数据到 SSD |
| kubectl 命令突然无响应 | apiserver 不可达、证书过期 | 确认 kubeconfig 是否走 VIP,检查证书有效期 |
| 集群升级后插件异常 | 版本兼容性问题 | 回滚到原版本,逐个小版本升级 |
5.2 我踩过的三个典型坑
第一个坑是 VIP 网段冲突。我最初把 VIP 设成了192.168.1.250,但没意识到这个地址已经被 DHCP 分配给了某个打印设备。部署完成后的第三天,打印机 IP 和 VIP 冲突,集群 apiserver 时好时坏,现象很诡异。排查了很久才发现是地址冲突。后来我把 VIP 规划到一个独立的保留网段,并在交换机上做静态 ARP 绑定,再也没出过这类问题。
第二个坑是 etcd 时钟漂移。三台 master 都是虚拟机,宿主机开了节能模式,导致虚拟机时钟漂移得很厉害。表现是集群偶尔出现几秒的 apiserver 无响应,etcd 日志里大量took too long告警。我一开始以为是磁盘问题,换了 SSD 之后告警还在,后来才发现是时钟同步没配好。强制 Chrony 同步、并开启系统时钟同步服务之后,问题彻底消失。
第三个坑是 join 第二个 master 时卡在 etcd 成员添加阶段,日志提示连不上 2380 端口。我当时以为防火墙已经关了,但排查发现是云平台安全组里只开了2379没开2380,导致 etcd peer 通信被拦。这种问题排查起来很容易绕弯路,因为表面现象是 apiserver 起不来,实际根源在网络层。后来的习惯是:初始化之前,先在所有 master 节点上用nc -vz测试一下 2379/2380 的双向连通性。
5.3 资源不足或网络不好的替代方案
最后补充一下资源受限的情况。如果你的测试环境只有两台机器甚至一台机器,还想体验高可用逻辑,我的建议是老老实实装单 master 集群,不要硬凑高可用。Sealos 在只有一个--masters参数时也能工作,它不会强制搭 etcd 集群。
如果网络不好,sealos run拉取镜像会非常慢甚至失败。Sealos 离线包是更好的选择:在能联网的机器上先sealos pull kubernetes:v1.33.6,然后把镜像导出、拷贝到内网机器加载,最后再执行sealos run。整个过程只需要把镜像文件传一遍,内网传输速度通常比直接从外网拉取快一个数量级。
我个人在实际操作中的体会是:Sealos 最大的价值不是省了那几十分钟安装时间,而是把集群的版本、架构、网络策略都统一收敛到一个可复现的入口命令里。团队里任何人,只要拿着一张主机清单和一条命令,就能在当前环境重建一套配置完全一致的集群,这种可复制性在生产环境里比什么都重要。最后再分享一个小技巧:多套环境的情况下,建议把你验证过的 Sealos 镜像和离线包固化到自己内网的镜像仓库里,版本锁死,之后每次部署都从内网分发,既快又稳。