技术文章2026 年 6 月 12 日约 6.1 分钟

华为云容器引擎 CCE:Kubernetes 生产集群搭建与运维

托管 K8s 把控制平面变成"别人的服务",代价是把看得见的复杂度换成了看不见的耦合。这篇的重点是分清:哪些故障你还能自己查,哪些只能等。

从自建 K8s 换到托管集群,第一周的感觉通常是"轻松":装集群、修 etcd、换证书这些活全没了。第二周开始会冒出一个新的不安——kubectl 还能用,但你不太确定它在跟谁说话,出了事也不知道能查到哪一层。

这个不安是对的。托管没有消灭复杂度,它做的是把复杂度从一个地方挪到另一个地方:把"看得见的运维负担"换成了"看不见的耦合边界"。这篇想讲清楚这条边界在哪。

#一、托管的分界线

托管的准确含义不是"K8s 由厂商运维",而是:

层次自建集群托管集群(CCE 这类)
控制平面(apiserver/etcd/scheduler)你装、你修、你能看日志厂商维护;你能看指标,通常看不到主机
数据面节点你装 kubelet、你修你管节点池,节点上的问题你能进
网络插件你选、你调通常平台集成,可调项是子集
版本生命周期你自己决定由平台的受支持版本决定
故障时能查的深度全栈到控制平面入口为止

看最后一行:这是托管最本质的代价。你能查的东西变少了,而且减少的部分恰好是最难自建的那部分。

这不是说托管不好——对绝大多数团队来说,自己维护 etcd 的风险远大于"少看到一层日志"的不便。但要接受它,并且在架构上为"查不到"留出余量(例如:客户端侧要有足够的可观测性,不能把全部诊断希望寄托在 apiserver 日志上)。

#二、节点池:把机器变成可丢弃的单位

节点池是托管集群里最重要的一个抽象。它的价值不在"批量管理",而在于它把节点从"资产"变成了"规格"。

用起来的关键是:按负载特征分池,而不是按机器型号分池。

池的划分依据例子好处
工作负载类型通用 / GPU / 内存密集调度约束清晰,扩缩容互不干扰
稳定性等级在线服务 / 批处理 / 抢占式故障与回收的影响面被隔离
生命周期长期 / 临时升级时可以整池替换

第三行值得单独说:"整池替换"是滚动升级真正能落地的前提。 如果一个池里混着不同年代、不同配置的节点,升级就变成了逐个(且各不相同)的维护动作;如果池是同类节点,升级可以做成"新池建好、流量切过去、旧池销毁"——从"修机器"变成"换机器"。

这也是云上最该被用起来的特性:把机器当成可以随时丢弃的东西,前提是任何一台机器上都没有不可重建的状态。

#三、可用性预算:你允许自己同时弄坏几台

K8s 里有一组机制专门用来表达"现在可以坏几台",理解它们之间的关系比记住名字有用:

机制表达什么用错时会发生什么
副本数需要几个实例单副本服务在节点维护时直接中断
反亲和/拓扑分布这些实例别挤在一起三副本全在一台机器上
PodDisruptionBudget (PDB)自愿中断时最多坏几个配得太严,节点永远驱逐不干净
就绪探针什么时候算能接流量探针太松,把坏实例也接进流量

第二行和第三行是一对:反亲和解决"物理上会不会一起坏",PDB 解决"运维动作会不会一次坏太多"。 两者缺一,高可用就是靠运气。

PDB 最容易配错的方向是"太严":

yaml
# 三副本、PDB 要求至少 2 个可用 → 一次只能坏 1 个
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
spec:
  minAvailable: 2
  selector:
    matchLabels: { app: web }

看起来保守,实际会出现一个很具体的现象:节点排空(drain)卡住不动,因为驱逐会被 PDB 拦住。这时候人容易做两件事——加大 --timeout(没用),或者直接把 PDB 删掉(危险)。正确的做法是理解"排空是自愿中断",然后按业务窗口安排它。

#四、托管集群的网络,边界在哪

网络是托管集群里最容易出现"我觉得是这样"的地方。三条常见边界:

  1. Pod 网段与节点网段的关系:不同网络模式(overlay 与 underlay 思路)决定了 Pod IP 能不能被集群外直接访问、SNAT 发生在哪里。这直接决定你排查"包到底有没有到"的路径。
  2. 服务端负载均衡的实现:LoadBalancer 类型的 Service 背后是厂商的负载均衡实例,这个实例有它自己的健康检查与会话保持策略——两个健康检查不一致,会出现"K8s 认为健康、LB 认为不健康"的经典错配。
  3. 网络策略的默认行为:NetworkPolicy 是白名单式的,未匹配的流量默认怎么走,各实现略有差异(有的默认允许,有的默认拒绝),上线前必须验证一次,而不是按理解假设。

第二条特别值得记住:任何"两层健康检查"的系统,错配是迟早的事。 排查时先确认"谁在判死",再去看被判定的一方。

#五、能自己查的 与 只能等的

这是这篇最实用的一节。把故障分一下类,心里会踏实很多:

现象你能不能自己往下查
Pod 起不来、反复重启能。kubectl describe、容器日志、事件
节点 NotReady部分能。节点本身能进,kubelet 日志能看到一部分
Service 访问不通能查到网络策略与端点,但云负载均衡那一层可能看不到
apiserver 报 5xx / 限流基本只能等。能看到的是客户端侧的错误率与延迟
调度不上去能。看事件里的调度失败原因,通常是资源或污点
存储挂载失败部分能。CSI 侧日志可见性取决于平台

最后一列那两条,正确的应对方式不是"想办法看到",而是在设计阶段就不依赖它:

  • 给 apiserver 的调用方(controller、operator、CI)加退避与降级。
  • 关键路径不要每次都实时查询 apiserver(比如用缓存/影子配置),避免把控制平面当成数据面用。

#六、成本:节点池的浪费长什么样

托管集群的账单浪费通常不是"节点太大",而是三种结构性的:

  1. 池的碎片:多个小池,每个都有闲置余量。池越多,余量被重复预留的次数越多。
  2. requests 与 limit 的差距:调度按 requests,实际用 limit 附近的量很少。requests 虚高是云上最普遍的隐性浪费。
  3. 缩容不下来的负载:没有用 HPA,或者用了但伸缩指标选错了(例如按 CPU 伸缩一个 IO 密集的服务,永远不触发)。

第一条和第三条都能靠"先把池合并、再按负载分池"解决;第二条需要的是基于实际用量的 requests 校准,而不是一次调完就完事——它需要一个定期校准的机制。

#七、这篇没写什么

  • 没写集群创建的具体步骤与控制台参数。 界面与选项随版本变化,请以官方文档为准。
  • 没写 CSI/CNI 各实现的对比。 差异大且演进快,结论很容易过期。
  • 没写 Service Mesh 与 Ingress 细节。 那是构建在集群之上的另一层,独立成篇更清楚。
  • 没给集群规模数字。 "多大的集群该用托管"取决于团队的自维护能力,不是节点数。

一句话收束:托管把控制平面变成了服务,代价是你的诊断能力在某个深度上被截断。承认这条边界、并围绕它设计客户端侧的可观测性,比假装它不存在要安全得多。

写于 2026 年 6 月 12 日

栏目
技术文章
约
6.1 分钟
字数
3.1K
阅读
1

本文为原创记录,转载请注明出处。如果这篇替你省了时间,欢迎留言说说你踩到的坑。

同题 · related

留言 · remarks

00 条

还没有留言,来说点什么吧。

华为云容器引擎 CCE:Kubernetes 生产集群搭建与运维 · LXH·BLOG