跳转到内容

TKE 集群控制面升级最佳实践

Kubernetes 活跃的社区和广大的用户群,使 Kubernetes 社区迭代速度快,每季度发布新版本,高频的版本发布带来了更多的新功能落地和性能优化,也包含 CVE 漏洞补丁和安全加固。TKE 包括业界云厂商仅维护支持最近 3-4 个次要版本,超期版本无法获得安全补丁和技术支持。集群升级是获取新功能与性能优化,抵御攻击、满足合规要求,避免版本碎片化风险,保证生态兼容性,避免技术债务累积的核心手段,也是 Kubernetes 持续运营(Continuous Operations)中版本管理的重要组成部分。忽视 Kubernetes 版本管理,会导致版本滞后,安全漏洞未修复、API 不兼容,无法使用新功能等问题,最终威胁业务连续性。

集群由控制面和节点组成,集群升级分为 控制面升级节点升级,为了确保集群平稳运行,控制面和节点都应运行相同的 Kubernetes 次要版本。控制面的版本由 Kubernetes API 服务器决定,节点版本由节点 kubelet 和容器运行时决定。

TKE 集群升级流程包括升级前准备、控制面升级、节点升级和升级后验证几个步骤,本文将着重介绍集群大版本所需工作,包含集群升级的风险、升级前准备和控制面升级中的相关流程。节点升级和升级后验证,会放到下一篇幅中。TKE 集群大版本升级仅支持双数版本升级(例如从 1.24 升级到 1.26),不支持跨多版本升级。

Kubernetes 的分层架构设计和组件化特性是其灵活性和扩展性的基础,但也正是这些设计特点为集群升级带来了特定的系统性风险。Kubernetes 是分层的,有控制平面、工作节点、API 层、网络存储层等,每个层都有不同的组件,比如 API Server、etcd、kubelet、CNI 插件等。组件化设计意味着各个组件可以独立升级,但也带来了兼容性问题。集群控制面升级的风险分为以下三个方面:

Kubernetes 通过 API 抽象资源管理,API 版本采用 GA/Beta/Alpha 分级制度,且每个大版本会清理已弃用超过 9 个月的 API(KEP-24 策略)。版本化 Schema 的强制校验会带来资源定义断裂的风险:

  • API 版本废弃(如 PodSecurityPolicy 在 1.25 被移除)
  • 资源定义规范变更(如 Ingress API 从 extensions/v1beta1networking.k8s.io/v1
  • 字段验证规则调整(如新增 required 字段)
  • 默认特性开关(Feature Gates)变更,也会影响已有功能

Master 组件的协同工作与版本约束,包含:

  • kube-apiserver 升级后与其他组件版本不匹配
  • etcd 存储格式变更导致数据兼容性问题(etcd 使用 Protobuf 序列化存储资源对象,不同 Kubernetes 版本可能修改 Protobuf 定义如字段重命名,导致出现数据反序列化失败)
  • 调度器/控制器行为变化(如默认调度策略调整)

Kubernetes 的版本兼容策略允许有限偏差(N±2),但第三方组件的兼容性矩阵往往更严格,组件兼容性需要人工维护矩阵,比如:

  • Helm Charts 未适配新版本 API(如旧版 Prometheus Operator)
  • 自研 Operator 未兼容新版 K8s 客户端库(client-go)

根据责任划分,TKE 需要解决的风险包括:保证 coredns、cbs 等系统组件适配新版本、提供废弃 API 的检查能力、保证控制面组件参数符合预期等。一些风险需要客户来解决,比如:游离 pod 的检查、客户自身组件的兼容性、使用第三方组件兼容性、业务适配默认行为变化和版本差异(比如 psp 等)等。

升级前准备包括仔细阅读 TKE Kubernetes 版本说明,了解 升级须知,确定集群升级时间,对集群进行升级前检查和备份。因为集群升级的风险性,这里着重介绍需要关注的升级前检查,通过升级前检查和对应处置手段,降低升级风险。

在 Kubernetes 中,ownerReferences 用于定义资源之间的依赖关系(如 Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod),其核心作用包括:

  • 垃圾回收:自动清理无用的子资源(如删除 Deployment 时自动删除关联的 ReplicaSet 和 Pod)
  • 级联操作:通过父对象触发子资源的创建、更新或删除
  • 状态同步:确保子资源的状态与父对象声明的一致性

错误的 ownerReferences 引用表现为:

  • 引用不存在的父资源(如错误的 UID 或名称)
  • 跨命名空间引用(例如父对象在 Namespace A,子对象在 Namespace B)
  • 引用错误的资源类型(如 Pod 直接引用 Deployment 而不是 ReplicaSet)
  • 使用已弃用的 API 版本(如 apps/v1beta1 升级到 apps/v1 后未更新)

如果存在错误的 ownerReferences 引用,升级后可能会导致以下问题:

  • 资源泄露:ownerReferences 中的父资源 UID 或类型错误,垃圾回收器无法识别关联关系。升级后 API 版本变更(如 extensions/v1beta1 弃用),旧版 ownerReferences 失效
  • 意外删除:删除父对象时,错误的 ownerReferences 导致级联删除到无关资源。删除操作卡死,升级后垃圾回收器逻辑变更,对无效引用更敏感(如严格校验 API 版本)
  • 控制器失效:父控制器(如 Deployment Controller)因 OwnerReferences 错误,无法关联到子资源(如 ReplicaSet)。升级后控制器逻辑变更,拒绝处理非预期的 OwnerReferences
  • 状态不一致:实际运行的资源与父对象声明不一致,错误的 OwnerReferences 导致控制器无法跟踪子资源,无法修复偏差

建议在集群升级前,使用 kubectl-check-ownerreferences 扫描集群中是否存在错误的 ownerreferences 引用。

3.1.2.1 安装 kubectl-check-ownerreferences
Section titled “3.1.2.1 安装 kubectl-check-ownerreferences”

官方页面 选择合适的版本下载(目前最新版本为 v0.4.0):

Terminal window
git clone https://github.com/kubernetes-sigs/kubectl-check-ownerreferences.git
cd kubectl-check-ownerreferences
make install
Terminal window
kubectl-check-ownerreferences

如果检查结果如下,则表明集群内没有异常 ownerReference 引用:

No invalid ownerReferences found

如果检查结果为其他,则表明对应的 ownerReference 引用异常,需要处理。

不同组件版本适配不同版本集群,集群升级对组件版本有要求。如果组件版本跟集群版本不适配,可能会导致组件功能受损或不可用。

TKE 目前在集群升级时,组件版本要求如下:

1.20 升级到 1.22:

组件最低版本
service-controller>= 1.8.0
l7-lb-controller>= 1.8.0
coredns>= 1.8.4
tke-eni-ipamd>= 3.4.2
tke-eni-agent>= 3.4.2
tke-eni-ip-scheduler>= 3.4.2
add-pod-eni-ip-limit-webhook>= 0.0.7
ingress-nginx 组件版本>= 1.0.0
ingress-nginx 实例版本>= 1.1.3

1.22 升级到 1.24:

组件最低版本
cbs>= 1.1.1

1.24 升级到 1.26:

组件最低版本
service-controller>= 1.8.0
l7-lb-controller>= 1.8.0
tke_log_agent>= 1.1.13
tke_event_collector>= 0.0.4
ingress-nginx 组件版本>= 1.3.0

在升级集群之前,要保证组件满足集群新版本要求,TKE 会对组件版本进行检查,若检查不通过则无法升级,您可按照要求升级组件版本。

组件版本中,coredns、service-controller、l7-lb-controller、nginx-ingress 组件、nginx-ingress 实例需要联系 TKE 进行后台升级,其他组件您可在组件管理下自助进行升级,升级前需要请参考 组件变更版本记录

!!! warning “注意” - TKE 组件自定义配置和参数,只能通过控制台修改,非控制台修改/设置的参数,升级将会覆盖 - TKE 组件升级无法回滚,如果升级出现问题,需第一时间联系 TKE 协助处理

随着 Kubernetes API 的演化,API 会周期性地被重组或升级,部分 API 会被弃用并被最终删除。以下为各 Kubernetes 社区版本中被废弃的 API,更多已废弃的 API 说明请参考:Kubernetes 弃用指南

废弃 API 不影响集群控制面升级的成功与否,但会影响集群升级后对应资源的操作。在集群升级后,当某 API 被废弃时,已经创建的资源对象不受影响,但新建或编辑该资源时将出现 API 版本被拦截的情况。

在升级前,可以通过 TKE 提供的升级前置检查能力,TKE 集群列表 -> 集群升级 -> 前置检查,检查即将被废弃的 API 是否仍在被使用(数据来源于自 Kubernetes v1.19 以来的指标:apiserver_requested_deprecated_apis),获取仍在被请求且即将废弃的 API 的列表。检查状态均为提示,TKE 已保证自身提供的服务均满足新版本集群 API 的要求,您需要对自身服务请求 API 使用的版本是否正确负责。

在获取到废弃 API 列表后,通过容器服务 -> 运维中心 -> 运维功能管理,找到请求对应集群,右侧操作下更多,点击集群审计检索,通过审计日志里的 useragentuser.username,找到请求废弃 GRV 的组件。

例如:搜索 1.25 要被废弃的 v1beta1 的 poddisruptionbudgets 示例:

requestURI:policy/v1beta1/poddisruptionbudgets

找到对应组件后,可参考社区或服务提供商要求更新,以满足新集群版本要求。TKE 提供的组件,均已通过测试和验证,当您满足 3.2 组件依赖检查时,可忽略废弃 API 检查中针对 TKE 组件的提示。

检查当前 HelmRelease 记录中是否含有目标集群版本不支持的废弃 API,如果存在,升级后 helm 模板会不可用,HelmRelease 资源无法被创建、更新或删除。

Kubent 全称 Kube No Trouble 是一个简单的工具,主要用于检查 k8s 集群中是否使用废弃的 API 版本,支持使用 Helm 清单,直接在各个命名空间中存储为 Secret 或 ConfigMap 的检查。

Terminal window
sh -c "$(curl -sSL 'https://git.io/install-kubent')"
Terminal window
kubent -k /root/.kube/config
_____________________________________________________________________________
>>> Deprecated APIs removed in 1.25 <<<
------------------------------------------------------------------------------------------

将 HelmRelease 记录中 K8s 废弃 API 转换为源版本和目标版本均兼容的 API,可以通过 helm 社区工具转换

除以上所有集群版本通用检查外,还有一些特定版本的检查。

历史原因,1.18 版本以前,TKE 提供 intree csi 的能力,在 api 中声明了 csi 的字段,字段在 1.20 版本中,该字段与社区 pb 号冲突,因此在 1.18 升级到 1.20 时,需要检查集群内是否有使用 intree csi 和 inline csi,如果有使用,需要转换为 outree 的 pv 和 pvc 才能升级,否则升级会阻塞。

社区在 1.23 版本,不再默认注入 serviceaccount,在 1.22 升级到 1.24 时,当您需要使用 serviceaccount 时,需要显式声明,否则在服务滚动更新后,会因为没有 serviceaccount 导致服务异常。

PodSecurityPolicy 在 1.21 版本被弃用,在 1.25 版本中被彻底移除。提高其可用性所需要的更新会带来破坏性的变化,因此有必要删除它,用更友好的 Pod Security Admission 来替代,如果当前已经使用了 PodSecurityPolicy,请参见 从 PSP 迁移

升级集群后,您无法对其进行降级。您可通过 TKE 提供的 备份中心 能力,对集群进行备份,可用于备份现有集群并将备份应用到新集群。如果升级失败,您可使用原始版本创建新集群并恢复数据平面。请注意,备份中不包含云上的资源,这些资源需要重新创建。

按照 TKE 集群升级文档 中的 升级 Master Kubernetes 版本 部分进行 master 升级。升级应选择业务低峰期,升级期间应该暂停操作集群和发布。

!!! warning “注意” 1. 控制面升级无法回滚,如果是大规模生产集群,可以提前联系 TKE 进行升级护航 2. 若已设置的 master 自定义参数,原参数不保留,需要重新设置新版本的自定义参数 3. 控制面升级后,需要预留足够的观察时间(15~20 分钟),有些行为变更是与新版的 Kubernetes 相关的,在升级到新版本后,才会通过 Kubernetes 的 reconcile 机制生效

Q:master 集群在控制台发起升级后,有没有办法回滚?

A:升级属于不可逆操作,不支持升级回滚,k8s 官方也不支持升级回滚,升级后如果回滚,会有大量的不可预知的兼容性风险。

  • 数据丢失:在升级过程中,旧版本的 Kubernetes 组件可能会被新版本覆盖或删除。这可能导致旧版本的数据丢失,包括配置、日志、存储卷等。如果升级后出现问题,回滚到旧版本可能会导致数据不一致或丢失
  • 状态不一致:Kubernetes 集群中的各种组件(如 Pod、Replicaset、Service 等)可能会在升级过程中处于不一致的状态。这可能导致回滚后集群出现错误,甚至无法正常工作
  • 版本兼容性问题:在升级过程中,新版本的 Kubernetes 组件可能与旧版本的 API Server 或其他组件不兼容。这可能导致回滚后集群出现错误,甚至无法正常工作
  • 升级策略问题:在升级过程中,如果没有正确配置升级策略(如滚动升级、蓝绿部署等),可能会导致集群中的部分节点升级成功,而其他节点仍然运行旧版本。这可能导致回滚后集群出现错误,甚至无法正常工作
  • 手动干预:在升级过程中,如果手动干预了集群的配置或状态,可能会导致回滚后集群出现错误,甚至无法正常工作

因此,在进行 Kubernetes 集群版本升级时,务必确保已经充分测试了新版本,并正确配置了升级策略。如果升级后出现问题,可以考虑使用备份和恢复工具来恢复数据,而不是直接回滚到旧版本。

Q:之前设置的自定义参数升级时是否会保留?

A:独立集群自定义参数场景下,master 升级会还原成默认的,对客户影响比较大(需要在升级之前对比一下参数,后端已有接口:DescribeClusterMasterDiff

托管集群自定义参数场景下,master 升级后自定义参数会保留,但如果自定义参数在新版本被废弃了,升级会阻塞。

Q:如何保证集群升级的成功率?

A:TKE 的集群升级都经过严格测试,大量验证后开放给客户,升级流程中,TKE 后台会监控集群整体的运行状态,当集群出现异常时会及时暂停升级,减少风险。