本文由雲+社區發表javascript
做者:turboxu前端
Kubernetes做爲容器編排生態圈中重要一員,是Google大規模容器管理系統borg的開源版本實現,吸取借鑑了google過去十年間在生產環境上所學到的經驗與教訓。 Kubernetes提供應用部署、維護、 擴展機制等功能,利用Kubernetes能方便地管理跨機器運行容器化的應用。當前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平臺,除此以外,也能夠直接運行在物理機上.kubernetes是一個開放的容器調度管理平臺,不限定任何一種言語,支持java/C++/go/python等各種應用程序 。java
kubernetes是一個完備的分佈式系統支持平臺,支持多層安全防禦、准入機制、多租戶應用支撐、透明的服務註冊、服務發現、內建負載均衡、強大的故障發現和自我修復機制、服務滾動升級和在線擴容、可擴展的資源自動調度機制、多粒度的資源配額管理能力,完善的管理工具,包括開發、測試、部署、運維監控,一站式的完備的分佈式系統開發和支撐平臺。node
kubernetes系統按節點功能由master和node組成。python
Mastergit
Master做爲控制節點,調度管理整個系統,包含如下組件:算法
API Server做爲kubernetes系統的入口,封裝了核心對象的增刪改查操做,以RESTful接口方式提供給外部客戶和內部組件調用。它維護的REST對象將持久化到etcd。docker
Scheduler:負責集羣的資源調度,爲新建的pod分配機器。這部分工做分出來變成一個組件,意味着能夠很方便地替換成其餘的調度器。後端
Controller Manager:負責執行各類控制器,目前有兩類:api
Node
Node是運行節點,運行業務容器,包含如下組件:
Kubelet:責管控docker容器,如啓動/中止、監控運行狀態等。它會按期從etcd獲取分配到本機的pod,並根據pod信息啓動或中止相應的容器。同時,它也會接收apiserver的HTTP請求,彙報pod的運行狀態。
Kube Proxy:負責爲pod提供代理。它會按期從etcd獲取全部的service,並根據service信息建立代理。當某個客戶pod要訪問其餘pod時,訪問請求會通過本機proxy作轉發。
借用一張網圖,表達功能組件之間關係:
node是kubernetes集羣中相對於master而言的工做主機,在較早版本中也被稱爲minion。Node能夠是一臺物理主機,也能夠是一臺虛擬機(VM)。在每一個node上運行用於啓動和管理pod的服務——kubelet,並可以被master管理。在node上運行的服務進程包括kubelet、kube-proxy和docker daemon。
Node的信息以下:
node地址:主機的IP地址或者nodeid。
node的運行狀態: pending,running,terminated。
node condition: 描述running狀態node的運行條件,目前只有一種條件Ready,表示node處於健康狀態,能夠接收master發來的建立pod的指令。
node系統容量:描述node可用的系統資源,包括CPU、內存、最大可調度pod數量等。
pod 是 kubernetes 的最基本操做單元,包括一個或多個緊密相關的容器,一個 pod 能夠被一個容器化的環境看做應用層的「邏輯宿主機」( Logical host )。一個 pod 中的多個容器應用一般是緊耦合的。Pod 在 node 上被建立、啓動或者銷燬。
爲何 kubernetes 使用 pod 在容器之上再封裝一層呢?一個很重要的緣由是,docker 容器之間通訊受到 docker 網絡機制的限制。在 docker 的,世界中,一個容器須要經過 link 方式才能訪問另外一個容器提供的服務(端口)。大量容器之間的 link 將是一個很是繁重的工做。經過 pod 的概念將多個容器組合在一個虛擬的「主機」內,能夠實現容器之間僅需經過 localhost 就能相互通訊了。
一個pod中的應用容器共享一組資源,如:
pid命名空間:pod中的不一樣應用程序能夠看到其餘的進程PID
網絡命名空間:pod中的多個容器可以訪問同一個IP和端口範圍
IPC命名空間:pod中的多個容器可以使用systemV ipc 或POSIX消息隊列進行通訊。
UTS命名空間:pod中的多個容器共享一個主機名。
Volumes(共享存儲卷):pod中的各個容器能夠訪問在pod級別定義的volumes。
label是kubernetes系統中的一個核心概念。Label以key/value鍵值對的形式附加到各類對象上,如pod、service、RC、Node等。Label定義了這些對象的可識別屬性,用來對它們進行管理和選擇。Label能夠在建立對象時附加到對象上,也能夠在對象建立後經過API進行管理。
在爲對象定義好label後,其餘對象就可使用label selector來定義其餘做用的對象了。
label selector的定義由多個逗號分隔的條件組成: 「label」: { 「key1」: 」value1」, 「key2」: 」value2」 }
Resource controller(RC)是kubernetes系統中的核心概念,用於定義pod副本的數量。在master的Controller manager進程經過RC的定義來完成pod的建立、監控、啓停等操做。
根據replication controller的定義,kubernetes可以確保在任意時刻都能運行用戶指定的pod「副本」(replica)數量。若是有過多的的pod副本在運行,系統會停掉一些pod;若是運行的pod副本數量太少,系統就會再啓動一些pod,總之,經過RC的定義,kubernetes老是保證集羣中運行着用戶指望副本數量。
在kubernetes的世界裏,雖然每一個pod都會被分配一個單獨的IP地址,但這個IP地址會隨着pod的銷燬而消失。這就引出一個問題:若是有一組pod組成一個集羣來提供服務,那麼如何來訪問它們呢?
kubernetes的service就是用來解決這個問題的核心概念。一個service能夠看做一組提供相同服務的pod的對外訪問接口。Service做用於哪些pod是經過label selector 來定義的。
pod的IP地址是docker daemon根據docker0網橋的IP地址段進行分配的,但service的Cluster IP地址是kubernetes系統中的虛擬IP地址,由系統動態分配。 Service的ClusterIP地址相對於pod的IP地址來講相對穩定,service被建立時即被分配IP地址,在銷燬該service以前,這個IP地址都不會再變化。
因爲service對象在Cluster IP Range池中分配到的IP只能在內部訪問,因此其餘pod均可以無障礙地訪問到它。但若是這個service做爲前端服務,準備爲集羣外的客戶端提供服務,咱們就須要給這個服務提供公共IP了。
kubernetes支持兩種對外提供服務的service的type定義:nodeport和loadbalancer。
volume是pod中可以被多個容器訪問的共享目錄。Kubernetes的volume概念與docker的volume比較相似,但並不徹底相同。Kubernetes中的volume與pod生命週期相同,但與容器的生命週期不相關。當容器終止或重啓時,volume中的數據也不會丟失。另外,kubernetes支持多種類型的volume,而且一個pod能夠同時使用任意多個volume。
(1)EmptyDir:一個EmptyDir volume是在pod分配到Node時建立的。從它的名稱就能夠看出,它的初始內容爲空。在同一個pod中全部容器能夠讀和寫EmptyDir中的相同文件。當pod從node上移除時,EmptyDir中的數據也會永久刪除。
(2)hostPath:在pod上掛載宿主機上的文件或目錄。一般用於: 容器應用程序生成的日誌文件須要永久保存,可使用宿主機的高速文件系統進行存儲; 須要訪問宿主機上的docker引擎內部數據結構的容器應用,能夠經過定義hostPath爲宿主機/var/lib/docker目錄,使容器內部應用能夠直接訪問docker的文件系統。
(3)gcePersistentDick:使用這種類型的volume表示使用谷歌計算引擎(Google Compute Engine, GCE)上永久磁盤(persistent disk,PD)上的文件。與EmptyDir不一樣,PD上的內容會永久保存,當pod被刪除時,PD只是被卸載(unmount),但不會被刪除。須要注意的是,你須要先建立一個永久磁盤(PD)才能使用gcePersistentDisk。
(4)awsElasticBlockStore:與GCE相似,該類型的volume使用Amazon提供的Amazon Web Service(AWS)的EBS Volume,並能夠掛載到pod中去。須要注意的是,須要先建立一個EBS Volume才能使用awsElasticBlockStore。
(5)nfs:使用NFS(網絡文件系統)提供的共享目錄掛載到Pod中。在系統中須要一個支行中的NFS系統。
(6)iscsi:使用iSCSI存儲設備上的目錄掛載到pod中。
(7)glusterfs:使用開源BlusterFS網絡文件系統的目錄掛載到pod中。
(8)rbd:使用Linux塊設備共享存儲(Rados Block Device)掛載到pod中。
(9)gitRepo:經過掛載一個空目錄,並從GIT庫clone一個git repository以供pod使用。
(10)secret:一個secret volume用於爲pod提供加密的信息,你能夠將定義在kubernetes中的secret直接掛載爲文件讓pod訪問。Secret volume是經過tmfs(內存文件系統)實現的,因此這種類型的volume老是不會持久化的。
(11)persistentVolumeClaim:從PV(persistentVolume)中申請所需的空間,PV一般是種網絡存儲,如GCEPersistentDisk、AWSElasticBlockStore、NFS、iSCSI等。
namespace(命名空間)是kubernetes系統中另外一個很是重要的概念,經過將系統內部的對象「分配」到不一樣的namespace中,造成邏輯上分組的不一樣項目、小組或用戶組,便於不一樣的分組在共享使用整個集羣的資源的同時還能分別管理。
kubernetes集羣在啓動後,會建立一個名爲「default」的namespace。接下來,若是不特別指明namespace,則用戶建立的pod、RC、Service都將被系統建立到名爲「default」的namespace中。
使用namespace來組織kubernetes的各類對象,能夠實現對用戶的分組,即「多租戶」管理。對不一樣的租房還能夠進行單獨的資源配額設備和管理,使得整個集羣配置很是靈活、方便。
annotation與label相似,也使用key/value鍵值對的形式進行定義。Label具備嚴格的全名規則,它定義的是kubernetes對象的元數據(metadata),而且用於label selector。Annotation則是用戶任意定義的「附加」信息,以便於外部工具進行查找。
用annotation來記錄的信息包括: build信息、release信息、docker鏡像信息等,如時間戳、release id號、PR號、鏡像hash值、docker Controller地址等。
以建立一個Pod爲例,kubernetes典型的流程以下圖所示:
爲了區分Controller Manager中的Replication Controller(副本控制器)和資源對象Replication Controller,咱們將資源對象簡寫爲RC,而Replication Controller特指「副本控制器」。
Replication Controller的核心做用是確保在任什麼時候間集羣中一個RC所關聯的pod都保持必定數量的pod副本處於正常運行狀態。若是該類pod的pod副本數量太多,則Replication Controller會銷燬一些pod副本;反之Replication Controller會添加pod副本,直到該類pod的pod副本數量達到預設的副本數量。最好不要超過RC直接建立pod,由於Replication Controller會經過RC管理pod副本,實現自動建立、補足、替換、刪除pod副本,這樣就能提升系統的容災能力,減小因爲節點崩潰等意外情況形成的損失。即便應用程序只用到一個pod副本,也強烈建設使用RC來定義pod。
Replication Controller管理的對象是pod,所以其操做與pod的狀態及重啓策略息息相關。
副本控制器的經常使用使用模式:
(1)從新調度:無論想運行1個副本仍是1000副本,副本控制器可以確保指定pod數量的副本存在於集羣中,若是節點故障或副本被終止運行等意外狀況,將會從新調度直到達到預期的副本正常運行。
(2)彈性伸縮:手動或經過自動擴容代理修改副本控制器的spec.replicas屬性值,很是容易實現擴大或縮小副本的數量。
(3)滾動更新:副本控制器被設計成經過逐個替換pod的方式來輔助服務的滾動更新。推薦的方式是建立一個新的只有一個副本的RC,若新的RC副本數量加1,則舊的RC的副本數量減1,直到這個舊的RC副本數量爲零,而後刪除該舊的RC。
在滾動更新的討論中,咱們發現一個應用在滾動更新時,可能存在多個版本的release。事實上,在生產環境中一個已經發布的應用程序存在多個release版本是很正常的現象。經過RC的標籤選擇器,咱們能很方便地實現對一個應用的多版本release的跟蹤。
Node Controller負責發現、管理和監控集羣中的各個node節點。Kubelet在啓動時經過API Server註冊節點信息,並定時向API Server發送節點信息。API Server接收到這些信息後,將這些信息寫入etcd。存入etcd的節點信息包括節點健康情況、節點資源、節點名稱、節點地址信息、操做系統版本、docker版本、kubelet版本等。節點健康情況包含「就緒(true)」、「未就緒(false)」和「未知(unknown)」三種。
(1)Controller Manager 在啓動時若是設置了—cluster-cidr參數,那麼爲每一個沒有設置spec.podCIDR的node生成一個CIDR地址,並用該CIDR設置節點的spec.PodCIDR屬性,這樣的目的是防止不一樣節點的CIDR地址發生衝突。
(2)逐個讀取節點的信息,屢次嘗試修改nodeStatusMap中的節點狀態信息,將該節點信息和node controller的nodeStatusMap中保存的節點信息比較。若是判斷中沒有收到kubelet發送的節點信息、第一次收到節點kubelet發送的節點信息,或在該處理過程當中節點狀態變成非「健康」狀態,則在nodeStatusMap中保存該節點的狀態信息,並用node controller所在節點的系統時間做爲探測時間和節點狀態變化時間。 若是判斷出在某一段時間內沒有收到節點的狀態信息,則設置節點狀態爲「未知(unknown)」,而且經過api server保存節點狀態。
(3)逐個讀取節點信息,若是節點狀態變爲非「就緒」狀態,則將節點加入待刪除隊列,不然將節點從該隊列中刪除。若是節點狀態爲非「就緒」狀態,且系統指定了Cloud Provider,則node controller調用Cloud Provider查看節點,若發現並節點故障,則刪除etcd中的節點信息,並刪除和該節點相關的pod等資源的信息。
做爲容器集羣的管理平臺, kubernetes也提供了資源配額管理這一高級功能,資源配額管理確保指定的對象在任什麼時候候都不會超量佔用系統資源,避免了因爲某些業務進程的設計或實現的缺陷致使整個系統運行紊亂甚至意外宕機,對整個集羣的平穩運行和穩定性有很是重要的做用。
目前kubernetes支持三個層次的資源配額管理:
(1)容器級別,能夠對CPU和內存的資源配額管理。
(2)pod級別,能夠對pod內全部容器的可用資源進行限制。
(3)namespace級別,爲namespace(能夠用於多租戶)級別的資源限制,包括:pod數量、replication Controller數量、service數量、ResourceQuota數量、secret數量、可持有的PV(persistent volume)數量。 kubernetes的配額管理是經過准入機制(admission control)來實現的,與配額相關的兩種准入控制器是LimitRanger和ResoureQuota,其中LimitRanger做用於pod和container上,ResourceQuota則做用於namespace上。此外,若是定義了資源配額,則scheduler在pod調度過程當中也會考慮這一因素,確保pod調度不會超出配額限制。
典型的資源控制流程以下圖所示:
用戶經過API Server能夠建立新的namespace並保存在etcd中,namespace controller定時經過api server讀取這些namespace信息。若是namespace被API標識爲優雅刪除(設置刪除期限,deletionTimestamp屬性被設置),則將該namespace的狀態設置爲「terminating」並保存到etcd中。同時namespace controller刪除該namespace下的serviceAccount、RC、Pod、Secret、PersistentVolume、ListRange、SesourceQuota和event等資源對象。 當namespace的狀態被設置爲「terminating」後,由Adminssion Controller的NamespaceLifecycle插件來阻止爲該namespace建立新的資源。同時,在namespace controller刪除完該namespace中的全部資源對象後,Namespace Controller對該namespace執行finalize操做,刪除namespace的spec.finalizers域中的信息。
若是Namespace Controller觀察到namespace設置了刪除期限(即DeletionTimestamp屬性被設置),同時namespacer 的spec.finalizers域值是空的,那麼namespace controller將經過API Server刪除該namespace資源。
ServiceAccount Controller和token Controller是與安全相關的兩個控制器。ServiceAccount Controller在Controller Manager啓動時被建立。它監聽Service Account的刪除事件和Namespace的建立、修改事件。若是在該Service Account的namespace中沒有default Service Account,那麼ServiceAccount Controller爲該Service Account的namespace建立一個default ServiceAccount。
在API Server的啓動中添加「—admission_control=ServiceAccount」後,API Server在啓動時會本身建立一個key和crt(/var/run/kubernetes/apiserver.crt和apiserver.key),而後在啓動./kube-controller-manager時添加參數service_account_privatge_key_file=/var/run/kubernetes/apiserver.key,這樣啓動kubernetes master後,就會發如今建立Service Account時系統會自動爲其建立一個secret。
若是Controller Manager在啓動時指定參數爲service-account-private-key-file,並且該參數所指定的文件包含一個PEM-encoded的編碼的RSA算法的私鑰,那麼,Controler Manager會建立token controller對象。
token controller對象監聽Service Account的建立、修改和刪除事件,並根據事件的不一樣作不一樣的處理。若是監聽到的事件是建立和修改Service Account事件,則讀取該Service Account的信息;若是該Service Account沒有Service Account Secret(即用於訪問Api server的secret),則用前面說起的私鑰爲該Service Account建立一個JWT Token,將該Token和ROOT CA(若是啓動時參數指定了該 ROOT CA)放入新建的secret中,將該新建的secret放入該Service Account中,同時修改etcd中Service Account的內容。若是監聽到的事件是刪除Service Account事件,則刪除與該Service Account相關的secret。
token controller對象同時監聽secret的建立、修改和刪除事件,並根據事件的不一樣作不一樣的處理。若是監聽到的事件是建立和修改secret事件,那麼讀取該secret中annotation所指定的Service Account信息,並根據須要爲該secret建立一個和其Service Account相關的token;若是監聽到的事件是刪除secret事件,則刪除secret和相關的Service Account的引用關係。
Kubernetes service是一個定義pod集合的抽象,或者被訪問都看做一個訪問策略,有時也被稱爲微服務。 kubernetes中的service是種資源對象,各全部其餘資源對象同樣,能夠經過API Server的POST接口建立一個新的實例。在下面的例子代碼中建立了一個名爲「MyServer」的Service,它包含一個標籤選擇器,經過該標籤選擇器選擇全部包含標籤爲「app=MyApp」的pod做爲該service的pod集合。Pod集合中的每一個pod的80端口被映射到節點本地的9376端口,同時kubernetes指派一個集羣IP(即虛擬IP)給該service。
{ 「kind」: 」service」, 「apiVersion」: 」v1」, 「metadata」: { 「name」: 」MyService」 }, 「spec」: { 「selector」: { 「app」: 」MyApp」 }, 「ports」: [ { 「protocol」: 」TCP」, 「port」: 80, 「targetPort」: 9376 } ] }, }
在kubernetes集羣中的每一個node上都運行着一個叫「kube-proxy」的進程,該進程會觀察master節點添加和刪除「service」和「endpoint」的行爲,如圖中第1步所示。
kube-proxy爲每一個service在本地主機上開一個端口(隨機選擇)。任何訪問該端口的鏈接都被代理到相應的一個後端pod上。Kube-proxy根據round robin算法及service的session粘連(SessionAffinity)決定哪一個後臺pod被選中,如第2步所示。
最後,如第3步所示,kube-proxy在本機的iptables中安裝相應的規則,這些規則使得iptables將捕獲的流量重定向到前面說起的隨機端口。經過該端口流量再被kube-proxy轉到相應的後端pod上。
在建立了服務後,服務endpoint模型會建立後端pod的IP和端口列表(包含中endpoint對象中),kube-proxy就是從這個endpoint列表中選擇服務後端的。集羣內的節點經過虛擬IP和端口可以訪問service後臺的pod。
在默認狀況下,kubernetes會爲server指定一個集羣IP(或虛擬IP、cluster IP),但在某些狀況下,但願可以本身指定該集羣IP。爲了給service指定集羣IP,用戶只須要在定義service時,在service的spec.clusterIP域中設置所須要的IP地址便可。
scheduler在整個kubernetes系統中承擔了「承上啓下」的重要功能,「承上」是指它負責接收Controller Manager建立的新pod,爲其安排一個落腳的「家」——目標node;「啓下」是指安置工做完成後,目標node上的kubelet服務進程接管後繼工做,負責pod生命週期中的「下半生」。
具體來講,scheduler的做用是將待調度的pod(API新建立的Pod、Controller Manager爲補足副本而建立的pod等)按照特定的調度算法和調度策略綁定(binding)到集羣中的某個合適的node上,並將綁定信息寫入etcd中。在整個調度過程當中涉及三個對象,分別是:待調度的pod列表、可用node列表、以及調度算法和策略。簡單地說,就是經過調度算法調度,爲待調度pod列表中的每一個pod從node列表中選擇一個最適合的node。
隨後,目標node上的kublet經過API Server監聽到scheduler產生的pod綁定事件,而後獲對應的取pod,下載image鏡像,並啓動容器。
scheduler當前提供的默認調度流程分爲兩步:
(1)預選調度過程,即遍歷全部目標node,篩選出符合要求的候選節點。爲此kubernetes內置了多種預先策略(xxx predicates)供用戶選擇。
(2)肯定最優節點,在第一步的基礎上,採用優先策略(xxx priority)計算出每一個候選節點的積分,積分最高都勝出。 scheduler的調度流程是經過插件方式加載的「調度算法提供者(AlgorithmProvider)」具體實現的。一個AlgorithmProvider其實就是包括了一組預選策略與一組優選策略的結構體,註冊AlgorithmProvider的函數以下: func RegisterAlgorithmProvider(name string, predicateKeys, priorityKeys util.StringSet) 它包含3個參數,name string 參數爲算法名;
predicateKeys參數爲算法集合用到的預選策略集合 priorityKeys 參數爲算法用到的優選策略集合 scheduler 中可用的預選策略包含7個,每一個節點只有經過PodFitsPorts、PodFitsResources、NoDiskConflict、PodSelectorMatches、PodFitsHost 5個默認預先策略後,才能初步被選中,進入下一個流程。
每一個節點經過優選策略時都會算出一個得分,計算各項得分,最終選出得分值最大的節點做爲優選的結果(也是調度算法的結果)。LeastRequestedPriority,選擇資源消耗最小節點:
(1)計算出全部備選節點上運行的pod和備選pod的CPU佔用量totalMilliCPU
(2)計算出全部備選節點上運行的pod和備選pod的內存佔用量totalMomory
(3)計算每一個節點的得分,計算規則大體以下: score=int(((nodeCpuCapacity-totalMilliCPU)10)/nodeCpuCapacity+((nodeMemoryCapacity-totalMemory)10/nodeMemoryCapacity)/2) CalculateNodeLabelPriority,根據CheckNodeLabelPresence策略打分 BalancedResourceAllocation,選擇資源使用最均衡節點
(1)計算出全部備選節點上運行的pod和備選pod的CPU佔用量totalMilliCPU
(2)計算出全部備選節點上運行的pod和備選pod的內存佔用量totalMomory
(3)計算每一個節點的得分,計算規則大體以下: score=int(10-math.abs(totalMilliCPU/nodeCpuCapacity-totalMemory/nodeMemoryCapacity) * 10)
節點管理包含節點的註冊、狀態上報、Pod管理、容器健康檢查、資源監控等部分。
在kubernetes集羣中,在每一個node節點上都會啓動一個kubelet服務進程。該進程用於處理master節點下發到本節點的任務,管理pod及pod中的容器。每一個kubelet進程會在API Server上註冊節點自身信息,按期向master節點彙報節點資源使用狀況,並經過cAdvisor監控容器和節點資源。
節點經過設置kubelet的啓動參數「—register-node」,來決定是否向API Server註冊本身。若是該參數爲true,那麼kubelet將試着經過API Server註冊本身。做爲自注冊,kubelet啓動還包含下列參數:
--api-servers,告訴kubelet API Server的位置; --kubeconfig,告訴kubelet在哪兒能夠找到用於訪問API Server的證書; --cloud-provider,告訴kubelet如何從雲服務商(IAAS)那裏讀取到和本身相關的元數據。
kubelet在啓動時經過API Server註冊節點,並定時向API Server發送節點新消息,API Server在接收到這些信息後,將這些信息寫入etcd。經過kubelet的啓動參數「—node-status-update-frequency」設置kubelet每隔多少時間向API Server報告節點狀態,默認爲10秒。
kubelet經過如下幾種方式獲取自身node上所要運行的pod清單: (1)文件:kubelet啓動參數「--config」指定的配置文件目錄下的文件。經過—file-check-frequency設置檢查該文件目錄的時間間隔,默認爲20秒。
(2)HTTP端點(URL):經過「—manifest-url」參數設置。經過—http-check-frequency設置檢查該HTTP端點的數據時間間隔,默認爲20秒。
(3)API Server:kubelet經過API Server監聽etcd目錄,同步pod清單。
全部以非API Server方式建立的pod都叫做static pod。Kubelet將static pod的狀態彙報給API Server,API Server爲static pod建立一個mirror pod和其相匹配。Mirror pod的狀態將真實反映static pod的狀態。當static pod被刪除時,與之相對應的mirror pod也會被刪除。Kubelet經過API Server client使用watch+list的方式監聽「/registry/node/ <當前node名稱> 」和「/registry/pods」目錄,將獲取的信息同步到本地緩存中。
kubelet監聽etcd,全部針對pod的操做將會被kubelet監聽到。若是發現有新的綁定到本節點的pod,則按照pod清單的要求建立該pod。若是發現本地的pod被修改,則kubelet會作出相應的修改,如刪除pod中的某個容器時,則經過docker client刪除該容器。若是發現刪除本節點的pod,則刪除相應的pod,並經過docker client刪除pod中的容器。
kubelet讀取監聽到的信息,若是是建立和修改pod任務,則作以下處理:
(1)爲該pod建立一個數據目錄。
(2)從API Server讀取該pod清單。
(3)爲該pod掛載外部卷(Extenal Volume)。
(4)下載pod用到的secret。
(5)檢查已經運行在節點中的pod,若是該 pod沒有容器或pause容器沒有啓動,則先中止pod裏全部容器進程。若是在pod中有須要刪除的容器,則刪除這些容器。
(6)用「kubernetes/pause」鏡像爲每一個pod建立一個容器,該pause容器用於接管pod中全部其餘容器的網絡。
(7)爲pod中的每一個容器作以下處理:
爲容器計算一個hash值,而後用容器的名字去docker查詢對應容器的hash值。若查到容器,且二者hash值不一樣,則中止docker中容器進程,並中止與之關聯的pause容器進程;若二者相同不作任何處理。
若是容器被停止了,且容器沒有指定的restartPolicy(重啓策略),則不作任何處理。
調用docker client下載容器鏡像,調用docker client運行容器。
pod經過兩類探針來檢查容器的健康狀態。一個是LivenessProbe探針,用於判斷容器是否健康,告訴kubelet一個容器何時處於不健康的狀態。若是LivenessProbe探針探測到容器不健康,則kubelet將刪除容器,並根據容器的重啓策略作相應的處理。若是一個容器不包含LivenessProbe探針,那麼kubelet認爲該容器的LivenessProbe探針返回的值永遠是「success」.另外一類是ReadinessProbe探針,用於判斷容器是否啓動完成,且準備接收請求。若是ReadinessProbe探針檢測到失敗,則pod的狀態將被修改。Endpoint controller將從service的endpoint中刪除包含該容器所在pod的IP地址的endpoint條目。
此文已由做者受權騰訊雲+社區在各渠道發佈
獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號