vSphere 7 发布那天,我盯着“Kubernetes 原生集成”这几个字看了很久。说实话,在它之前我从没想过,一个以虚拟机为中心的平台会把容器编排提到这么高的优先级。但如果你真正上手用一段时间就会发现,这并不只是加了一个新功能,而是把 Kubernetes 的 API 变成了 vSphere 的入口之一。
这篇文章不打算做长篇理论科普,也不复述官方文档里反复出现的概念。我想以一个既做过虚拟化运维、又折腾过自建 K8s 的人的身份,记录一次完整的 vSphere 7 Kubernetes 初体验:从架构思路、部署前置条件,到激活 Workload Management、创建 Tanzu 集群、跑通第一个应用,再到我踩过的坑和排查方法。如果你是第一次接触这套东西,跟着走一遍,应该能省下不少琢磨时间。
1. 为什么 vSphere 7 非要把 Kubernetes 塞进来
vSphere 7 之前,大多数企业的状态是:虚拟化平台管虚拟机,容器平台管容器,两套系统、两套运维、两套监控,互不相通。虚拟机团队关心资源池、DRS、HA;容器团队关心 Pod、Deployment、Service。一旦线上出了性能问题,两边先各自排查,最后才在某个中间层通报会上一拍桌子,发现都在抢同一批物理资源。
vSphere 7 with Kubernetes 的核心思路,就是要把这两套体系合并到同一个控制平面里。它引入了三个并列的能力:
- Supervisor Cluster:vCenter 本身变成一个 Kubernetes 控制平面,物理的 ESXi 主机以集群节点的形式被 Kubernetes 调度。你在 vCenter 里看到的资源池、主机、存储,都能被 Kubernetes 感知到。
- vSphere Pod Service:一个 Pod 就是一个独立 VM,拥有虚拟机级别的隔离边界。它不像普通容器那样依赖宿主机内核共享,而是把每个 Pod 都包在可独立引导的 VM 里。这样做的好处是安全隔离性更强,坏处是资源开销比普通容器大。
- Tanzu Kubernetes Grid Service (TKGS):在 Supervisor Cluster 之上,按需生成完整 Kubernetes 集群,也就是俗称的 TKC(Tanzu Kubernetes Cluster)。你可以像创建虚拟机一样,在 vCenter 里点几下,就得到一个生产可用的独立 K8s 集群。
我第一次把这三个概念理清楚的时候,脑子里冒出来的画面是:以前我们要在机房架一台物理服务器,装好虚拟化层,再在一台虚拟机里装 K8s,然后再把应用跑上去;现在虚拟化层和 K8s 控制平面混在一起了,你只需要告诉 vCenter“我要一个两节点的 Kubernetes 集群”,剩下的由平台去完成。
这个方案对已经投资了 vSphere 的企业来说特别有意义。不用推翻现有的虚拟化架构,不用让运维团队立即转型去学裸金属集群管理,就能在熟悉的 vCenter 界面上用上 Kubernetes。开发侧和运维侧各拿各的工具:开发用 kubectl,运维看 vCenter,背后是同一套物理资源池。
2. 部署前要想清楚的事:集群、网络、存储和内容库
2.1 计算资源要怎么规划和预留
启用 Workload Management 的前提是有一个运行正常的 vSphere 集群。官方要求集群里至少有三台 ESXi 主机,实际测试时我建议别少于三台,因为 Supervisor Cluster 自身的控制平面组件就有不少 VM 需要调度,主机太少很容易出现资源不足导致部署卡住。
DRS 必须开启,而且调度模式要设为“全自动”,否则 Workload Management 激活流程会直接弹错误。HA 建议开启,但初期测试可以先不开。EVC(增强 vMotion 兼容性)最好打开,这样后续节点的 vMotion 迁移更稳妥。
从资源预留角度来看,不要按“正好够用”去算。我测试环境里每台 ESXi 配置了 16 核 CPU、64GB 内存和 1TB SSD,三台加起来一共 48 核、192GB 内存,一开始觉得挺宽裕。结果 Supervisor Cluster 控制平面起来之后,我创建第一个 TKC 时发现可用资源比预期少了一大截,原因在于 Supervisor 自身会预留一部分资源,而且命名空间配额还需要显式分配。所以如果是生产使用,建议起步就是每台主机 32 核、512GB 内存,不要委屈它。
2.2 网络方案:NSX-T 还是 vDS 端口组
这是部署前必须想清楚的一个分岔口。vSphere 7 初始版本对 Workload Management 的完整支持依赖 NSX-T,用 NSX-T 可以给每个网络提供独立的管理平面、安全策略和负载均衡能力。但 NSX-T 本身的部署和维护门槛不低,对很多只想体验一下的团队来说太重。
vSphere 7 Update 1 之后,VMware 开放了基于标准 vDS 的方案,也就是直接给 Supervisor Cluster 指定一个标准交换机端口组来承载工作负载网络。这个方案大大降低了入门门槛,没有 NSX-T 那套复杂组件,只需要在 vCenter 里提前建好 vDS、配置好上行链路和 VLAN,划分出管理网络、vSphere Pod 网络、Tanzu Kubernetes 集群网络需要的网段就行。
我在测试环境里用的是 vDS 方案,因为目的就是快速验证。如果你的目标是生产化部署,而且你已经有一套成熟的 NSX 环境,那走 NSX-T 路线会更完整,特别是负载均衡能力会强很多。vDS 方案下,创建 TKC 后要对外暴露 Service,负载均衡器支持是受限的,这点后面会详细说。
2.3 存储策略是能否创建集群的关键
vSphere 7 with Kubernetes 对存储有两个要求:必须是共享存储,并且要正确设置 VM 存储策略。所谓共享存储,意思是所有 ESXi 主机都能看到同一份存储,这是 DRS 和 HA 的基础。vSAN、iSCSI、FC 存储都可以,官方文档里推荐 vSAN,因为它能和 vSphere 存储策略无缝集成。
为什么存储策略这么重要?因为 TKC 的每个节点都是通过 OVA 模板创建的虚拟机,这些虚拟机要获得持久化存储,就得依赖 vSphere Storage Policy。在 vSAN 环境中,默认策略就能满足大多数场景;如果用传统共享存储,需要手动创建一个允许“精简置备”或“厚置备”的策略,并且在 Workload Management 激活时把它选上。
还有一个容易忽略的点:内容库里的 OVA 模板本身也需要存储空间。我建议单独给内容库分配一个数据目录,避免和运行的虚拟机抢空间,尤其是当 TKG 模板有几十 GB 的时候。
2.4 内容库:TKC 集群的“模板来源”
在激活 Workload Management 之前,最好先把内容库准备好。Tanzu Kubernetes Grid Service 创建 TKC 时,要从内容库中读取 Kubernetes OVA 模板文件。如果没有内容库,你会发现创建流程里根本没有可选的 Kubernetes 版本。
内容库的创建路径是 vCenter 首页 -> Content Library -> Create。可以选择“本地内容库”或“订阅内容库”。如果你能访问外部网络,可以用 VMware 提供的订阅 URL 让 vCenter 自动同步;网络受限时,就手动下载 OVA 文件后上传到本地内容库。OVA 文件较大,上传时间取决于网络,最好放在空闲时段做。
内容库建好之后,确认里面已经存在一个可用的 TKG OVA,再开始激活 Workload Management。我有一个建议,上传完成后做一次“检查更新”或者重新导入一次,确保模板元数据完整,否则后面创建集群时会报“模板不存在”。
3. 一步一步激活 Workload Management 并创建首个集群
3.1 在 vCenter UI 上启用工作负载管理
激活入口在 vCenter 首页的“Workload Management”标签页。点击“开始使用”,系统会引导你走一个向导。
第一步是选择运行 Supervisor Cluster 的 vCenter Server 以及承载它的 vSphere 集群。这里只能选已经开启了 DRS 的集群,如果列表里没有可选项,检查一下 DRS 状态。
第二步是配置 Supervisor 网络。你需要提供:
- 管理网络 DNS 服务器地址
- NTP 服务器地址
- 管理网络的网关地址
- 可用的 IP 起始地址和地址范围(用于给 Supervisor 控制平面 VM 分配 IP)
第三步是配置工作负载网络。vDS 方案下,选择一个已经建好的端口组,然后指定调度网络的 VLAN 和网段。这里要特别注意,工作负载网络的起始 IP 段不要和管理网络重合,否则后续会给容器网络规则带来麻烦。
第四步是配置存储策略。选择第二步中提到的 vSAN 策略或者手动创建的 VM 存储策略,这一步直接决定了 TKC 的持久化能力。
最后一步是核对所有配置并点击完成。从这一刻起,vCenter 会开始在后台创建 Supervisor Cluster 的各个组件,包括 scgw(Supervisor Cluster Gateway)、dnsmasq、etcd、HAProxy 等,同时会在选定的分布式交换机上创建逻辑网络。这个过程耗时不短,我见过最快 30 分钟,慢的时候要一个多小时。期间不要轻易中断任务,也不要去修改网络配置。
等状态变成“已启用”,再回到 Workload Management 页面,就能看到 Supervisor Cluster 的基本信息显示出来。
3.2 创建命名空间并规划资源配额
Supervisor Cluster 启用后,下一步是创建 Namespace。这里的 Namespace 和 Kubernetes 里的 Namespace 概念类似,但功能更重:它是资源配额、权限边界、存储容量和网络策略的集合体。
在 Workload Management 界面选择“命名空间”,点击“创建命名空间”。输入名称(比如 dev-namespace),然后给这个命名空间分配:
- CPU 资源上限,比如 16 GHz
- 内存上限,比如 32 GB
- 存储容量,比如 200 GB
- 允许使用的 VM 存储策略
接着绑定权限,把需要操作这个命名空间的用户或用户组加进来,并分配 Owner、Edit、View 等角色。注意,这里的权限不仅影响 UI 操作,也影响 kubectl 登录时能看到的资源范围。
命名空间的资源配额有一个非常关键的细节:后续创建的 TKC 集群节点所需的资源,全都从这个配额里扣除。比如配额设置成 16GHz CPU、32GB 内存,而 TKC 一个 worker 节点的实例类型是 2 vCPU、8GB 内存,那么最多只能创建四个 worker 节点。很多人的集群创建卡在“Pending”,都是因为配额不够了。建议给命名空间预留额外 30% 的资源,作为弹性扩容的余地。
3.3 创建 Tanzu Kubernetes Cluster 的完整流程
命名空间准备好后,进入该命名空间的详情页,找到“Kubernetes 集群”服务,点击“创建”。
创建向导要填写:
- 集群名称:比如 app-cluster-01
- Kubernetes 版本:下拉列表会列出内容库中已有的 TKG OVA 对应的版本,这里会自动带出版本号
- 控制平面节点数:生产建议 3,测试 1 就够
- 工作节点数量:按需填写,测试环境 2 个节点足够
- 实例类型:选择节点 VM 的规格,有 2 vCPU / 8GB、4 vCPU / 16GB、8 vCPU / 32GB 等选项
- 存储类:选择命名空间可用的存储策略
点击创建后,vCenter 会进入一个较长的任务过程。控制平面 VM 会先被创建出来,等它完全启动并初始化之后,再批量创建 worker 节点。整个过程中你能在 vCenter 的“主机和集群”视图里看到一台台名称为“tkc-node”的虚拟机不断上线。这个过程通常需要 10 到 20 分钟,取决于模板大小和主机磁盘 IO。
集群状态显示为“运行中”之后,你其实已经拥有了一个独立的 Kubernetes 集群。这时就可以回到终端,准备用 kubectl 去操作它了。
4. 连上集群,把第一个应用跑起来
4.1 kubeconfig 获取方式对比
拿到 TKC 的 kubeconfig 有两条路。
一条是直接从 vCenter UI 下载。进入命名空间详情页,找到刚创建的 TKC,有一个“下载 kubeconfig”的按钮,点击后下载的是一个配置文件,直接kubectl --kubeconfig=kubeconfig.yaml get nodes就能用。这个方式最简单,但没法体验 vSphere 插件登录的上下文切换。
另一条是安装 vSphere Kubectl 插件,用kubectl vsphere login登录。这是更接近日常操作的方式。插件登录后,kubeconfig 会被写入本地,然后通过kubectl config use-context切换到不同集群。需要注意的是,插件的版本最好和 vCenter 版本保持一致,否则可能报 server 版本不匹配。
我个人推荐第二种方式,因为当你管理多个 TKC 时,上下文切换比反复下载文件方便得多。
4.2 部署一个无状态应用
连上 TKC 后,先确认节点状态:
kubectl get nodes正常情况下,控制平面和 worker 节点都会是 Ready 状态。如果节点还是 NotReady,说明 worker 节点的 kubelet 或网络组件初始化有问题,别急着部署应用,先完成后面的排查。
然后创建第一个 Deployment 和 Service:
kubectl create deployment nginx --image=nginx:1.25 kubectl expose deployment nginx --port=80 --type=NodePort kubectl get pods -o wide kubectl get svc因为我用的是 vDS 网络方案,LoadBalancer 类型的 Service 受限于网络能力,所以我选了 NodePort 做验证。等到 Pod 状态变成 Running,查看 Service 的 NodePort 端口,然后用任意 worker 节点的 IP 加端口去访问。这一步跑通,说明从 vSphere 资源池到 Kubernetes 网络链路是正常的。
如果你用了 NSX-T 方案,可以直接用 LoadBalancer 类型,vSphere 会自动创建负载均衡器并分配外部 IP,体验更接近公有云。
4.3 在 vCenter 里观察 Kubernetes 的虚拟化视角
一个很直观的感受是,你在 vCenter UI 里能看到 Kubernetes 产生的动态变化。比如扩展 Deployment 副本数时:
kubectl scale deployment nginx --replicas=5vCenter 的“主机和集群”视图中会立刻出现新的节点 VM 或新的 Pod VM(如果用 vSphere Pod Service)。这种虚拟化层和容器层联动的方式,是纯裸金属 K8s 完全没有的体验。维护人员可以在一张拓扑图上看到虚拟机和容器的实时状态,排障起来少切好几个界面。
5. 踩坑笔记:从部署到运行的七个高频问题
5.1 Workload Management 激活失败,卡在初始化阶段
这个问题是我第一次尝试时遇到的,报错信息指向 DNS 解析异常。排查后发现,原因是 vCenter 和 ESXi 主机的 NTP 时间不同步,导致 Supervisor Cluster 内部组件之间的 TLS 握手失败,进而影响 DNS 服务初始化。
排查思路:
- 在各台 ESXi 上执行
ntpq -p确认 NTP 同步状态 - 确认 vCenter 的时间源和主机时间源一致
- 检查 vCenter 的 DNS 配置是否能解析自身的 FQDN
修复时间同步后,需要把 Workload Management 的状态重置,重新激活。这里有个经验:激活失败不要反复重试,先把底层时间、DNS、网络这三件事全部检查一遍再动手,不然每次都卡在同一个地方。
5.2 内容库导入 TKG OVA 时长时间卡住不动
TKG OVA 文件动辄几十 GB,上传慢很正常,但如果几个小时没进度,就要检查是不是网络问题。我遇到过一次,是因为内容库所在的 Datastore 空间不够了,上传任务虽然显示在跑,实际上一直在等待空间释放。
处理方式:给内容库换一个空间充足的 Datastore,或者上传前先确认磁盘剩余量。内容库的位置可以在创建时指定,也可以在创建后重新配置。
另外,别用“订阅内容库”搭配一个无法稳定访问的外部地址,否则下一次同步会把现有模板状态弄坏。测试环境建议直接用“本地内容库”。
5.3 kubectl vsphere login 反复失败
报错一般是 “server version is not supported” 或者 “failed to authenticate”。前者基本上是因为 kubectl 插件版本跟 vCenter 版本差太多。插件更新到和 vCenter 同版本后问题就消失了。
后者需要检查用户名是否带了正确的域名前缀。vSphere 的 SSO 账号登录时,用户名格式通常是user@vsphere.local,省略后缀很容易认证失败。
5.4 TKC 一直处于 Provisioning 状态
创建 TKC 时,界面上一开始会显示“Provisioning”,正常情况下十几分钟后变“运行中”。如果长时间停在 Provisioning,原因大概率出在资源配额或存储策略。
先去命名空间的“配额”页面看 CPU、内存、存储的已用和剩余量。如果配额已经接近上限,创建计划中的节点数必然会失败。再看是否有可用的存储类,TKC 创建时如果没有可匹配的存储策略,worker 节点的磁盘根本无法分配。
我遇到的一次就是因为给命名空间分配的内存配额只有 16GB,但 TKC 的控制节点规格默认需要 4GB,worker 每次创建两个 8GB 的节点,直接把配额吃满了。把内存配额加到 32GB 之后,再重新创建就正常了。
5.5 能创建集群,但 Pod 调度不到节点上
集群正常运行,kubectl get nodes也能看到节点,但部署 Pod 时一直 Pending。这种情况通常是节点有污点(Taint)或者节点上的 kubelet 网络插件没就绪。
用下面的命令查看节点详情:
kubectl describe node <node-name>重点关注节点的 Taints 和 Conditions。如果节点处于 NotReady 状态,大概率是 kubelet 没办法注册到集群,而 kubelet 起不来通常是 VM 的网络初始化有问题。在 vCenter 里打开对应节点的虚拟机控制台,查看 kubelet 服务状态。如果发现 kubelet 循环重启,尝试重启整个 TKC 集群中的该节点虚拟机。
5.6 Service 通过 NodePort 无法访问
这个问题在 vDS 网络方案下比较容易出现。排查要先确认 Pod 已经 Ready,Service 的 Endpoints 中能看到 Pod IP。如果 Endpoints 为空,说明 Service 的选择器和 Pod 的 Label 不匹配。
kubectl describe svc nginx kubectl get endpoints nginx另外,vDS 方案下 NodePort 端口在宿主机侧可能被防火墙阻断,建议先确认 ESXi 主机的防火墙规则允许对应端口。如果是 LoadBalancer 类型,vDS 方案下约等于不可用,这种情况改成 NodePort 是最快的绕行方案。
5.7 容量充足但创建集群仍然提示资源不足
明明三台主机都有剩余,命名空间配额也设得很大,创建第二个 TKC 时还是提示资源不足。这通常是因为 Supervisor Cluster 在创建 TKC 时会检查主机级别的碎片资源,也就是单台主机的可用内存或 CPU 不足以承载一台节点 VM 的完整调度。
解决办法:保证至少有一台 ESXi 主机的空闲内存和 CPU 都能容纳单节点 VM 的规格。如果碎片化严重,可以先把主机置于维护模式再退出,触发 DRS 重新平衡资源,或者减少一个节点规格再试。
6. 这套方案到底适合谁:场景与个人体会
6.1 适合的建议场景
如果你所在团队的现状是:已经有一套稳定的 vSphere,运维团队对虚拟化非常熟悉,但对容器编排还不够熟练,同时开发团队希望快速获得 Kubernetes 环境,那么 vSphere 7 with Kubernetes 就很适合你。它让运维可以继续用 vCenter 干活,开发能用真正的 K8s API,底层资源统一管理,扩容缩容都在同一套界面里完成。
如果是初创团队从零开始,或者团队已经具备很强的云原生能力,那直接选择裸金属集群或公有云 Kubernetes 服务往往更省事。vSphere 7 with Kubernetes 的价值更多体现在“存量虚拟化环境平滑演进”,而不是“新建系统最简方案”。
6.2 我的使用体会
我在实际使用中能明显感觉到,这套平台不是把 K8s 变简单了,而是把 K8s 变得可控。对管理员来说,每个 TKC 集群本质上还是一批 VM,出了问题可以像处理虚拟机一样处理,这比对着黑乎乎的节点 SSH 从容很多。对开发者来说,kubectl 的使用方式和标准 K8s 几乎没有差别,不需要学习新的 API。
还有一点比较有用的经验:创建 TKC 时要提前想好规格。由于节点 VM 一旦创建,实例类型就不能随意修改,如果后续要给集群加更多用量的 Pod,你只能横向加节点,而不是把已有节点改大。所以在选择实例类型时,宁可稍微偏大,也别为了省资源选择最小规格。
最后分享一个小技巧:如果你只是做功能验证,别一上来就配置完整的 NSX-T。先用 vDS 方案把 Supervisor Cluster 拉起来,跑通 TKC 创建和 kubectl 操作,理解整体流程之后,再考虑生产环境要不要引入 NSX-T。对大多数人来说,vDS 方案下的体验已经足够了解整套平台的能力边界了。