Kubernetes 裸机部署的难点,不是把命令逐条执行一遍,而是先把节点、运行时、网络和故障边界设计清楚。对于学习集群、内网服务或希望掌握底层运维流程的团队,kubeadm 仍然是一条清晰的入口;但生产环境不能简单照搬实验室脚本。
本文把一套从零搭建集群的过程重新整理为“先理解架构,再准备主机,最后初始化和验收”的路径,并重点说明 Docker、CRI、Harbor、Flannel 之间的关系。
先判断:裸机 K8S 适合什么场景
裸机部署适合以下情况:
- 需要掌握控制平面、节点和容器运行时的工作边界;
- 有多台云服务器或物理机,希望统一调度服务;
- 需要自建镜像仓库、网络插件和发布流程;
- 接受自行处理升级、证书、etcd 备份和节点故障。
如果目标只是快速运行几个网站或微服务,托管 Kubernetes 往往更省运维成本。裸机方案的价值在于可控和可学习,而不是命令更少。
集群架构:先分清控制平面与工作节点
一个 Kubernetes 集群由控制平面和一个或多个工作节点组成。控制平面负责接受声明、保存状态和做调度决策;工作节点负责运行 Pod。常见组件可以按职责理解:
- API Server:集群资源的统一入口,
kubectl、控制器和其他组件都通过它交互; - etcd:保存集群状态的键值数据库,磁盘可靠性和备份策略直接影响集群恢复;
- Scheduler:根据资源、亲和性、污点等条件选择 Pod 的目标节点;
- Controller Manager:持续比较“期望状态”和“实际状态”,并触发修复;
- kubelet:运行在每个节点上,负责 Pod 生命周期和节点状态上报;
- 容器运行时:真正创建和管理容器;
- kube-proxy:协助实现 Service 的网络转发。
因此,部署前至少要规划三类信息:节点角色、节点间网络、Pod 与 Service 的地址段。地址段不能与办公网、云服务器 VPC 或 VPN 网段重叠,否则网络插件上线后可能出现“节点互通但服务不通”的问题。
主机准备:把不稳定因素提前消除
1. 统一系统和节点信息
所有节点尽量使用相同的 Linux 发行版、内核策略和时间同步方式,并为每台主机设置稳定的主机名。准备好节点清单:
control-plane 192.168.10.10
worker-1 192.168.10.11
worker-2 192.168.10.12生产环境还应提前规划控制平面高可用、负载均衡入口、etcd 数据盘和备份位置。单控制平面适合实验和小规模内部服务,不应被称为高可用集群。
2. 检查 swap、内核参数和端口
按照所选 Kubernetes 版本的安装文档完成 swap、内核模块、桥接网络和转发参数配置。不要只复制旧教程中的参数:不同发行版的默认值、cgroup 驱动和防火墙策略可能不同。
部署前逐台检查:
hostnamectl
free -h
lsmod | grep -E 'overlay|br_netfilter'
sysctl net.ipv4.ip_forward同时确认控制平面与工作节点之间的 API Server、kubelet、节点网络插件和 DNS 所需通信没有被安全组或防火墙拦截。云服务器上,安全组规则和操作系统防火墙需要同时检查。
容器运行时:不要把 Docker 等同于 CRI
Kubernetes 通过 CRI(Container Runtime Interface)与容器运行时交互。Docker Engine 本身不直接实现 CRI;如果坚持使用 Docker,需要额外部署 cri-dockerd 并让 kubelet、kubeadm 指向对应的 Unix socket。更直接的路径通常是选择兼容 CRI 的运行时,并统一 kubelet 与运行时的 cgroup driver。
这也是很多旧教程失败的原因:它们把 Docker 安装成功当成 Kubernetes 已经具备运行条件。实际验收应至少包括:
systemctl status <runtime-service>
crictl info
systemctl status kubelet如果使用 Docker + cri-dockerd,初始化或加入节点时显式指定 CRI socket,避免机器上同时存在多个运行时导致自动探测结果不符合预期。Kubernetes 官方文档也明确说明,Docker Engine 需要通过 cri-dockerd 接入,而不是直接作为 CRI 端点使用。
kubeadm 部署主线:初始化、网络、扩容
1. 安装 kubelet、kubeadm 和 kubectl
三者职责不同:kubeadm 负责创建和加入集群,kubelet 负责节点上的 Pod 生命周期,kubectl 是管理命令行工具。版本应锁定在同一支持范围内,并使用 Kubernetes 官方软件源,不要混用多套仓库。
2. 初始化控制平面
在控制平面执行初始化时,明确 Pod 网段、API Server 地址和 CRI socket。初始化成功后,将管理员 kubeconfig 放到当前用户目录,并立即执行:
kubectl get nodes
kubectl get pods -A此时节点可能仍显示 NotReady,因为网络插件尚未安装,这是正常的中间状态。不要在网络插件未就绪前急着部署业务。
3. 安装 CNI 网络插件
Flannel 等 CNI 插件负责 Pod 网络连通。安装前确认它使用的 Pod 网段与初始化参数一致;如果两者不一致,常见表现是 CoreDNS 一直无法运行、Pod 跨节点通信失败或 Service 访问异常。
验收时观察:
kubectl get pods -A
kubectl get nodes -o wide
kubectl describe node <node-name>4. 加入工作节点
使用初始化输出的 kubeadm join 命令加入工作节点。生产环境不要把 join token 长期暴露在工单、聊天记录或脚本仓库中;如果 token 泄露,应重新生成并限制节点间的网络访问。
Harbor 与镜像供应链
自建 Harbor 的意义不只是“存镜像”,还包括版本留存、访问控制、漏洞扫描和内网拉取。建议按环境划分项目,例如 dev、staging 和 prod,并为节点配置可信证书或明确的 TLS 策略。
业务发布前先验证完整链路:开发机推送镜像、Harbor 保存镜像、工作节点拉取镜像、Pod 成功启动。仅在控制平面上 docker pull 成功,不能证明工作节点能够拉取;每类节点都要检查 DNS、证书、凭据和出站网络。
生产化前必须补上的检查
这套部署流程可以作为学习和初始搭建框架,但要进入生产,还需要补齐:
- 高可用:多个控制平面节点、稳定的 API Server 入口和可靠的 etcd 拓扑;
- 备份恢复:定期备份 etcd,并在备用环境演练恢复,而不是只保留配置文件;
- 证书管理:定期检查 kubeadm 证书有效期,明确轮换窗口;
- 资源与存储:为系统组件预留 CPU、内存和磁盘,规划持久卷及快照;
- 可观测性:接入日志、指标和告警,至少能定位节点、Pod、网络和镜像四类故障;
- 升级策略:先在非生产集群验证版本,再按控制平面、节点和应用的顺序滚动升级。
常见故障的排查顺序
遇到 Pod 启动失败时,不要一开始就重装集群。可以按下面的顺序缩小范围:
kubectl describe pod查看调度、挂载和事件;kubectl get nodes确认节点是否 Ready、资源是否耗尽;- 在目标节点查看 kubelet 和运行时日志;
- 检查镜像仓库连通性、证书和拉取凭据;
- 最后再检查 CNI、Service、DNS 和网络策略。
如果 etcd 报磁盘空间不足,应先检查数据目录、事件历史和备份状态;如果证书过期,则使用对应版本的 kubeadm 工具检查和更新,更新后再验证控制平面组件。把故障处理写成 Runbook,比临时依赖某个管理员的记忆更可靠。
裸机 Kubernetes 的正确打开方式,是把它当成一套分层系统来部署:主机层保证稳定,运行时层提供容器能力,kubeadm 负责集群引导,CNI 负责网络,Harbor 负责镜像供应链,最后再由监控、备份和升级策略把实验集群变成可维护的平台。