跳到正文
Kubernetes、GitOps 与平台演进:从调度能力到可治理的生产系统
Kubernetes、GitOps 与平台演进:从调度能力到可治理的生产系统

Kubernetes、GitOps 与平台演进:从调度能力到可治理的生产系统

从 Google Borg/SRE、Netflix Kayenta、Spotify Backstage 和 CNCF 开源生态出发,分析 Kubernetes 的适用条件、生产边界、GitOps、渐进式发布与 Compose 迁移路线。

Kubernetes 解决的是一组分布式系统和平台治理问题,不是“比 Docker Compose 更专业”的部署界面。本文不提供一份可以直接复制的集群安装脚本,而是说明它何时值得引入、哪些问题仍然留给团队,以及成熟公司的公开实践如何缩小为可操作的原则。

一、先判断是否真的需要 Kubernetes#

服务数量不是可靠阈值。十个稳定服务可能用 Compose 管理得很好,三个关键服务也可能因多团队、强隔离、频繁发布和弹性要求而需要统一平台。

真正的触发条件通常同时出现:

  • 工作负载需要根据资源和约束自动放置到不同节点。
  • 节点故障后需要自动重建副本,而不是等待人工登录。
  • 多团队需要 Namespace、RBAC、Quota、NetworkPolicy 和统一入口。
  • 发布频繁,需要标准化滚动、Canary、审批和审计。
  • 服务发现、配置、证书和可观测性已经重复建设。
  • 团队能够持续承担集群升级、网络、存储、策略和事故响应。

如果当前主要问题是没有备份、镜像不可追踪、探针随便写、数据库放在容器本地,迁移 Kubernetes 只会把这些问题变成更多 YAML。

先有:不可变镜像 + 状态外置 + 健康语义 + 资源画像 + 回滚演练
再评估:调度 + 多租户 + 弹性 + 统一平台是否值得长期成本

二、从 Borg 借设计思想,不复制 Google 的规模#

Google 公开的 Borg 论文描述了大规模集群管理中的作业提交、资源调度、故障处理和统一控制面。Kubernetes 继承了许多相似思想:用户提交期望状态,控制器不断比较期望与实际,调度器为 Pod 选择节点。

声明式对象
API Server(状态入口)
Controller(持续协调)
Scheduler(选择节点)
kubelet / container runtime(执行)

这里最重要的不是“大规模”,而是 reconciliation。一次 kubectl apply 成功只说明 API 接受了对象;系统能否持续把故障后的实际状态拉回期望状态,才是控制面的核心价值。

但 Kubernetes 不理解业务正确性。它可以发现 Pod 数量不足,却不知道一次扣款是否重复、缓存数据是否过期、数据库副本是否已经失去一致性。这些仍然需要应用协议、指标和人工运行手册。

三、先理解四个生产平面#

1. 控制平面#

API Server、etcd、scheduler 和 controller manager 保存并协调集群状态。控制平面故障时,已有 Pod 可能继续运行,但扩缩容、重建、发布和配置变更会受影响。

需要明确:

  • etcd 的成员、仲裁和备份恢复。
  • API Server 的可用入口与证书轮换。
  • 版本升级顺序和支持跨度。
  • 谁拥有 cluster-admin,怎样审计紧急访问。
  • 控制面不可用时,业务和运维分别能坚持多久。

2. 数据平面#

工作节点上的 kubelet、容器运行时、CNI、kube-proxy 或 eBPF 数据路径实际承载业务。Pod 重建会改变 IP,Service 和入口组件负责提供稳定寻址。

节点 Ready 不代表其上的每条网络路径、磁盘和 DNS 都正常。生产监控应覆盖节点、Pod、Service、Ingress/Gateway 和关键依赖的端到端路径。

3. 交付平面#

CI 构建和验证制品,GitOps 控制器或发布系统把已批准版本推进环境。不要让每个开发者的本地 kubectl 成为生产状态的唯一来源。

4. 可观测与安全平面#

指标、日志、Trace、审计、策略和密钥贯穿所有 Namespace。它们不应该在上线最后一周才补,因为发布回滚、容量判断和入侵调查都依赖这些证据。

四、一个 Deployment 背后的真实语义#

一个看似普通的 Deployment 至少表达镜像身份、资源、探针、安全上下文和终止行为:

apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout
spec:
replicas: 3
strategy:
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: checkout
template:
metadata:
labels:
app: checkout
spec:
terminationGracePeriodSeconds: 30
containers:
- name: app
image: ghcr.io/example/checkout@sha256:...
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
memory: 512Mi
readinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 15
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 5
failureThreshold: 24
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop: ["ALL"]

这不是万能模板。CPU limit 是否合适、应用是否支持只读根目录、启动时长和优雅终止时间都要用真实行为验证。

三种探针不要互相替代#

  • Startup probe:慢启动是否已经完成;通过前抑制 liveness/readiness 的干扰。
  • Readiness probe:此实例现在是否应该接收流量。
  • Liveness probe:进程是否进入只能通过重启恢复的状态。

把数据库短暂不可用直接写入 liveness,可能让所有 Pod 同时重启,扩大一次依赖抖动。把业务依赖完全排除在 readiness 外,又可能让无法服务的实例持续接流量。探针必须对应恢复动作:摘流量能解决什么,重启又能解决什么。

Requests 与 Limits 是调度合同#

Scheduler 主要依据 requests 放置 Pod。请求过低会导致节点过度承诺,过高会造成资源浪费和调度失败。内存 limit 超限通常触发 OOM,CPU limit 则可能产生 throttling;两者不能只靠“公司统一模板”填写。

Vertical Pod Autoscaler 的建议、历史分位数和压测可以帮助校准。Horizontal Pod Autoscaler 也需要与启动时间、下游容量和指标延迟共同设计,不能只看 CPU 百分比。

五、可用性不是副本数等于三#

三个副本可能被调度到同一节点、同一可用区,甚至共同依赖一个数据库。提高应用层可用性至少要处理:

  • topology spread constraints 或 pod anti-affinity。
  • 多可用区节点与入口流量。
  • PodDisruptionBudget(PDB)。
  • readiness 与连接排空。
  • 滚动更新的 surge/unavailable 参数。
  • 下游数据库、缓存和消息系统的共同故障。

PDB 只约束部分自愿中断,例如节点维护,并不阻止节点宕机,也不会为单副本应用创造高可用。minAvailable: 3 还可能让三副本工作负载无法正常排空节点。可用性配置必须与维护过程一起演练。

六、有状态系统:PVC 不是备份,Operator 也不是责任转移#

StatefulSet 提供稳定身份和有序管理,PVC 提供持久卷声明;它们不会自动完成数据库的一致复制、时间点恢复、跨区域灾备和 schema 升级。

在 Kubernetes 中运行数据库前,应回答:

  • 存储类的故障域、快照一致性和恢复时间是什么?
  • Pod 被调度到新节点时,卷能否及时重新挂载?
  • 数据库如何选主,如何防止旧主继续写入?
  • 备份是数据库一致备份,还是仅有磁盘快照?
  • Operator 升级与数据库版本升级如何回退?
  • 集群整体故障时,恢复工具是否也依赖该集群?

成熟 Operator 可以自动化重复步骤,但团队仍需理解它的状态机和失败路径。小团队首次上 Kubernetes 时,优先使用托管数据库或独立维护的数据平台,通常能缩小故障半径。

七、GitOps:Git 保存期望状态,控制器负责协调#

GitOps 的基本闭环是:

Pull Request
↓ 审查期望状态
Git Repository
↓ 拉取并比较
Argo CD / Flux
↓ apply / health / drift
Kubernetes Cluster
状态与事件回到可观测系统

OpenGitOps 将核心原则概括为声明式、版本化且不可变、自动拉取和持续协调。成熟实现通常还会区分:

  • 应用源码仓库:测试并生成不可变镜像。
  • 环境配置仓库:记录每个环境批准的镜像 digest 与配置。
  • 控制器身份:只拥有目标 Namespace 或资源所需权限。
  • Promote:把已验证制品从预发布推进生产,不重新构建。

GitOps 不自动等于安全#

  • Git 历史会长期保留误提交的 Secret。
  • Kubernetes Secret 默认只是 base64 表达,不是静态加密保证。
  • 控制器通常拥有高权限,其仓库和凭据是关键攻击面。
  • 自动同步可能迅速放大错误变更。
  • 自动修复 drift 可能覆盖事故中的临时处置。

可选方案包括 SOPS + age、External Secrets Operator、Vault 或云密钥服务。选择标准是明文在哪里出现、谁能解密、怎样轮换、集群丢失后怎样恢复,而不是项目 Star 数量。

Argo CD 与 Flux 的取舍#

两者都能持续协调 Kubernetes 期望状态。Argo CD 提供以应用为中心的 UI、健康和同步模型;Flux 更强调可组合的控制器工具箱。没有必要因为使用 Helm 或 Kustomize 就预先站队,两者都支持常见清单工作流。

先用一个非关键应用验证:漂移、失败同步、依赖顺序、回滚、密钥和灾难恢复。维护两套 GitOps 控制器通常不会增加可靠性,只会增加两套状态机。

八、渐进式发布:Deployment 不是自动业务回滚#

原生 rolling update 能控制新旧 Pod 的数量,但不能根据错误率和业务指标自动判断版本好坏。成熟的渐进式发布需要:

  1. 将少量真实流量导向新版本。
  2. 同时保留稳定版本作为基线。
  3. 在固定观察窗口比较错误率、延迟和业务指标。
  4. 达到阈值后扩大流量,否则暂停或回滚。
  5. 保存判定输入与结果,供复盘。

Argo Rollouts 和 Flagger 可以配合服务网格或 Ingress 实现 Canary/Blue-Green;Prometheus 等系统提供分析指标。引入前先确认普通滚动发布已经有正确探针和可回滚数据库变更,否则高级控制器只是在自动化不可靠的基础。

九、三个海外成熟案例,真正值得迁移的部分#

Google:Borg 与 SRE#

Borg 展示了统一调度、资源管理和控制循环;Google SRE 则提供 SLI、SLO、Error Budget、Toil 和无责复盘等运行方法。两者结合说明:平台能力与可靠性治理缺一不可。

小团队不需要复制 Google 的集群规模,但可以做到:为用户路径定义 SLI,用 SLO 决定是否继续发布,把重复人工操作记为 Toil,并用 Error Budget 避免“永不发布”或“无视可靠性”两个极端。

Netflix:Spinnaker 与 Kayenta#

Netflix 开源的 Spinnaker 和与 Google 合作的 Kayenta 展示了多阶段交付和自动 Canary 分析。最可迁移的原则是把“构建制品”和“推广制品”分开,并让业务指标参与发布决策。

这并不意味着小团队需要同时安装 Spinnaker、Kayenta、Argo CD 和 Argo Rollouts。一个发布控制器、一套可靠指标和清晰的停止条件通常已经足够。

Spotify:Backstage 与 Golden Path#

Spotify 创建并开源 Backstage,解决的是服务目录、所有权、模板和开发者入口。它反映了平台工程的一个成熟方向:平台团队维护公共能力,业务团队通过受支持的 Golden Path 创建和运行服务。

但 Backstage 本身不会自动建立平台。服务所有者不准确、模板无法持续升级、目录只做链接收藏时,门户会成为另一层维护负担。先统一服务元数据、CI 模板和运行标准,再引入开发者门户,顺序更稳妥。

十、托管 Kubernetes 与三 VPS k3s#

托管 Kubernetes#

EKS、GKE、AKS 等通常托管部分控制面,并集成云负载均衡、身份和存储。团队仍负责:

  • 工作节点或无服务器计算配置。
  • 应用、RBAC、NetworkPolicy 和密钥。
  • CNI、Ingress/Gateway、DNS 和存储的实际行为。
  • 版本兼容、成本、备份与事故响应。

“控制面托管”不是“集群免运维”,但通常比小团队自己维护 etcd 和 API Server 更容易建立明确责任边界。

三 VPS k3s#

三台 VPS 可以运行高可用 k3s server,但生产可用性受更广泛条件限制:

  • 三节点间网络延迟与稳定性是否适合 etcd 仲裁。
  • VPS 是否位于真正独立的故障域。
  • 外部负载均衡器如何访问 API Server。
  • 节点维护时是否还能保持多数派和业务容量。
  • 持久卷如何在节点故障后恢复。
  • etcd snapshot 是否复制到集群之外并演练恢复。

三节点只是控制面仲裁的起点,不是数据层、入口和应用自动获得生产级高可用的证明。

十一、从 Compose 迁移的最小风险路线#

阶段 0:先在原平台修正应用#

  • 镜像使用 digest,构建一次多环境推广。
  • 配置外置,Secret 不进入镜像。
  • 应用无状态,上传和数据库独立。
  • 探针、优雅终止和资源消耗已经测量。
  • 数据库迁移向前兼容并可回滚应用。

阶段 1:迁移一个非关键无状态服务#

只引入 Deployment、Service、Ingress/Gateway、ConfigMap/Secret 和基础监控。验证 Pod 重建、节点排空、发布失败和日志定位。

阶段 2:建立生产基线#

补齐 Namespace、RBAC、NetworkPolicy、Quota、PDB、拓扑分散、备份、审计和升级运行手册。让所有基线通过代码审查,而不是手工点击。

阶段 3:GitOps 与渐进式发布#

先用 Argo CD 或 Flux 管理期望状态,再按真实发布风险引入 Argo Rollouts 或 Flagger。不要在同一次迁移中同时更换编排、网络、数据库和交付系统。

阶段 4:平台产品化#

只有当多个团队反复创建服务、复制模板并寻找所有者时,才值得引入 Backstage 或自建门户。Golden Path 必须允许受控逃生路径,否则平台会阻挡确实不同的工作负载。

十二、生产故障演练#

至少定期验证:

  • 删除一个 Pod,观察 Service、探针和请求是否正常恢复。
  • drain 一个节点,确认 PDB、容量和优雅终止行为。
  • 阻断一个可用区或模拟节点网络故障,检查拓扑分散。
  • 提交错误镜像和错误配置,确认 GitOps/发布流程如何停止。
  • 让关键 Secret 轮换,确认应用无长时间中断且旧凭据失效。
  • 恢复 etcd 和业务数据到隔离环境,记录 RPO/RTO。
  • 暂停 GitOps 控制器,确认业务继续运行以及如何恢复协调。

Chaos 工具不是前提。先有清晰假设、观察信号、停止条件和恢复步骤,再决定是否使用 LitmusChaos、Chaos Mesh 等项目自动化。

十三、成熟开源组合:按问题选择,不按清单安装#

问题可选项目
轻量发行版与运行时k3s、containerd
网络与策略Cilium、Calico、Envoy Gateway
清单与包管理Kustomize、Helm
GitOpsArgo CD、Flux
渐进式发布Argo Rollouts、Flagger
证书与密钥cert-manager、External Secrets Operator、SOPS、Vault
指标与追踪Prometheus、Grafana、OpenTelemetry、Tempo/Jaeger
策略Kyverno、OPA Gatekeeper
供应链Trivy、Syft、Cosign、SLSA
数据库自动化CloudNativePG、Crunchy Postgres Operator、Percona Operators

一个产品在 CNCF Landscape 出现或进入毕业阶段,只能说明项目治理和采用情况,不能证明它适合当前团队。每多一个控制器,都要知道它 watch 哪些对象、拥有什么权限、升级失败时如何恢复。

十四、最终决策清单#

  • Kubernetes 要解决的现有问题已经量化,而不是预期未来会有规模。
  • 团队有明确的集群所有者、值班责任和升级预算。
  • 镜像、配置、探针、资源和数据迁移在迁移前已规范。
  • 控制面、节点、网络、入口、DNS 和存储都有故障模型。
  • 应用副本跨真实故障域分散,并验证过节点排空。
  • GitOps 仓库、控制器权限和 Secret 解密边界清楚。
  • 发布根据业务指标停止,而不只看 Pod Ready。
  • PVC、数据库副本和备份没有被混为一谈。
  • etcd 与业务数据均可在集群之外恢复。
  • 引入的每个控制器都有所有者、监控和移除路径。

参考资料#

版权许可

CC BY-NC-SA 4.0 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

s1oopX

登录 s1oopX