我们为什么会删除不了集群的 Namespace?

背景

今天我们讨论的这个问题,跟 K8s 集群的 Namespace 有关。Namespace 是 K8s 集群资源的“收纳”机制。我们可以把相关的资源“收纳”到同一个 Namespace 里,以避免不相关资源之间不必要的影响。

Namespace 本身也是一种资源。通过集群 API Server 入口,我们可以新建 Namespace,而对于不再使用的 Namespace,我们需要清理掉。Namespace 的 Controller 会通过 API Server,监视集群中 Namespace 的变化,然后根据变化来执行预先定义的动作。

图片

有时候,我们会遇到下图中的问题,即 Namespace 的状态被标记成了 “Terminating”,但却没有办法被完全删除。

图片

从集群入口开始

因为删除操作是通过集群 API Server 来执行的,所以我们要分析 API Server 的行为。跟大多数集群组件类似,API Server 提供了不同级别的日志输出。为了理解 API Server 的行为,我们将日志级别调整到最高级。然后,通过创建删除 tobedeletedb 这个 Namespace 来重现问题。

但可惜的是,API Server 并没有输出太多和这个问题有关的日志。

相关的日志,可以分为两部分:

  • 一部分是 Namespace 被删除的记录,记录显示客户端工具是 kubectl,以及发起操作的源 IP 地址是 192.168.0.41,这符合预期;
  • 另外一部分是 Kube Controller Manager 在重复地获取这个 Namespace 的信息。

图片

Kube Controller Manager 实现了集群中大多数的 Controller,它在重复获取 tobedeletedb 的信息,基本上可以判断,是 Namespace 的 Controller 在获取这个 Namespace 的信息。

Controller 在做什么?

和上一节类似,我们通过开启 Kube Controller Manager 最高级别日志,来研究这个组件的行为。在 Kube Controller Manager 的日志里,可以看到 Namespace 的 Controller 在不断地尝试一个失败了的操作,就是清理 tobedeletedb 这个 Namespace 里“收纳”的资源。

1. 怎么样删除“收纳盒”里的资源?

这里我们需要理解一点,就是 Namespace 作为资源的“收纳盒”,其实是逻辑意义上的概念。它并不像现实中的收纳工具,可以把小的物件收纳其中。Namespace 的“收纳”实际上是一种映射关系。

图片

这一点之所以重要,是因为它直接决定了,删除 Namespace 内部资源的方法。如果是物理意义上的“收纳”,那我们只需要删除“收纳盒”,里边的资源就一并被删除了。而对于逻辑意义上的关系,我们则需要罗列所有资源,并删除那些指向需要删除的 Namespace 的资源。

2. API、Group、Version

怎么样罗列集群中的所有资源呢?这个问题需要从集群 API 的组织方式说起。

K8s 集群的 API 不是铁板一块的,它是用分组和版本来组织的。这样做的好处显而易见,就是不同分组的 API 可以独立迭代,互不影响。常见的分组如 apps,它有 v1、v1beta1 和 v1beta2 三个版本。完整的分组/版本列表,可以使用 kubectl api-versions 命令看到。

图片

我们创建的每一个资源,都必然属于某一个 API 分组/版本。以下边 Ingress 为例,我们指定 Ingress 资源的分组/版本为 networking.k8s.io/v1beta1。

kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

用一个简单的示意图来总结 API 分组和版本。

图片

实际上,集群有很多 API 分组/版本,每个 API 分组/版本支持特定的资源类型。我们通过 yaml 编排资源时,需要指定资源类型 kind,以及 API 分组/版本 apiVersion。而要列出资源,我们需要获取 API 分组/版本的列表。

3. Controller 为什么不能删除 Namespace 里的资源?

理解了 API 分组/版本的概念之后,再回头看 Kube Controller Manager 的日志,就会豁然开朗。显然 Namespace 的 Controller 在尝试获取 API 分组/版本列表,当遇到 metrics.k8s.io/v1beta1 的时候,查询失败了。并且查询失败的原因是 “the server is currently unable to handle the request”。

再次回到集群入口

在上文中,我们发现 Kube Controller Manager 在获取 metrics.k8s.io/v1beta1 这个 API 分组/版本的时候失败了。而这个查询请求,显然是发给 API Server 的。所以我们回到 API Server 日志,分析 metrics.k8s.io/v1beta1 相关的记录。

在相同的时间点,我们看到 API Server 也报了同样的错误 “the server is currently unable to handle the request”。

图片

显然这里有一个矛盾,就是 API Server 明显在正常工作,为什么在获取 metrics.k8s.io/v1beta1 这个 API 分组版本的时候,会返回 Server 不可用呢?为了回答这个问题,我们需要理解一下 API Server 的“外挂”机制。

图片

集群 API Server 有扩展自己的机制,开发者可以利用这个机制,来实现 API Server 的“外挂”。这个“外挂”的主要功能,就是实现新的 API 分组/版本。API Server 作为代理,会把相应的 API 调用,转发给自己的“外挂”。

以 Metrics Server 为例,它实现了 metrics.k8s.io/v1beta1 这个 API 分组/版本。所有针对这个分组/版本的调用,都会被转发到 Metrics Server。如下图,Metrics Server 的实现,主要用到一个服务和一个 pod。

图片

而上图中最后的 apiservice,则是把“外挂”和 API Server 联系起来的机制。下图可以看到这个 apiservice 详细定义。它包括 API 分组/版本,以及实现了 Metrics Server 的服务名。有了这些信息,API Server 就能把针对 metrics.k8s.io/v1beta1 的调用,转发给 Metrics Server。

图片

节点与 Pod 之间的通信

经过简单的测试,我们发现,这个问题实际上是 API server 和 metrics server pod 之间的通信问题。在阿里云 K8s 集群环境里,API Server 使用的是主机网络,即 ECS 的网络,而 Metrics Server 使用的是 Pod 网络。这两者之间的通信,依赖于 VPC 路由表的转发。

图片

以上图为例,如果 API Server 运行在 Node A 上,那它的 IP 地址就是 192.168.0.193。假设 Metrics Server 的 IP 是 172.16.1.12,那么从 API Server 到 Metrics Server 的网络连接,必须要通过 VPC 路由表第二条路由规则的转发。

检查集群 VPC 路由表,发现指向 Metrics Server 所在节点的路由表项缺失,所以 API server 和 Metrics Server 之间的通信出了问题。

Route Controller 为什么不工作?

为了维持集群 VPC 路由表项的正确性,阿里云在 Cloud Controller Manager 内部实现了 Route Controller。这个 Controller 在时刻监听着集群节点状态,以及 VPC 路由表状态。当发现路由表项缺失的时候,它会自动把缺失的路由表项填写回去。

现在的情况,显然和预期不一致,Route Controller 显然没有正常工作。这个可以通过查看 Cloud Controller Manager 日志来确认。在日志中,我们发现,Route Controller 在使用集群 VPC id 去查找 VPC 实例的时候,没有办法获取到这个实例的信息。

图片

但是集群还在,ECS 还在,所以 VPC 不可能不在了。这一点我们可以通过 VPC id 在 VPC 控制台确认。那下边的问题,就是为什么 Cloud Controller Manager 没有办法获取到这个 VPC 的信息呢?

集群节点访问云资源

Cloud Controller Manager 获取 VPC 信息,是通过阿里云开放 API 来实现的。这基本上等于从云上一台 ECS 内部,去获取一个 VPC 实例的信息,而这需要 ECS 有足够的权限。目前的常规做法是,给 ECS 服务器授予 RAM 角色,同时给对应的 RAM 角色绑定相应的角色授权。

图片

如果集群组件,以其所在节点的身份,不能获取云资源的信息,那基本上有两种可能性。一是 ECS 没有绑定正确的 RAM 角色;二是 RAM 角色绑定的 RAM 角色授权没有定义正确的授权规则。检查节点的 RAM 角色,以及 RAM 角色所管理的授权,我们发现,针对 vpc 的授权策略被改掉了。

图片

当我们把 Effect 修改成 Allow 之后,没多久,所有的 Terminating 状态的 namespace 全部都消失了。

图片

问题大图

总体来说,这个问题与 K8s 集群的 6 个组件有关系,分别是 API Server 及其扩展 Metrics Server,Namespace Controller 和 Route Controller,以及 VPC 路由表和 RAM 角色授权。

图片

通过分析前三个组件的行为,我们定位到,集群网络问题导致了 API Server 无法连接到 Metrics Server;通过排查后三个组件,我们发现导致问题的根本原因是 VPC 路由表被删除且 RAM 角色授权策略被改动。

总结

K8s 集群 Namespace 删除不掉的问题,是线上比较常见的一个问题。这个问题看起来无关痛痒,但实际上不仅复杂,而且意味着集群重要功能的缺失。这篇文章全面分析了一个这样的问题,其中的排查方法和原理,希望对大家排查类似问题有一定的帮助。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/228226.html<

(0)
运维的头像运维
上一篇2025-04-18 05:11
下一篇 2025-04-18 05:12

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注