熟練オフリッピングするサークルからK8S - なぜ私たちは、名前空間のクラスタを削除することはできませんか?

販売後の学生の技術チームは、両方の毎日オンライン奇妙な質問のすべての種類を扱っでアリの雲。一般的な、ネットワーク接続障害、サーバーのダウンタイム、パフォーマンスがアップし、遅い応答要求に対してではありませんがあります。あなたは脳を作るのに十分な些細実際に思える何の問題、選択したい場合はしかし、私は答えは間違いなく「カットできない」問題であると考えています。たとえば、削除されたファイルは余裕がないことができ、プロセスを終了する余裕がない、ので、ドライブがアンインストールすることはできません。

この問題は、我々が予想以上に多くの場合、それらの背後にある複雑なロジックの影に隠された氷山、のようなものです。

背景

問題は、我々は、関連する名前空間K8Sクラスタで、今日議論されています。名前空間は、「ストレージ」メカニズムK8Sクラスタリソースです。私たちは、関係のないリソースへの影響との間に不必要を避けるために、同じ名前空間に「収容」、関連リソースを置くことができます。

名前空間自体がリソースです。クラスタAPIサーバーを介して入り口は、私たちは、新しい名前空間を作成することができますし、名前空間が使用されなくなったために、私たちが出てきれいにする必要がありません。コントローラの名前空間は、APIサーバーを通過し、クラスタの名前空間の変化を監視して、事前に定義された変更に基づいてアクションを実行します。
11

時々、私たちは、下図の問題、状態の名前空間を持っており、「終端」をマークしたが、完全に除去する方法はありません。
22

クラスタの入り口を開始

クラスタAPIサーバーを介してアクションを実行するので、私たちは、APIサーバーの動作を分析する必要があります。同様の構成要素のほとんどのクラスタは、APIサーバーは、ログ出力の異なるレベルを提供します。API Serverの動作を理解するために、我々は、最高レベルのログ出力レベルを調整します。その後、削除して問題を再現するには、この名前空間を作成tobedeletedb。

しかし残念ながら、APIサーバーは、多くのログに関連する問題をエクスポートしません。

関連ログは、2つの部分に分けることができます。名前空間削除されたレコードの一部、レコードが表示され、クライアントツールはkubectlであり、送信元IPアドレスの操作を開始すると、期待に沿ったもので、192.168.0.41であり、他の部分は、この情報の重複名前空間を得ることにKUBEコントローラマネージャです。
33

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

Controller在做什么?

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

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

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

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

API、Group、Version

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

我们创建的每一个资源,都必然属于某一个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分组和版本。
77

实际上,集群有很多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”。
88

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

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

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

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

节点与Pod之间的通信

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

以上图为例,如果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实例的时候,没有办法获取到这个实例的信息。
44

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

集群节点访问云资源

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

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

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

问题大图

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

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

后记

問題を削除することはできませんK8Sクラスタ名前空間には、問題がより一般的なオンラインです。この問題は無害と思われるが、実際にはないだけに複雑ですが、また、クラスタの重要な機能が欠け意味します。我々は同様の問題を解決したいの調査は、方法と原則、この記事で、この問題の包括的な分析は、確かに役立ちます。

おすすめ

転載: yq.aliyun.com/articles/710206