K8S从懵圈到熟练 - 我们为什么会删除不了集群的命名空间?
阿里云售后技術(shù)團(tuán)隊(duì)的同學(xué),每天都在處理各式各樣千奇百怪的線上問(wèn)題。常見(jiàn)的有,網(wǎng)絡(luò)連接失敗,服務(wù)器宕機(jī),性能不達(dá)標(biāo),請(qǐng)求響應(yīng)慢等。但如果要評(píng)選,什么問(wèn)題看起來(lái)微不足道事實(shí)上卻足以讓人絞盡腦汁,我相信答案肯定是“刪不掉”的問(wèn)題。比如文件刪不掉,進(jìn)程結(jié)束不掉,驅(qū)動(dòng)卸載不了等。
這樣的問(wèn)題就像冰山,影藏在它們背后的復(fù)雜邏輯,往往超過(guò)我們的預(yù)想。
背景
今天我們討論的這個(gè)問(wèn)題,跟K8S集群的命名空間有關(guān)。命名空間是K8S集群資源的“收納”機(jī)制。我們可以把相關(guān)的資源,“收納”到同一個(gè)命名空間里,以避免不相關(guān)資源之間不必要的影響。
命名空間本身也是一種資源。通過(guò)集群API Server入口,我們可以新建命名空間,而對(duì)于不再使用的命名空間,我們需要清理掉。命名空間的Controller會(huì)通過(guò)API Server,監(jiān)視集群中命名空間的變化,然后根據(jù)變化來(lái)執(zhí)行預(yù)先定義的動(dòng)作。
有時(shí)候,我們會(huì)遇到下圖中的問(wèn)題,即命名空間的狀態(tài)被標(biāo)記成了“Terminating”,但卻沒(méi)有辦法被完全刪除。
從集群入口開(kāi)始
因?yàn)閯h除操作是通過(guò)集群API Server來(lái)執(zhí)行的,所以我們要分析API Server的行為。跟大多數(shù)集群組件類(lèi)似,API Server提供了不同級(jí)別的日志輸出。為了理解API Server的行為,我們將日志級(jí)別調(diào)整到最高級(jí)。然后,通過(guò)創(chuàng)建刪除tobedeletedb這個(gè)命名空間來(lái)重現(xiàn)問(wèn)題。
但可惜的是,API Server并沒(méi)有輸出太多和這個(gè)問(wèn)題有關(guān)的日志。
相關(guān)的日志,可以分為兩部分。一部分是命名空間被刪除的記錄,記錄顯示客戶端工具是kubectl,以及發(fā)起操作的源IP地址是192.168.0.41,這符合預(yù)期;另外一部分是Kube Controller Manager在重復(fù)的獲取這個(gè)命名空間的信息。
Kube Controller Manager實(shí)現(xiàn)了集群中大多數(shù)的Controller,它在重復(fù)獲取tobedeletedb的信息,基本上可以判斷,是命名空間的Controller在獲取這個(gè)命名空間的信息。
Controller在做什么?
和上一節(jié)類(lèi)似,我們通過(guò)開(kāi)啟Kube Controller Manager最高級(jí)別日志,來(lái)研究這個(gè)組件的行為。在Kube Controller Manager的日志里,可以看到命名空間的Controller在不斷地嘗試一個(gè)失敗了的操作,就是清理tobedeletedb這個(gè)命名空間里“收納”的資源。
怎么樣刪除“收納盒”里的資源
這里我們需要理解一點(diǎn),就是命名空間作為資源的“收納盒”,其實(shí)是邏輯意義上的概念。它并不像現(xiàn)實(shí)中的收納工具,可以把小的物件收納其中。命名空間的“收納”實(shí)際上是一種映射關(guān)系。
這一點(diǎn)之所以重要,是因?yàn)樗苯記Q定了,刪除命名空間內(nèi)部資源的方法。如果是物理意義上的“收納”,那我們只需要?jiǎng)h除“收納盒”,里邊的資源就一并被刪除了。而對(duì)于邏輯意義上的關(guān)系,我們則需要羅列所有資源,并刪除那些指向需要?jiǎng)h除的命名空間的資源。
API、Group、Version
怎么樣羅列集群中的所有資源呢,這個(gè)問(wèn)題需要從集群API的組織方式說(shuō)起。K8S集群的API不是鐵板一塊的,它是用分組和版本來(lái)組織的。這樣做的好處顯而易見(jiàn),就是不同分組的API可以獨(dú)立的迭代,互不影響。常見(jiàn)的分組如apps,它有v1,v1beta1和v1beta2這三個(gè)版本。完整的分組/版本列表,可以使用kubectl api-versions命令看到。
我們創(chuàng)建的每一個(gè)資源,都必然屬于某一個(gè)API分組/版本。以下邊Ingress為例,我們指定Ingress資源的分組/版本為networking.k8s.io/v1beta1。
kind: Ingress metadata:name: test-ingress spec:rules:- http:paths:- path: /testpathbackend:serviceName: testservicePort: 80用一個(gè)簡(jiǎn)單的示意圖來(lái)總結(jié)API分組和版本。
實(shí)際上,集群有很多API分組/版本,每個(gè)API分組/版本支持特定的資源類(lèi)型。我們通過(guò)yaml編排資源時(shí),需要指定資源類(lèi)型kind,以及API分組/版本apiVersion。而要列出資源,我們需要獲取API分組/版本的列表。
Controller為什么不能刪除命名空間里的資源
理解了API分組/版本的概念之后,再回頭看Kube Controller Manager的日志,就會(huì)豁然開(kāi)朗。顯然命名空間的Controller在嘗試獲取API分組/版本列表,當(dāng)遇到metrics.k8s.io/v1beta1的時(shí)候,查詢失敗了。并且查詢失敗的原因是“the server is currently unable to handle the request”。
再次回到集群入口
在上一節(jié)中,我們發(fā)現(xiàn)Kube Controller Manager在獲取metrics.k8s.io/v1beta1這個(gè)API分組/版本的時(shí)候失敗了。而這個(gè)查詢請(qǐng)求,顯然是發(fā)給API Server的。所以我們回到API Server日志,分析metrics.k8s.io/v1beta1相關(guān)的記錄。在相同的時(shí)間點(diǎn),我們看到API Server也報(bào)了同樣的錯(cuò)誤“the server is currently unable to handle the request”。
顯然這里有一個(gè)矛盾,就是API Server明顯在正常工作,為什么在獲取metrics.k8s.io/v1beta1這個(gè)API分組版本的時(shí)候,會(huì)返回Server不可用呢?為了回答這個(gè)問(wèn)題,我們需要理解一下API Server的“外掛”機(jī)制。
集群API Server有擴(kuò)展自己的機(jī)制,開(kāi)發(fā)者可以利用這個(gè)機(jī)制,來(lái)實(shí)現(xiàn)API Server的“外掛”。這個(gè)“外掛”的主要功能,就是實(shí)現(xiàn)新的API分組/版本。API Server作為代理,會(huì)把相應(yīng)的API調(diào)用,轉(zhuǎn)發(fā)給自己的“外掛”。
以Metrics Server為例,它實(shí)現(xiàn)了metrics.k8s.io/v1beta1這個(gè)API分組/版本。所有針對(duì)這個(gè)分組/版本的調(diào)用,都會(huì)被轉(zhuǎn)發(fā)到Metrics Server。如下圖,Metrics Server的實(shí)現(xiàn),主要用到一個(gè)服務(wù)和一個(gè)pod。
而上圖中最后的apiservice,則是把“外掛”和API Server聯(lián)系起來(lái)的機(jī)制。下圖可以看到這個(gè)apiservice詳細(xì)定義。它包括API分組/版本,以及實(shí)現(xiàn)了Metrics Server的服務(wù)名。有了這些信息,API Server就能把針對(duì)metrics.k8s.io/v1beta1的調(diào)用,轉(zhuǎn)發(fā)給Metrics Server。
節(jié)點(diǎn)與Pod之間的通信
經(jīng)過(guò)簡(jiǎn)單的測(cè)試,我們發(fā)現(xiàn),這個(gè)問(wèn)題實(shí)際上是API server和metrics server pod之間的通信問(wèn)題。在阿里云K8S集群環(huán)境里,API Server使用的是主機(jī)網(wǎng)絡(luò),即ECS的網(wǎng)絡(luò),而Metrics Server使用的是Pod網(wǎng)絡(luò)。這兩者之間的通信,依賴于VPC路由表的轉(zhuǎn)發(fā)。
以上圖為例,如果API Server運(yùn)行在Node A上,那它的IP地址就是192.168.0.193。假設(shè)Metrics Server的IP是172.16.1.12,那么從API Server到Metrics Server的網(wǎng)絡(luò)連接,必須要通過(guò)VPC路由表第二條路由規(guī)則的轉(zhuǎn)發(fā)。
檢查集群VPC路由表,發(fā)現(xiàn)指向Metrics Server所在節(jié)點(diǎn)的路由表項(xiàng)缺失,所以API server和Metrics Server之間的通信出了問(wèn)題。
Route Controller為什么不工作?
為了維持集群VPC路由表項(xiàng)的正確性,阿里云在Cloud Controller Manager內(nèi)部實(shí)現(xiàn)了Route Controller。這個(gè)Controller在時(shí)刻監(jiān)聽(tīng)著集群節(jié)點(diǎn)狀態(tài),以及VPC路由表狀態(tài)。當(dāng)發(fā)現(xiàn)路由表項(xiàng)缺失的時(shí)候,它會(huì)自動(dòng)把缺失的路由表項(xiàng)填寫(xiě)回去。
現(xiàn)在的情況,顯然和預(yù)期不一致,Route Controller顯然沒(méi)有正常工作。這個(gè)可以通過(guò)查看Cloud Controller Manager日志來(lái)確認(rèn)。在日志中,我們發(fā)現(xiàn),Route Controller在使用集群VPC id去查找VPC實(shí)例的時(shí)候,沒(méi)有辦法獲取到這個(gè)實(shí)例的信息。
但是集群還在,ECS還在,所以VPC不可能不在了。這一點(diǎn)我們可以通過(guò)VPC id在VPC控制臺(tái)確認(rèn)。那下邊的問(wèn)題,就是為什么Cloud Controller Manager沒(méi)有辦法獲取到這個(gè)VPC的信息呢?
集群節(jié)點(diǎn)訪問(wèn)云資源
Cloud Controller Manager獲取VPC信息,是通過(guò)阿里云開(kāi)放API來(lái)實(shí)現(xiàn)的。這基本上等于,從云上一臺(tái)ECS內(nèi)部,去獲取一個(gè)VPC實(shí)例的信息,而這需要ECS有足夠的權(quán)限。目前的常規(guī)做法是,給ECS服務(wù)器授予RAM角色,同時(shí)給對(duì)應(yīng)的RAM角色綁定相應(yīng)的角色授權(quán)。
如果集群組件,以其所在節(jié)點(diǎn)的身份,不能獲取云資源的信息,那基本上有兩種可能性。一是ECS沒(méi)有綁定正確的RAM角色;二是RAM角色綁定的RAM角色授權(quán)沒(méi)有定義正確的授權(quán)規(guī)則。檢查節(jié)點(diǎn)的RAM角色,以及RAM角色所管理的授權(quán),我們發(fā)現(xiàn),針對(duì)vpc的授權(quán)策略被改掉了。
當(dāng)我們把Effect修改成Allow之后,沒(méi)多久,所有的Terminating狀態(tài)的namespace全部都消失了。
問(wèn)題大圖
總體來(lái)說(shuō),這個(gè)問(wèn)題與K8S集群的6個(gè)組件有關(guān)系,分別是API Server及其擴(kuò)展Metrics Server,Namespace Controller和Route Controller,以及VPC路由表和RAM角色授權(quán)。
通過(guò)分析前三個(gè)組件的行為,我們定位到,集群網(wǎng)絡(luò)問(wèn)題導(dǎo)致了API Server無(wú)法連接到Metrics Server;通過(guò)排查后三個(gè)組件,我們發(fā)現(xiàn)導(dǎo)致問(wèn)題的根本原因是VPC路由表被刪除且RAM角色授權(quán)策略被改動(dòng)。
后記
K8S集群命名空間刪除不掉的問(wèn)題,是線上比較常見(jiàn)的一個(gè)問(wèn)題。這個(gè)問(wèn)題看起來(lái)無(wú)關(guān)痛癢,但實(shí)際上不僅復(fù)雜,而且意味著集群重要功能的缺失。這篇文章全面分析了一個(gè)這樣的問(wèn)題,其中的排查方法和原理,希望對(duì)大家排查類(lèi)似問(wèn)題有一定的幫助。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的K8S从懵圈到熟练 - 我们为什么会删除不了集群的命名空间?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: K8S中手动扩容云盘数据卷
- 下一篇: 一个实时精准触达系统的自我修养