这次我们来看一套比较实用的交付形态:基于 VMware 虚拟机的三节点 Kubernetes 集群运行环境,版本固定为 Kubernetes 1.29.14。它的核心价值是把“Kubernetes 多节点集群”从云主机或裸金属搬到本地虚拟机里,一台 Windows/Linux 宿主机配上 VMware Workstation,就能获得一套可控、可快照、可反复推倒重来的 K8s 实验环境。
先看几个关键信息:集群规模是三节点,通常是一台控制平面节点加两台工作节点;集群初始化使用 kubeadm,这是当前本地部署 Kubernetes 最标准的方式;容器运行时使用 containerd;底层虚拟化平台是 VMware Workstation 或 vSphere/ESXi。宿主机硬件门槛并不高,重点看内存和磁盘,CPU 只要支持虚拟化并开启 VT-x/AMD-V 即可。这套环境的核心能力包括:支持 kubectl 和 Kubernetes API 访问、支持 Deployment/Job/CronJob 等批量任务、支持多节点调度观察、支持通过 VMware 快照快速回滚。
这篇文章会带你把整条链路走通:宿主机与 VMware 环境准备、三台虚拟机资源规划、节点系统初始化、containerd 与 kubeadm/kubelet/kubectl 安装、控制平面初始化、工作节点加入、网络插件部署、集群功能验证,最后是一份可以直接参考的排查清单。如果你是第一次在 VMware 虚拟机上搭 Kubernetes 集群,这篇文章可以当作一份 Checklist 使用。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 基于 VMware 虚拟化的多节点 Kubernetes 集群运行环境 |
| 集群规模 | 3 节点:1 个控制平面节点 + 2 个工作节点 |
| Kubernetes 版本 | 1.29.14 |
| 虚拟化平台 | VMware Workstation Pro / VMware vSphere |
| 容器运行时 | containerd(Kubernetes 1.29 兼容运行时) |
| 集群初始化方式 | kubeadm |
| 网络插件 | Calico 或 Flannel,按环境二选一 |
| 节点最低规格 | 每节点 2 核 CPU / 2 GB 内存(官方最低要求) |
| 推荐宿主机内存 | 16 GB 及以上,三节点资源叠加后需要留出余量 |
| 推荐磁盘 | SSD,建议 200 GB 可用空间 |
| API 能力 | kube-apiserver 6443 端口,kubectl 与 REST API 均可访问 |
| 批量任务 | 通过 Deployment、Job、CronJob 原生支持 |
| 适用场景 | 本地学习、开发测试、离线演示、CI 流水线验证 |
这里需要说清楚:这套环境不是生产级高可用集群,而是可复现的本地实验环境。三节点拓扑的好处是能够覆盖控制平面和工作节点分离后的主要管理操作,比如节点调度、故障转移观察、跨节点 Pod 分布,资源占用又不会太高。从材料来看,这个环境定位更像是“预置好了跑 K8s 的虚拟机骨架”,接下来所有部署动作都由你在控制台上完成。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 适用场景与使用边界
适合用这套环境的人有三类。第一类是刚开始学 Kubernetes 的开发者,kubeadm init、kubeadm join、CNI 网络插件、节点状态排查这一套流程,在虚拟机上做成本最低,做错了拍快照回滚即可。第二类是需要在隔离环境里反复验证部署脚本、Helm Chart、Operator 逻辑的运维工程师,在虚拟机里测试不会污染真实业务。第三类是需要在无外网或弱外网环境下做演示和培训的团队,三节点虚拟机可以直接打包迁移。
它不适合什么场景也很明确。不适合做生产环境,单台物理机上的 VMware 虚拟机集群存在宿主机单点故障,etcd 和业务 Pod 都在同一块物理磁盘上。不适合做高并发压测,虚拟机磁盘 IO 和网络转发都会成为瓶颈。不适合做大规模数据存储,除非后续接入外部存储和独立备份。如果目标是学习高可用架构,这套环境至少需要扩到五节点或部署三控制平面 HA,并且在虚拟机层面配置反亲和规则。
使用边界方面必须注意合规和安全。VMware 和 Linux 发行版镜像要按对应授权协议使用,Kubernetes 与 containerd 等开源组件遵循各自 License。如果虚拟机要接入外部网络,不要直接把 kube-apiserver 的 6443 端口映射到公网。涉及真实业务数据或用户信息时,先确认脱敏和授权,再进入测试环境。
3. 环境准备与虚拟化平台配置
3.1 宿主机虚拟化检查
宿主机推荐使用 VMware Workstation Pro 17,也可以使用 VMware vSphere/ESXi。安装 VMware 之前先确认 CPU 虚拟化已经开启。
在 Windows 宿主机上打开任务管理器,进入“性能”选项卡,查看“虚拟化”状态是否显示“已启用”。如果显示禁用,需要进 BIOS/UEFI 开启 Intel VT-x 或 AMD-V。这一步很多人会漏掉,结果就是虚拟机开机直接报“无法启用虚拟机平台”或“VT-x is not available”。
Linux 宿主机可以用下面命令检查:
bash复制grep -E 'vmx|svm' /proc/cpuinfo
如果有 vmx 或 svm 输出,说明 CPU 支持虚拟化。还需要确认宿主机内存至少 16 GB,三台虚拟机叠加后建议留出 4 GB 以上给宿主机自己使用。
3.2 VMware 网络模式与 IP 规划
VMware 虚拟机网络建议使用 NAT 或桥接模式。NAT 模式适合完全隔离的本地实验,虚拟机之间可以通过虚拟网络互通,宿主机也能访问虚拟机,但外部网络访问虚拟机需要端口转发。桥接模式让虚拟机直接获取局域网 IP,适合需要被其他机器访问的场景。
集群内部通信需要稳定的 IP,不能依赖 DHCP 随机分配。建议在 VMware 的 NAT 设置里固定 DHCP 地址绑定,或者在虚拟机内部直接配置静态 IP。更稳妥的做法是在三个节点的 /etc/hosts 里写好互相的主机名映射,避免 Kubernetes 组件之间因为主机名解析失败而报错。
3.3 系统镜像与软件清单
操作系统建议使用 Ubuntu 22.04 LTS Server 或 Rocky Linux 9,下面命令以 Ubuntu 的 apt 包管理为例。Kubernetes 1.29.14 官方支持主流 Linux 发行版,选哪个取决于团队维护习惯。
软件清单如下:
- VMware Tools:每个虚拟机安装后启用,便于剪贴板共享、文件拖拽和性能优化
- kubeadm、kubelet、kubectl:版本固定为 1.29.14
- containerd:容器运行时,版本选择与 Kubernetes 1.29 兼容的 1.7.x 或更新版本
- Calico 或 Flannel:Pod 网络插件,二选一
- metrics-server:可选,用于 kubectl top 查看节点和 Pod 资源占用
4. 三节点虚拟机规划与系统初始化
4.1 节点角色与资源分配
三台虚拟机建议按下表分配资源。
| 角色 | 主机名建议 | 推荐 CPU | 推荐内存 | 推荐磁盘 | 运行组件 |
|---|---|---|---|---|---|
| 控制平面节点 | k8s-master | 2 核 | 4 GB | 40 GB | kube-apiserver、etcd、kube-scheduler、kube-controller-manager |
| 工作节点 1 | k8s-node1 | 4 核 | 8 GB | 80 GB | 业务 Pod |
| 工作节点 2 | k8s-node2 | 4 核 | 8 GB | 80 GB | 业务 Pod |
这组配置属于常见推荐范围,不是绝对标准。实际占用取决于你部署的 Pod 数量和镜像大小。可以先按 2 核 / 4 GB 跑通集群,再根据 kubectl top 的观察结果扩容。
4.2 节点基础初始化命令
三台虚拟机都要执行相同的系统初始化步骤,顺序是先关闭 swap,再加载内核模块,最后配置内核参数。
关闭 swap:
bash复制sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
加载 overlay 和 br_netfilter 模块:
bash复制cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
配置 Kubernetes 需要的内核参数:
bash复制cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
配置完成后用 sysctl net.bridge.bridge-nf-call-iptables 验证返回值是否为 1。如果系统没装 bridge 相关模块,可以先安装 bridge-utils 再做 modprobe。
4.3 主机名与 hosts 配置
每台虚拟机设置独立主机名:
bash复制sudo hostnamectl set-hostname k8s-master
sudo hostnamectl set-hostname k8s-node1
sudo hostnamectl set-hostname k8s-node2
然后在三个节点的 /etc/hosts 中写入相同的映射,示例 IP 需要替换成你的实际环境:
bash复制192.168.10.10 k8s-master
192.168.10.11 k8s-node1
192.168.10.12 k8s-node2
这一步很关键。kubeadm 初始化时 kubelet 会通过主机名注册节点,如果节点之间无法互相解析主机名,会出现 TLS 证书校验失败和节点 NotReady 的问题。
5. 安装容器运行时与 Kubernetes 1.29.14 组件
5.1 安装 containerd
先安装 containerd:
bash复制sudo apt update
sudo apt install -y containerd
生成默认配置,并开启 SystemdCgroup:
bash复制sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
SystemdCgroup 必须设为 true,否则 kubelet 与 containerd 对 cgroup 驱动理解不一致,Pod 可能反复 CrashLoopBackOff。修改配置后重启 containerd:
bash复制sudo systemctl restart containerd
国内网络环境下,可以同时修改 containerd 配置中的 registry 镜像加速地址,把 docker.io 和 registry.k8s.io 的拉取路径指向可用镜像仓库。具体地址要按你实际可用的镜像加速服务填写,不要使用来路不明的公共地址。
5.2 安装 kubeadm、kubelet、kubectl
使用 Kubernetes 官方 apt 源安装,将版本固定为 1.29.14:
bash复制sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet=1.29.14-* kubeadm=1.29.14-* kubectl=1.29.14-*
sudo apt-mark hold kubelet kubeadm kubectl
注意 kubelet=1.29.14-* 后面的通配符表示仓库里具体的 revision 号可能不同,这是 Debian 包管理的正常现象。apt-mark hold 的作用是防止后续 apt upgrade 把三个组件升级到其他版本,集群版本保持固定非常重要。
如果官方源在特定网络环境访问不稳定,可以改用国内可用的 Kubernetes 镜像源,但配置前需要验证源地址的可用性和安全性。
5.3 预拉取镜像
在控制平面节点上执行 kubeadm config images pull,提前把控制平面组件镜像拉下来:
bash复制sudo kubeadm config images pull \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.29.14
如果你的网络可以直接访问 registry.k8s.io,也可以不指定 image-repository。这里用的是国内常见镜像仓库,具体可用性以你所在网络为准。预拉取的好处是能提前发现镜像仓库连通性和版本匹配问题,避免 init 过程中因为拉镜像超时而失败。
6. 集群初始化、网络插件与节点加入
6.1 初始化控制平面
在 k8s-master 节点执行 kubeadm init。下面命令中的 IP 是示例,必须替换为控制平面节点实际 IP,pod-network-cidr 取值要和你选择的网络插件匹配。这里使用 Flannel 常用的 10.244.0.0/16:
bash复制sudo kubeadm init \
--kubernetes-version=v1.29.14 \
--control-plane-endpoint=192.168.10.10 \
--apiserver-advertise-address=192.168.10.10 \
--pod-network-cidr=10.244.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers
初始化成功的标准是看到 “Your Kubernetes control-plane has been initialized successfully!” 输出,并且末尾会给出 kubeadm join 命令。如果初始化中途失败,先不要盲目重试,先看日志。常见失败点是镜像拉取超时、swap 未完全关闭、/etc/hosts 配置错误。
6.2 配置 kubectl 与部署网络插件
初始化完成后,在控制平面节点执行:
bash复制mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
然后用 kubectl get nodes 查看节点状态,此时控制平面节点可能还是 NotReady,因为还没有部署 Pod 网络插件。
部署 Calico 网络插件:
bash复制kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/calico.yaml
这里 v3.28.2 是示例版本号,实际部署前建议到 Calico 官方 release 页面确认与 Kubernetes 1.29 匹配的版本,并替换 URL 中的版本号。如果选择 Flannel,则下载对应 flannel.yml 后 apply,同时 kubeadm init 时要把 pod-network-cidr 设为 10.244.0.0/16。
6.3 工作节点加入与状态验证
在两台工作节点执行 kubeadm init 输出的 join 命令。命令长这样,实际 token 和 hash 以 init 输出为准:
bash复制sudo kubeadm join 192.168.10.10:6443 \
--token xxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxx
如果 token 超过 24 小时有效期,在控制平面节点重新生成:
bash复制sudo kubeadm token create --print-join-command
节点全部加入后,回到控制平面节点验证:
bash复制kubectl get nodes -o wide
kubectl get pods -A -o wide
预期结果是三个节点 STATUS 都为 Ready,kube-system 命名空间下的 CoreDNS 和其他系统组件处于 Running 状态。这里要重点观察 READY 列,如果某个节点迟迟不 Ready,大概率是网络插件问题或节点时间不同步。
7. 集群功能验证:API 访问、工作负载与批量任务
7.1 验证 Kubernetes API Server
这套环境最核心的接口就是 Kubernetes API Server。kubectl 所有操作最终都会转换成 REST API 请求,端口是 6443。验证 API 是否正常响应:
bash复制curl --cacert /etc/kubernetes/pki/ca.crt https://127.0.0.1:6443/version
接口会返回类似这样的 JSON 内容:
json复制{
"major": "1",
"minor": "29",
"gitVersion": "v1.29.14"
}
拿到这个返回,说明 apiserver、证书、kubectl 配置链路完全通了。后续不管接什么自动化工具,本质上都是调 6443 端口上的 /api 和 /apis 接口。
7.2 用 Nginx 验证工作负载调度
部署一个三副本 Nginx Deployment,验证 Pod 是否按照预期分布到三个节点:
bash复制kubectl create deployment nginx-demo --image=nginx:1.25-alpine --replicas=3
kubectl get pods -o wide
如果调度正常,三个 Pod 会分散到不同节点上。然后暴露服务:
bash复制kubectl expose deployment nginx-demo --type=NodePort --port=80
kubectl get svc nginx-demo
拿到 NodePort 后,在任意节点用 curl http://节点IP:NodePort 访问,能返回 Nginx 默认页面就说明 Service、kube-proxy、Pod 网络链路正常。
7.3 验证 CoreDNS 服务发现
Kubernetes 集群内部 DNS 是服务发现的基础。创建一个临时 Pod 执行 nslookup:
bash复制kubectl run -it --rm debug-pod \
--image=busybox:1.36 \
--restart=Never \
-- nslookup kubernetes.default
正常情况下会解析出 kubernetes.default.svc.cluster.local 对应的 ClusterIP。如果解析超时,问题基本锁定在 CoreDNS 或网络插件。
7.4 验证 Job 批量任务
批量任务直接交给 Kubernetes 原生的 Job 控制器。跑一个计算圆周率的经典 Job:
bash复制kubectl create job pi --image=perl:5.34 \
-- perl -Mbignum=bpi -wle 'print bpi(2000)'
查看执行结果:
bash复制kubectl get job pi
kubectl logs job/pi
Job 状态变为 Completed 并输出计算结果,说明批处理能力正常。这套环境后续接 CronJob、定时数据同步、离线计算任务都走同一个链路。
8. 资源占用与性能观察
8.1 观察宿主机与节点资源
VMware Workstation 里可以直接看到每台虚拟机的 CPU 和内存实时占用。节点内部用 free -h 看内存,df -h 看磁盘,top 看 CPU。集群层面需要先部署 metrics-server:
bash复制kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
部署完成后:
bash复制kubectl top nodes
kubectl top pods -A
从常见部署经验来看,三节点集群启动后,控制平面节点的基础内存占用通常在 2 到 4 GB 之间,工作节点基础组件占用 1 到 2 GB,剩余内存取决于业务 Pod 数量。这只是一个观察方向,具体数值要以你本机测试为准,不同镜像、不同副本数差异很大。
8.2 影响性能的关键因素
第一个因素是磁盘 IO。三台虚拟机共享宿主机物理磁盘,业务 Pod 写日志、etcd 写数据、镜像拉取解压会同时抢磁盘。优先给虚拟机分配 SSD 存储,避免机械硬盘导致的卡顿。
第二个因素是内存超配。如果宿主机内存只有 16 GB,三台虚拟机各分 4 GB/8 GB 后剩余空间很小,虚拟机之间会发生内存 Swap,节点响应变慢。出现这种情况就削减节点内存或减少业务 Pod 副本数。
第三个因素是网络模式。NAT 模式下节点间流量经过虚拟网卡转发,性能比桥接模式稍低。本地实验差别不大,如果要跑网络密集型应用,建议改用桥接模式并给节点配置静态 IP。
8.3 快照与回收策略
VMware 快照是这套环境最有价值的运维手段。集群初始化成功后,先拍一个“基线快照”,后续安装任何组件前再拍一个,出问题直接回滚,比重新初始化快得多。
磁盘回收方面,注意 /var/lib/containerd 的镜像缓存和 /var/lib/kubelet 的 Pod 日志会持续增长。定期执行:
bash复制sudo crictl rmi --prune
sudo journalctl --vacuum-time=2d
减少无用的镜像和日志占用的磁盘空间。
9. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| kubeadm init 拉取镜像超时 | 镜像仓库不可达,或网络未配置加速 | kubeadm config images list 查看镜像列表,手动 docker pull 测试 | 配置可用镜像加速地址,或更换 image-repository |
| 节点 STATUS 一直 NotReady | CNI 网络插件未部署,或节点时间不同步 | kubectl describe node 查看条件,journalctl -u kubelet 看日志 | 部署 Calico/Flannel,安装 chrony 同步时间 |
| CoreDNS 一直 Pending | 网络插件未就绪或节点资源不足 | kubectl describe pod -n kube-system | 等待网络插件就绪,检查节点内存 |
| Pod 一直 ContainerCreating | 镜像拉取失败,或 CNI 配置异常 | kubectl describe pod 查看事件 | 修复镜像地址,重启 containerd |
| kubeadm join 失败,提示 token 过期 | token 有效期 24 小时 | 控制节点执行 kubeadm token list | 重新执行 kubeadm token create --print-join-command |
| VMware 虚拟机无法开机 | BIOS 未开启 VT-x/AMD-V | 检查任务管理器虚拟化状态 | 进 BIOS 开启虚拟化 |
| 虚拟机之间网络不通 | hosts 配置错误,或 VMware 网络模式不一致 | ping 节点 IP 和主机名 | 统一网络模式,修改 /etc/hosts |
| 访问 NodePort 服务不通 | kube-proxy 异常或防火墙拦截 | kubectl get svc 查看端口,curl 节点 IP | 重启 kube-proxy,放行 30000-32767 端口 |
| 节点 OOM 导致 Pod 被杀 | 节点内存不足,Pod 无 limits | kubectl top nodes 查看占用 | 减少副本数,给 Pod 设置 resources.limits |
| 证书过期导致 API 无法访问 | kubeadm 证书默认一年有效期 | kubeadm certs check-expiration | 执行 kubeadm certs renew all 并重启组件 |
如果 kubelet 报错但无法定位,先看服务状态:
bash复制sudo systemctl status kubelet
sudo journalctl -u kubelet -f
排查顺序是:网络通不通 -> 时间是否同步 -> 镜像能不能拉 -> 证书是否有效 -> 资源是否够用。按这个顺序走一遍,大部分集群搭建问题都能定位到具体环节。
10. 最佳实践与后续扩展建议
第一次搭建时,单节点跑通再扩展节点。先用最小配置完成控制平面初始化,加入第一个工作节点,验证 Nginx 部署之后,再添加第二个工作节点。这样每一步出问题都知道是哪一台机器引起的。
建立虚拟机快照基线。集群初始化完成、加入两个工作节点、部署好 Calico 之后,这个状态非常值得保存。后续所有的 Helm 安装、存储插件、监控组件测试都基于这个基线,安装失败就回滚,不需要重装系统。
给工作负载设置资源限制。任何 Deployment 都应该声明 requests 和 limits,否则一个内存泄漏的 Pod 可能拖垮整个虚拟机。示例:
yaml复制resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
合规边界再强调一次:不要在未授权情况下对真实人脸、声音、版权素材做处理实验,不要将 6443 端口暴露到公网,不要在未授权服务器上抓取数据。这套环境只用于学习、开发和演示,涉及业务数据必须先脱敏。
后续可以继续在这个环境上做的实验方向包括:部署 Redis 集群、Kafka 集群验证有状态应用编排;通过多控制平面扩展实现高可用;部署 Ingress Controller 接管 HTTP 流量;接入 Prometheus + Grafana 监控集群状态。每一条路线都能在这个三节点环境里先跑通,再决定是否上真实生产环境。
11. 最后:把这套环境变成你的实验台
这套基于 VMware 虚拟机的三节点 Kubernetes 1.29.14 集群环境,最值得先验证的是三件事:节点全部 Ready、Nginx Deployment 跨节点调度、Job 批量任务正常完成。这三个状态都确认了,集群核心链路就没有问题。
最容易踩的坑集中在三个地方:第一是 BIOS 里没开虚拟化导致 VMware 虚拟机无法启动;第二是 swap 没关干净导致 kubeadm init 失败;第三是网络插件和 pod-network-cidr 不匹配导致节点 NotReady。这三类问题占了新手搭建集群的大多数报错。
先拍快照,再改配置。建议把整篇操作过程保存为你的部署笔记,跑通之后拍一个基线快照。后面不管是学习 Kubernetes 调度、部署 Redis/Kafka 集群,还是测试 CI/CD 流程,都可以随时从这个基线重新开始。
