一文帶你看透kubernetes 容器編排系統

Kubernetes作為容器編排生態圈中重要一員,是Google大規模容器管理系統borg的開源版本實現,吸收借鑑了google過去十年間在生產環境上所學到的經驗與教訓。 Kubernetes提供應用部署、維護、 擴展機制等功能,利用Kubernetes能方便地管理跨機器運行容器化的應用。當前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平臺,除此之外,也可以直接運行在物理機上.kubernetes是一個開放的容器調度管理平臺,不限定任何一種言語,支持java/C++/go/python等各類應用程序 。

kubernetes是一個完備的分佈式系統支持平臺,支持多層安全防護、准入機制、多租戶應用支撐、透明的服務註冊、服務發現、內建負載均衡、強大的故障發現和自我修復機制、服務滾動升級和在線擴容、可擴展的資源自動調度機制、多粒度的資源配額管理能力,完善的管理工具,包括開發、測試、部署、運維監控,一站式的完備的分佈式系統開發和支撐平臺。

一. 系統架構

kubernetes系統按節點功能由master和node組成。

一文帶你看透kubernetes 容器編排系統

Master

Master作為控制節點,調度管理整個系統,包含以下組件:

API Server作為kubernetes系統的入口,封裝了核心對象的增刪改查操作,以RESTful接口方式提供給外部客戶和內部組件調用。它維護的REST對象將持久化到etcd。

Scheduler:負責集群的資源調度,為新建的pod分配機器。這部分工作分出來變成一個組件,意味著可以很方便地替換成其他的調度器。

Controller Manager:負責執行各種控制器,目前有兩類:

  1. Endpoint Controller:定期關聯service和pod(關聯信息由endpoint對象維護),保證service到pod的映射總是最新的。
  2. Replication Controller:定期關聯replicationController和pod,保證replicationController定義的複製數量與實際運行pod的數量總是一致的。

Node

Node是運行節點,運行業務容器,包含以下組件:

Kubelet:責管控docker容器,如啟動/停止、監控運行狀態等。它會定期從etcd獲取分配到本機的pod,並根據pod信息啟動或停止相應的容器。同時,它也會接收apiserver的HTTP請求,彙報pod的運行狀態。

Kube Proxy:負責為pod提供代理。它會定期從etcd獲取所有的service,並根據service信息創建代理。當某個客戶pod要訪問其他pod時,訪問請求會經過本機proxy做轉發。

借用一張網圖,表達功能組件之間關係:

一文帶你看透kubernetes 容器編排系統

二.基本概念

Node

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

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

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)

Resource controller(RC)是kubernetes系統中的核心概念,用於定義pod副本的數量。在master的Controller manager進程通過RC的定義來完成pod的創建、監控、啟停等操作。

根據replication controller的定義,kubernetes能夠確保在任意時刻都能運行用戶指定的pod“副本”(replica)數量。如果有過多的的pod副本在運行,系統會停掉一些pod;如果運行的pod副本數量太少,系統就會再啟動一些pod,總之,通過RC的定義,kubernetes總是保證集群中運行著用戶期望副本數量。

Service(服務)

在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(存儲卷)

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(命名空間)

namespace(命名空間)是kubernetes系統中另一個非常重要的概念,通過將系統內部的對象“分配”到不同的namespace中,形成邏輯上分組的不同項目、小組或用戶組,便於不同的分組在共享使用整個集群的資源的同時還能分別管理。

kubernetes集群在啟動後,會創建一個名為“default”的namespace。接下來,如果不特別指明namespace,則用戶創建的pod、RC、Service都將被系統創建到名為“default”的namespace中。

使用namespace來組織kubernetes的各種對象,可以實現對用戶的分組,即“多租戶”管理。對不同的租房還可以進行單獨的資源配額設備和管理,使得整個集群配置非常靈活、方便。

Annotation(註解)

annotation與label類似,也使用key/value鍵值對的形式進行定義。Label具有嚴格的全名規則,它定義的是kubernetes對象的元數據(metadata),並且用於label selector。Annotation則是用戶任意定義的“附加”信息,以便於外部工具進行查找。

用annotation來記錄的信息包括: build信息、release信息、docker鏡像信息等,如時間戳、release id號、PR號、鏡像hash值、docker Controller地址等。

典型流程

以創建一個Pod為例,kubernetes典型的流程如下圖所示:

一文帶你看透kubernetes 容器編排系統

三.組件

Replication Controller

為了區分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 Controller負責發現、管理和監控集群中的各個node節點。Kubelet在啟動時通過API Server註冊節點信息,並定時向API Server發送節點信息。API Server接收到這些信息後,將這些信息寫入etcd。存入etcd的節點信息包括節點健康狀況、節點資源、節點名稱、節點地址信息、操作系統版本、docker版本、kubelet版本等。節點健康狀況包含“就緒(true)”、“未就緒(false)”和“未知(unknown)”三種。

一文帶你看透kubernetes 容器編排系統

(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等資源的信息。

ResourceQuota controller

作為容器集群的管理平臺, 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調度不會超出配額限制。

典型的資源控制流程如下圖所示:

一文帶你看透kubernetes 容器編排系統

namaspace controller

一文帶你看透kubernetes 容器編排系統

用戶通過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資源。

kubernetes安全控制

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

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的引用關係。

service controller&endpoint controller

一文帶你看透kubernetes 容器編排系統

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
}
]
},

四.功能特性

Service 集群訪問流程(服務發現)

一文帶你看透kubernetes 容器編排系統

在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(調度)

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鏡像,並啟動容器。

一文帶你看透kubernetes 容器編排系統

Scheduler(調度策略)

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 容器編排系統

節點註冊

在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秒。

Pod管理

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/”和“/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條目。


分享到:


相關文章: