前阵子有套测试环境要升级,几台 Rocky Linux 9 的机器一直闲着,正好拿来做一套 Kubernetes 1.33.6 高可用集群。要是按老办法手动装,先配 etcd 三副本,再装 kubeadm 初始化 master,然后折腾负载均衡、token 认证、worker join,一台一台敲命令至少得耗掉半天,中间还容易因为证书、网络、SELinux 这些细节翻车。这次我直接用 sealos 来装,一条 run 命令把集群拉起来,高可用相关的负载均衡也一起处理掉,整个过程比预期顺畅很多。这篇就把从规划、安装到踩坑排查的完整过程写下来,给想快速搭高可用 Kubernetes 又不想啃安装文档的同学做个参考。
1. Sealos 到底解决了什么问题
1.1 手动搭高可用集群的痛
Kubernetes 高可用集群,说白了就是多个 master 节点同时工作,任何一个 master 挂了,集群仍然能对外提供服务。手动搭建时,你至少要做这么几件事:
- 在三台 master 上分别安装并配置 etcd,三节点 etcd 要生成证书、配置 peer 通信和 client 通信,一个节点写错 IP,集群就起不来。
- 把 kube-apiserver、kube-controller-manager、kube-scheduler 配成 systemd 或 static pod 形式,apiserver 必须通过负载均衡暴露给所有节点。
- 给 Worker 节点准备好 kubelet、kube-proxy 和容器运行时。
- 初始化第一个 master 后,要用 join 命令把另外两个 master 加进来,同时处理 bootstrap token 和证书分发。
这几步里,负载均衡是最容易出问题的。很多教程让你用 HAProxy、Nginx 或者 keepalived + VIP 在前面顶一层,但你想过没有,负载均衡器本身也有单点问题,要么两个 LB 起 keepalived 做漂移,要么让 kubelet、kube-proxy、controller-manager 都去连虚拟 IP,一旦 VIP 漂移、健康检查配置错误,整个集群控制面就访问不到了。
sealos 的思路是把这些复杂操作封装成“集群镜像”。它用 Go 写的,并发 SSH 到所有节点,然后自动做网络检查、镜像分发、组件安装、etcd 集群初始化、负载均衡部署。你不需要关心 kubeadm init 到底改了什么,也基本不用手工生成证书。
1.2 Sealos 的核心机制
sealos 不是替代 kubeadm,而是巧妙地封装了 kubeadm。安装过程中你会在日志里看到类似 [init] using kubernetes version: v1.26.0、[preflight] running pre-flight checks 这样的输出,这就是它内部调用 kubeadm 的标准输出。对于高可用场景,sealos 会为每台 master 节点部署一个内置负载均衡器,用 ipvs 和健康检查把流量转发到各 apiserver 的 6443 端口。它对 etcd 也是直接做成了 static pod 形式,数据目录、证书、启动参数全部由 sealos 统一生成,天然就是三节点集群。
这样做有个非常实际的好处:你不需要再单独引入 HAProxy、Keepalived 这些组件。以前“上层 LB + 后端 apiserver”的模式中,LB 节点有时比 master 还金贵,一旦 LB 挂了,所有 kubectl 命令都会卡死。sealos 把负载均衡能力内置到每个 master 上,master 本身既是控制面节点,也是负载均衡节点,少一层组件就少一层故障。
1.3 什么时候不该用 Sealos
说句公道话,sealos 不是万能的。如果只有一台机器,只想本地学习 Kubernetes,那直接用 minikube 或 k3s 更省事,这台场景下 sealos 反而显得重。如果公司已经有成熟的负载均衡方案,比如 F5、SLB,并且你希望完全手工控制每个组件参数,那可以继续用 kubeadm 一步步装,灵活度更高。
sealos 最舒服的场景就是:你手头有一批全新服务器,操作系统是干净的 Linux 发行版,SSH 能连上,希望在一小时内拿到一套多 master、多 worker、容器运行时和网络插件都配好的生产可用集群。这个定位,sealos 目前确实做得很到位。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 集群规划与前置准备
2.1 节点规划表
先把目标定下来,这次我一共用了 5 台机器,3 台 master 做控制面高可用,2 台 worker 跑业务负载。操作系统全部是 Rocky Linux 9,内核版本 5.14,容器运行时统一用 containerd。这里多说一句,Rocky Linux 9 默认防火墙是 firewalld,SELinux 是 Enforcing 状态,虽然 sealos 会自动做一部分系统配置,但提前处理掉这些项,后面会少很多莫名其妙的报错。
| 节点角色 | 主机名 | IP 地址 | 配置 |
|---|---|---|---|
| master-01 | k8s-master-01 | 192.168.1.10 | 4C8G / 100G SSD |
| master-02 | k8s-master-02 | 192.168.1.11 | 4C8G / 100G SSD |
| master-03 | k8s-master-03 | 192.168.1.12 | 4C8G / 100G SSD |
| worker-01 | k8s-worker-01 | 192.168.1.13 | 8C16G / 200G SSD |
| worker-02 | k8s-worker-02 | 192.168.1.14 | 8C16G / 200G SSD |
为什么要 3 个 master?因为 etcd 集群要能容忍单节点故障,最少就是 3 台,etcd 的 raft 协议在多数派存活时才能选主,2 台节点挂 1 台就直接脑裂了。3 个 master 加 2 个 worker 是比较经典的起步配置,既保证了控制面高可用,又留出了业务资源。
2.2 Rocky Linux 9 系统初始化
先说一个容易踩的坑:不要以为 sealos 能自动帮你做所有初始化,就不管系统了。我的习惯是先把这些固定动作做掉。
bash复制# 关闭 SELinux
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
setenforce 0
# 关闭或放行防火墙端口,测试环境直接关闭 firewalld
systemctl stop firewalld && systemctl disable firewalld
# 关闭 swap,Kubernetes 1.33 依然要求 kubelet 在关闭 swap 的情况下运行
swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab
# 加载必要内核模块,并设置网桥转发参数
cat > /etc/modules-load.d/k8s.conf <<EOF
overlay
br_netfilter
EOF
modprobe overlay && modprobe br_netfilter
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
# 设置主机名,每台机器单独执行
hostnamectl set-hostname k8s-master-01
# master-02 / master-03 / worker-01 / worker-02 按表格修改即可
这些操作做完后,最好检查一下:
bash复制getenforce
free -h
sysctl net.bridge.bridge-nf-call-iptables
SELinux 这里我选择的是 permissive,而不是 enforcing,因为生产环境强制开启 SELinux 需要额外配置容器权限,sealos 生成的组件参数未必匹配所有自定义策略。测试环境用 permissive 够用,但生产环境建议单独评估策略。
另外所有节点的主机名和 /etc/hosts 一定要写好,sealos 在初始化 etcd 节点时,各节点之间需要互相通过主机名解析访问。
bash复制cat >> /etc/hosts <<EOF
192.168.1.10 k8s-master-01
192.168.1.11 k8s-master-02
192.168.1.12 k8s-master-03
192.168.1.13 k8s-worker-01
192.168.1.14 k8s-worker-02
EOF
2.3 网络与 SSH 准备
sealos 需要从其中一台机器作为执行节点,SSH 到所有目标机器上执行命令。所以你得确保执行节点能通过 22 端口访问所有机器,而且密码或密钥对能正常认证。
我一般不会用 root 密码明文跑命令,而是提前把执行节点的 SSH 公钥分发到所有节点:
bash复制ssh-keygen -t rsa -b 4096
ssh-copy-id root@192.168.1.10
ssh-copy-id root@192.168.1.11
ssh-copy-id root@192.168.1.12
ssh-copy-id root@192.168.1.13
ssh-copy-id root@192.168.1.14
公钥分发好后,如果还需要密码,也可以让 sealos 用密码方式工作,但公钥方式更稳,日志里不会因为密码特殊字符被转义而出问题。
此外要注意,节点之间的时间最好同步。Kubernetes 组件和 etcd 对时间偏差很敏感,偏差过大可能导致证书校验失败。我用的比较土的办法,直接在每台机器上配置 chrony 同步:
bash复制dnf install -y chrony
systemctl enable chronyd --now
chronyc sources -v
这些都弄完以后,基本就可以进入了实际安装环节了。
3. Sealos 安装 Kubernetes 高可用集群实操
3.1 下载并安装 sealos
sealos 是一个单一二进制文件,安装方式非常简单。如果你所在环境访问 GitHub 不稳定,可以用阿里云镜像地址下载,这个镜像源在国内访问速度一直不错。
bash复制wget https://mirrors.aliyun.com/sealos/v4.0.0/sealos_4.0.0_linux_amd64.tar.gz -O sealos.tar.gz
tar -zxvf sealos.tar.gz sealos
chmod +x sealos && mv sealos /usr/local/bin/
sealos version
看到版本号输出后,说明基础工具没问题。如果下载时提示证书错误,检查系统时间是不是不对,或者手动加 --no-check-certificate。不过我更推荐先把时间同步好,免得后面 sealos 和 SSH 都出现奇怪的 TLS 问题。
3.2 一条命令拉起集群
准备好执行节点后,直接执行:
bash复制sealos run kubernetes:v1.33.6 \
--masters 192.168.1.10,192.168.1.11,192.168.1.12 \
--nodes 192.168.1.13,192.168.1.14 \
--passwd '你的SSH密码'
如果你刚才已经做了公钥免密登录,这里的 --passwd 可以省略,sealos 会自动探测到密钥登录方式。
执行后日志就像这样:
code复制[init] using kubernetes version: v1.33.6
[preflight] running pre-flight checks
[wait-control-plane] waiting for the kubelet to boot
[etcd] Starting etcd cluster...
[kube-apiserver] waiting for the apiserver to become ready...
...
很多人第一次看到 [preflight] running pre-flight checks 时会紧张,其实这是 sealos 在调用 kubeadm 时打印的标准日志,它在检查主机名是否合法、端口是否被占用、内核参数是否满足要求、swap 是否关闭、容器运行时是否可用。如果某项不通过,日志会直接报出来,常见的就是 swap 没关或 6443 端口被占用。
整个过程大概是这样的:
- sealos 先把 Kubernetes 集群镜像拉取到本地并推送到各节点。
- 在 master 节点上通过 kubeadm 初始化第一个控制面。
- 在其余 master 节点上并行执行 join 操作,把 etcd 和控制面组件补全。
- 在所有 worker 节点上执行 kubeadm join,加入集群。
- 安装 flannel 或 calico 作为 CNI 网络插件。
大约等待 5 到 10 分钟,看到所有输出完毕后,在任意 master 节点执行命令确认:
bash复制kubectl get nodes
kubectl get pods -A
正常你会看到 5 个节点都被列出来,STATUS 是 Ready,CoreDNS、flannel 或 calico 等系统组件都处于 Running 状态。
3.3 加节点:扩展 worker
如果集群想加一台 worker 节点,没必要重新跑整套安装。只需要在新机器上做好前面说的系统初始化(关闭 swap、SELinux 等),然后执行:
bash复制sealos add --nodes 192.168.1.15
sealos 会自动把新节点纳入集群,安装 kubelet、kube-proxy、containerd,并完成 join 流程。过几分钟再看 kubectl get nodes,新节点就会是 Ready 状态。删节点也很干净:
bash复制sealos delete --nodes 192.168.1.15
这个命令会把节点上的相关组件重置并摘除,比手动去 controlplane 上 kubectl drain 再清理要省事。不过需要提醒一句,delete 是直接从集群里踢出去,不会做 pod 优雅迁移,如果节点上有重要业务,先自行迁移 workload 再删。
3.4 集群验证与应用部署测试
集群起来了,但我不会马上把任务交上去,至少要验证两层东西,一是控制面高可用,二是 Pod 网络是否正常。
先测 apiserver 的健康接口:
bash复制kubectl get --raw='/healthz?verbose'
如果输出包含 [+]ping ok、[+]log ok、[+]etcd ok 这些,说明 master 健康检查全过。
然后是验证高可用,随便在一个 master 上停掉 kubelet 或直接关机,等几十秒,再在另外两台 master 上执行 kubectl 命令,看集群是否还能正常响应。理论上只要能保住 etcd 多数派,控制面就不会中断。sealos 内置的负载均衡监听的是 VIP 或本机地址,会自动把 apiserver 请求转发到健康节点。
再部署一个简单的 Nginx 测试业务:
bash复制kubectl create deployment test-nginx --image=nginx:latest
kubectl scale deployment test-nginx --replicas=3
kubectl expose deployment test-nginx --port=80 --type=NodePort
kubectl get pods -o wide
三个副本应该分布在不同的 worker 节点上,通过任意节点 IP 加 NodePort 端口都能访问到页面。到了这一步,整套高可用集群的可用性就已经得到了基本验证。
4. 常见问题与排查技巧实录
4.1 高可用场景下最容易翻车的几个问题
安装过程里遇到问题不奇怪,下面这几个是我在实际使用中碰到或听群友讲过的典型案例,整理成一个速查表。
| 错误信息或现象 | 可能原因 | 处理办法 |
|---|---|---|
[preflight] running pre-flight checks 后报 swap 未关闭 |
系统初始化没做干净,或 /etc/fstab 里仍有 swap 条目 |
执行 swapoff -a 并注释相关行 |
SSH 连接超时或 dial tcp ... connection refused |
22 端口未开放,或防火墙拦截 | 检查 firewalld 状态,放行 22 端口 |
| apiserver 健康检查一直等待 | 镜像拉取慢,或 containerd 配置有问题 | 检查 containerd 状态,配置国内 registry mirror |
| 节点状态显示 NotReady | CNI 网络插件没起来,或 kubelet 异常 | 查看 kubectl get pods -A,重点看 flannel/calico pod |
| 添加节点时报 token 过期 | join 节点间隔时间过长,bootstrap token 失效 | 重新执行 sealos add,它会自动重新生成并分发生成密钥 |
| etcd 集群只有一个节点 ready | master 间时间不同步,或 peer URL 配置错误 | 用 chrony 同步时间,检查 master 之间 2380 端口连通性 |
| kubelet 起不来,日志里有 permission denied | SELinux 干扰 | 临时 setenforce 0 测试,确认后统一配置策略 |
4.2 状态检查三板斧
不管安装还是运维,遇到问题先做这三步,能解决 80% 的困惑:
第一步看节点状态:
bash复制kubectl get nodes -o wide
第二步看系统组件状态:
bash复制kubectl get pods -n kube-system -o wide
第三步看日志:
bash复制journalctl -u kubelet -f
crictl ps -a
crictl logs <container-id>
sealos 安装的 Kubernetes,容器运行时默认是 containerd,所以用 crictl 而不是 docker ps。很多人刚接触时不习惯,其实 crictl 就是专门对接 CRI 的命令行工具,查容器状态、看日志都比 docker CLI 更贴近 Kubernetes 视角。
如果是发愁镜像拉不下来,重点检查 containerd 的 registry mirror 配置。配置文件在 /etc/containerd/certs.d 目录下,sealos 在安装过程中会自动处理一部分,但如果网络环境特殊,镜像源质量差,确实会导致 pod 一直 ImagePullBackOff。可以用 crictl pull 先手动测试能否拉取镜像,再定位是网络问题还是配置问题。
4.3 集群卸载与重建
有人会问,装错了怎么办?重来就行。sealos 提供了 reset 命令,会清理所有节点的 Kubernetes 相关组件:
bash复制sealos reset
执行完以后,节点上的 kubelet、containerd(如果是 sealos 装的)、网络插件都会被清掉,系统和数据盘恢复得比较干净。但注意,如果你之后在集群里部署了自己的业务,reset 会直接全部删除,而且这个操作不会做备份确认,生产环境慎用。
如果只是某个 master 节点坏了,不想推到重来,可以试试:
bash复制sealos delete --masters 192.168.1.11
然后重新添加节点。不过 etcd 数据会从剩余集群恢复,如果你之前的 master 节点数据已经损坏到无法恢复,建议直接 reset 重建,避免 etcd 集群因为“僵尸节点”导致多数派不稳定。
5. 运维侧的一些补充与个人感受
5.1 证书与升级思路
Kubernetes 控制面组件证书默认有效期是一年。集群用了一段时间后,会和 apiserver 的通信报证书过期,这在自建集群里特别常见。sealos 安装的集群,证书管理方式和其他集群类似,可以通过 kubeadm 命令查看:
bash复制kubeadm certs check-expiration
不同的 Kubernetes 版本会在证书到期前提醒你,留意控制面日志即可。升级思路也不复杂,用新版本的 cluster image 重新执行 run 命令,sealos 会负责把 etcd、apiserver、kubelet 等组件滚动升级。但任何升级都要遵守一个原则:先升级到相邻的小版本,不要跨大版本直接跳,尤其生产环境。
5.2 etcd 和 apiserver 的日常健康检查
高可用集群中,最核心的就两个东西:etcd 和 apiserver。我的习惯是借着 crontab 或监控系统每天做一次探测:
bash复制kubectl get --raw='/readyz'
如果 apiserver 不可用,控制面就不稳定。另外 etcd 可以看集群内 pod 日志,也可以在 master 节点上直接检查端口探测是否通:
bash复制ss -tnlp | grep 2379
ss -tnlp | grep 2380
2379 是 etcd client 端口,2380 是 peer 通信端口。如果 2380 不互通,etcd 集群等于直接分裂,这是高可用集群里最需要盯紧的指标。
5.3 个人使用体验
我把话说在前头,sealos 并不是“黑魔法”,它只是把你手动搭建时那些可重复、高风险的步骤规范化了。正因如此,它非常适合那些没有专职运维、或不想维护一堆安装脚本的团队。这次基于 Sealos 安装 Kubernetes 1.33.6 高可用集群的体验,整体上是省心的,尤其在负载均衡、etcd 初始化这两块,省掉了大量手工操作。我也把整个流程沉淀到了团队文档里,后续再扩节点或者重装环境,10 分钟就能拉一套新集群出来。如果你正准备搭自建 K8s,又不想熬夜盯命令行,真的可以试试这一套流程。
