跳转至

TKE 防误删策略配置最佳实践

TKE 是基于 K8s 的腾讯云核心 PaaS 产品,承载了微信、腾讯游戏、腾讯视频、小红书、央视频等海量核心业务,管理的 CPU 规模核心数千万核。K8s 中心式管理、声明式管理、以及控制器实时对账式的管理模式,给我们带来便利的背后,也潜藏着极大的稳定性风险,如 K8s Namespace 的删除会触发 Namespace 下的 Pod 等资源级联删除,K8s 的 CoreDNS 组件的 Helm Chart 配置不当导致 CoreDNS ConfigMap 被删除影响集群内部通信,K8s 的核心系统组件 kubernetes-proxy 被清理,导致集群无法正常访问。任何一个误删除操作都可能会导致整个集群大量业务异常,导致大规模故障的产生。

TKE 的稳定性深刻影响着各个业务的稳定性,为了对抗 K8s 的脆弱性,TKE 团队上线了策略管理模块,通过产品级策略来保障 K8s 集群、节点和系统组件的稳定运行。本文先介绍 TKE 在运维大规模用户集群中遇到的各类误删除典型案例,针对各种删除场景提出了产品化解决方案——基于开源组件 Gatekeeper(本质是 Webhook Server)实现的各类资源删除保护策略,接着介绍了 TKE 当前支持的防误删策略列表,最后介绍各个策略的配置示例,便于用户启用策略。

1. 误删除背景介绍

1.1. 行业真实发生的误删除案例

下面收集了 K8s 生产环境因资源删除操作出现的一些列故障,暴露出 K8s 在误删防护方面的脆弱性和生产使用中的潜在风险。

上述资源删除行为发生后,虽然在事后可以进行资源恢复,但是关键 Pod 被销毁对业务造成的中断,会影响业务的正常运行,仅仅依靠备份恢复,无法从根本上解决问题。

1.2. 误删除操作背后的根因分析

1.2.1. 声明式 API 的不可逆性

案例体现

  • CRD 删除导致关联 CR 级联销毁(案例 2)
  • CoreDNS ConfigMap 被 Helm 模板误删(案例 5)
  • Pod 被误删引发系统组件宕机(案例 6)

风险本质

Kubernetes 采用声明式 API,资源状态由控制器自动维护。一旦关键资源(如 CRD、ConfigMap)被删除,控制器会立即执行预期外的清理动作,且无法通过简单回滚恢复。

1.2.2. 级联删除的默认行为

案例体现

  • Namespace 级联删除导致业务 Pod 全灭(案例 1)
  • Argo CD 误删应用资源(案例 3)

风险本质

Kubernetes 默认启用级联删除(--cascade=true),删除父资源时会连带销毁子资源(如 Deployment 删除导致 ReplicaSet/Pod 消失)。

1.2.3. 自动化工具的"双刃剑"效应

案例体现

  • Helm Chart 模板缺陷导致 ConfigMap 误删(案例 5)
  • xargs 批量删除误伤业务节点(案例 4)

风险本质

Kubernetes 生态工具(如 Helm、kubectl)的自动化能力大幅提升了效率,但语法错误或逻辑缺陷会放大误操作影响范围。

1.2.4. 权限管理的天然缺陷

案例体现

  • 集群被完全删除(案例 8)
  • 系统组件 Pod 被误删(案例 6/7)

风险本质

Kubernetes Role-Based Access Control (RBAC) 默认允许用户操作其命名空间内资源,但缺乏细粒度权限分级(如禁止删除核心组件)。

1.2.5. 声明式架构的认知门槛

案例体现

  • 误认为删除 CRD 不会影响已有 CR
  • 认为单个 Pod 删除不会影响 Service 可用性
  • 忽视节点删除对调度策略的影响

风险本质

声明式架构的抽象层级较高,开发者容易低估底层依赖关系。例如:删除 Node 不仅移除物理节点,还会触发 Pod 重新调度策略。

1.3. 小结

Kubernetes 的声明式架构通过控制器模型实现了强大的自动化能力,但也显著提高了操作风险。开发/运维人员需具备以下能力才能规避误操作:

  1. 深度理解资源拓扑关系:熟悉 Controller-Resource-Object 的依赖链
  2. 精细化权限管理:通过 RBAC 实现最小权限控制
  3. 完备的备份体系:依靠 tke-backup 实现快速恢复
  4. 混沌工程实践:定期演练误删除场景下的灾难恢复能力

在诸多系统架构和软件系统风险管控的经验总结中,都反复提及一个观点:"Designing systems with built-in safeguards (e.g., fail-safe mechanisms) ensures that even if human error occurs, the system compensates to prevent catastrophic outcomes"(系统需要内置保护措施,确保即使发生人为错误也能够防止灾难性的后果),企业需在架构设计阶段即植入容错机制,而非依赖操作人员的"零失误"。

为了防止误删除引起业务故障,TKE 利用开源组件 Gatekeeper 实现了防误删功能。对重要的 K8s 资源进行删除拦截,阻断非预期的删除行为,防止误删除引起重大业务故障。

2. 产品方案介绍

2.1. 产品化方案

TKE 新增"策略管理"模块,预定义 K8s 核心资源防护策略,并将策略部署到用户集群中。当删除操作发生时,基于策略判断是否是误删除行为,对于判定为误删除的删除请求进行拦截。

例如:策略 存在 pod 的命名空间不允许删除

用户执行 kubectl delete namespace xxx 时,系统自动判断 namespace 下是否存在 pod,如果 pod 存在则当前删除行为会被拦截,命令行 error 提示不可删除及错误原因。

具体说明见:容器服务 策略管理 - TKE 标准集群指南

2.2. 技术原理

底层基于 Kubernetes validating webhook 机制,拦截集群内资源的 delete 请求,策略引擎组件基于策略对请求分析研判是否属于误删除行为,如果是误删除行为则需要被拦截。

核心组件/配置说明

  • gatekeeper-controller-manager:接收删除请求并匹配策略,判断是否拦截
  • gatekeeper-provider:查询被删除资源的信息
  • constrainttemplates:策略模板,定义策略的拦截逻辑
  • constraints:策略实例,定义策略生效的资源对象

防误删组件部署在管控面集群,webhook、策略模版、策略实例部署在用户集群中。

3. TKE 支持的防误删策略

3.1. 防误删策略集合

TKE 目前通过产品化方式支持的资源误删除保护策略如下:

3.2. 策略详情

该章节对每个策略进行详细介绍,具体说明了策略的使用场景、参数配置和生效的资源类型,并给出默认的策略实例。

3.2.1. 存在 pod 的命名空间不允许删除

基本信息

  • 策略类型:优选策略
  • 生效资源类型:Pod
  • 参数:excludedNamespaces
  • 参数类型:字符串数组。表示策略豁免生效的命名空间,在该列表中的命名空间不会生效此条策略。
  • 参数值设置
    • 不填该字段或者字段取值为空时,表示没有豁免的命名空间。
    • 支持前缀匹配,例如 excludedNamespaces: ["kube-*"] 匹配 "kube-system" 和 "kube-public"。
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。

作用

拦截非预期的 namespace 删除行为。避免删除 namespace 前未检查 namespace 下是否有正在运行的组件,误删除 namespace 时导致组件被级联删除引起业务故障。

策略实例示例

以下策略实例展示了策略定义生效的资源类型和豁免的 namespace,其中策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.2.2. 存在 cr 的 crd 不允许删除

基本信息

  • 策略类型:优选策略
  • 生效资源类型:CRD
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。

作用

拦截非预期的 CRD 删除行为。避免删除 CRD 前未检查 CRD 下是否有已创建的 CR 资源,直接删除 CRD 导致有效的业务 CR 资源被级联删除。

策略实例示例

以下策略实例展示了策略定义生效的资源类型。其中策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.2.3. CoreDNS 组件删除保护

基本信息

  • 策略类型:优选策略
  • 生效资源类型:CoreDNS 的 Deployment、ConfigMap、Service
  • 参数:min_replicas
  • 参数类型:整数。表示 CoreDNS 的 Deployment 更新后,允许的最小副本数。
  • 参数值设置
    • 默认值为 2,用户按照集群的规模和业务调用量级修改。
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。

作用

拦截非预期的 CoreDNS 组件删除行为。避免 CoreDNS 组件升级时误删除相关的 ConfigMap、Service 导致 CoreDNS 不可用,甚至将 CoreDNS 的副本数调至很低,和集群负载不匹配,引起组件之间通信问题。

策略实例示例

以下策略实例展示了策略定义生效的资源类型和最小副本数设置,kinds 列表中的 Scale 是为了避免使用 kubectl scale 调整 CoreDNS 的副本数为非预期值。策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.2.4. 资源删除保护

基本信息

  • 策略类型:优选策略
  • 生效资源类型:Service、Ingress、Deployment、StatefulSet
  • 参数:LabelName、LabelValue
  • 参数类型:字符串。表示要进行删除保护的资源当前具备的 Label Name 和 Label Value 信息。
  • 参数值设置
    • 默认值为 LabelName=tke.cloud.tencent.com/delete-protectionLabelValue="true",用户可以使用已有的 Label Name 和 Value 替换默认值,也可以给要保护的资源打上默认的 Label 使策略生效。
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。

作用

基于资源标签保护 K8s 集群内的资源,拦截非预期的业务组件和配置被删除。避免正在运行的业务组件或配置在未经确认的情况被删除,导致业务中断。

策略实例示例

以下策略实例展示了策略定义生效的资源类型和默认的删除保护标签,用户可以去掉示例中不需要保护的资源 apiGroups 和 kinds,但是不能增加新的 kinds,因为资源 Kind 也需要添加到 validating webhook 配置中才能生效,后台 webhook 规则仅添加了示例中的资源 Kind。此外,如果想要该策略实例创建后立即生效,需要把 LabelName 和 LabelValue 替换为集群内现有资源的 Label 信息。策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.2.5. PV 处于绑定状态则不允许删除

基本信息

  • 策略类型:优选策略
  • 生效资源类型:PersistentVolume
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。

作用

保护正在使用的磁盘卷不被删除。PersistentVolume 正在使用时,如果被删除会卡在删除状态(因为 K8s 有 finalizer 保护机制),但是删除过程不可逆。该策略从根本上保证 PersistentVolume 不会被误删除。

策略实例示例

以下策略实例展示了策略定义生效的资源类型。策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.2.6. 非封锁状态的 Node 不允许删除

基本信息

  • 策略类型:优选策略
  • 生效资源类型:Node
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。

作用

保护正在使用中的 Node 不被删除。Node 处于非封锁状态时,会持续有新 Pod 调度上来。删除 Node 会引起 Pod 批量重建,在 Pod 没有配置打散策略时,会引起业务中断。

策略实例示例

以下策略实例展示了策略定义生效的资源类型。策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.2.7. Node 处于封锁状态,如果 Node 上仍然存在运行中的非 DaemonSet 类型 Pod,则不允许删除 Node

基本信息

  • 策略类型:优选策略
  • 生效资源类型:Node
  • 参数:enforcementAction
  • 参数类型:字符串。表示策略的运行模式。
  • 参数值设置
    • 固定值 dryrun,只检查请求是否命中策略,命中后不执行实际拦截操作。
    • 固定值 deny,请求命中策略后执行拦截操作。
  • 其他:该策略目前在控制台不可见,因为需要升级管控面的组件才能使用该策略。

作用

保护正在使用中的 Node 不被删除。Node 处于封锁状态时,但是上面的 Pod 没有被驱逐,Pod 会正常对外提供服务。删除 Node 会引起 Pod 批量重建,在 Pod 没有配置打散策略时,会引起业务中断。

策略实例示例

以下策略实例展示了策略定义生效的资源类型。策略运行模式见 enforcementAction 字段,目前为 deny 模式。

3.3. 创建和管理策略实例

3.3.1. 创建策略实例

单集群创建策略实例

针对单个集群的策略开启,可以使用控制台。通过控制台创建策略实例。

多集群创建策略实例

策略管理功能目前没有支持策略批量下发到多集群的能力。如果用户希望将多个策略下发到多个集群,且保证多个集群策略实例相同,建议通过云 API 来开启。

创建策略云 API:ModifyOpenPolicyList。跳转链接

策略的运行模式切换,如:从 deny 模式切换到 dryrun 模式,可以在界面操作。也可以调用云 API ModifyOpenPolicyList 完成操作。

3.3.2. 修改/删除策略实例

单集群修改/删除策略实例

通过控制台操作。

多集群修改/删除策略实例

通过 kubectl 连接集群,修改和删除策略实例。

4. 防误删策略开启的影响

1. 策略拦截产生的影响

问题场景:策略开启后,如果业务销毁时,直接删除 Namespace 或者 CRD 资源,且命中了防误删策略,会对业务的销毁流程产生拦截。

解决方案:策略有 deny 和 dryrun 模式。用户可以先开启 dryrun 进行观察(弊端:dryrun 命中时没有审计日志,只能靠 TKE 观察后台日志)。

2. 删除链路增加一跳产生的影响

问题场景:删除链路增加了策略判断这个环节,如果后台 gatekeeper 组件无法正常提供服务,会影响删除操作。

解决方案:防误删策略是通过 Webhook 实现。相关 Webhook 规则在配置时,设置了 failurePolicy: Ignore。如果 Webhook Server 挂了,会放过删除请求的检测,不会拦截删除请求,和没有开启策略的效果一样。

3. 用户自定义策略潜在的影响

问题场景:因为防误删是通过开源组件 Gatekeeper 来实现,用户可以根据需要,自己定义策略模板和策略实例,然后修改 Webhook 规则,将请求发送到 Gatekeeper 组件使其生效。如果用户在设置 Webhook 规则时,将资源的 GKV 全部设置为 *,会将所有请求定向到 Gatekeeper Server,可能会把后台打挂。

解决方案:用户要遵循最小配置原则,且联系 TKE 运维进行容量评估和预留。

4. 耗时方面的影响

Gatekeeper 在做策略判断时,简单的判断逻辑会在 50-100 毫秒内返回。需要调用第三方云 API 判断时,需要 200-400 毫秒返回。