50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

深入浅出 Kubernetes 实践篇 (三):命名空间删除问题

  • 2020-03-30
  • 本文字数:3677 字

    阅读完需:约 12 分钟

深入浅出Kubernetes 实践篇 (三):命名空间删除问题

阿里云售后技术团队的同学,每天都在处理各式各样千奇百怪的线上问题。常见的有,网络连接失败,服务器宕机,性能不达标,请求响应慢等。但如果要评选,什么问题看起来微不足道事实上却足以让人绞尽脑汁,我相信答案肯定是“删不掉”的问题。比如文件删不掉,进程结束不掉,驱动卸载不了等。


这样的问题就像冰山,影藏在它们背后的复杂逻辑,往往超过我们的预想。

背景

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


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



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


从集群入口开始

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


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


相关的日志,可以分为两部分。一部分是命名空间被删除的记录,记录显示客户端工具是 kubectl,以及发起操作的源 IP 地址是 192.168.0.41,这符合预期;另外一部分是 Kube Controller Manager 在重复的获取这个命名空间的信息。



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

Controller 在做什么?

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



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


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



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


API、Group、Version


怎么样罗列集群中的所有资源呢,这个问题需要从集群 API 的组织方式说起。Kubernetes 集群的 API 不是铁板一块的,它是用分组和版本来组织的。这样做的好处显而易见,就是不同分组的 API 可以独立的迭代,互不影响。常见的分组如 apps,它有 v1,v1beta1 和 v1beta2 这三个版本。完整的分组/版本列表,可以使用 kubectl api-versions 命令看到。



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


kind: Ingressmetadata:  name: test-ingressspec:  rules:  - http:      paths:      - path: /testpath        backend:          serviceName: test          servicePort: 80
复制代码


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



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


Controller 为什么不能删除命名空间里的资源


理解了 API 分组/版本的概念之后,再回头看 Kube Controller Manager 的日志,就会豁然开朗。显然命名空间的 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 之间的通信问题。在阿里云 Kubernetes 集群环境里,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 全部都消失了。


问题大图

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



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

后记

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


作者简介


罗建龙(花名声东),阿里云技术专家。多年操作系统和图形显卡驱动调试和开发经验。目前专注云原生领域,容器集群和服务网格。


相关阅读


深入浅出Kubernetes 实践篇 (一):节点就绪问题之一


深入浅出Kubernetes 实践篇 (二):节点就绪问题之二


2020-03-30 17:141385

评论

发布
暂无评论
发现更多内容

一文带你剖析LiteOS互斥锁Mutex源代码

华为云开发者联盟

mutex LiteOS 互斥锁 互斥锁结构体

2D+1D | vivo官网Web 3D应用开发与实战

vivo互联网技术

大前端 WebGL 3D数据可视化 Draco 3D

智慧公安情报综合研判平台开发,助推公安信息化发展

13828808769

智慧城市

OKR实践中的痛点(5):战略缺失怎么玩OKR?

大叔杨

团队管理 OKR 敏捷 敏捷绩效

技术人如何调研和选型第三方 SDK?全文干货

融云 RongCloud

「免费开源」基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之业务数据增删改查(七)

crudapi

Vue API crud crudapi quasar

划重点丨详解Java流程控制语句知识点

华为云开发者联盟

Java 流程控制语句

数据分析与数据增长核心逻辑杂谈

小飞象@木木自由

数据分析

公有云成本节省神器!京东云共享带宽包正式上线

京东科技开发者

公有云 带宽

亿网嘉元是做什么的?

飞亚科技

装双系统?不需要!教你在iMac上流畅使用Windows

懒得勤快

Mac 虚拟机 苹果 crossover

NA(Nirvana)公链“为应用而生” NAC公链领跑公链新格局!

区块链第一资讯

创建索引,这些知识应该了解

Simon

MySQL 索引

区块链电子合同技术方案,区块链电子合同存证

13828808769

区块链 区块链+

Cloudreve 自建云盘实践,我说了没人能限得了我的容量和速度!

小傅哥

Java 小傅哥 Cloudreve 自建云盘

线上服务 CPU 100% ?一键定位 so easy!

Java小咖秀

性能 cpu 服务器 负载 紧急问题

SumSwap在市场上的强大突破是否会成为DEX领域最大的黑马?

币圈资讯

进来看看是不是你想要的效果,Android吸顶效果,并有着ViewPager左右切换

第三女神程忆难

Java android kotlin 安卓 移动开发

css网页布局小结

Darren

CSS

【LeetCode】子集二Java题解

Albert

算法 LeetCode 4月日更

云小课 | 不了解EIP带宽计费规则?看这里!

华为云开发者联盟

带宽 弹性公网IP 带宽变更 计费模式

你的数仓函数结果不稳定,可能是属性指定错了

华为云开发者联盟

函数 GaussDB(DWS) 函数属性 函数下推 易失性级别

MySQL 事务隔离

Sakura

4月日更

Linux rmdir 命令

一个大红包

linux命令 4月日更

大意!6行代码,“报废”5片单片机!

不脱发的程序猿

程序人生 嵌入式软件 单片机 4月日更 国产MCU

华为帐号服务学习笔记(三):10分钟完成Authorization Code模式客户端Demo开发

Coding狙击

android HMS

云数据库时代的新思考,这位90后大咖想邀你聊聊

华为云开发者联盟

数据库 开源 opengauss GaussDB 华为云数据库

派出所重点人员管控系统开发,建设智慧警务

13828808769

智慧组工

Dubbo 学习笔记(三) Spring Boot 整合 Dubbo(官方版)

U2647

Spring Boot dubbo 4月日更

将本地maven仓库的数据恢复到Nexus仓库

白粥

工作笔记

systemctl的使用

箭上有毒

linux运维 4月日更

深入浅出Kubernetes 实践篇 (三):命名空间删除问题_文化 & 方法_罗建龙(声东)_InfoQ精选文章