kubernetes (k8s)容器編排系統

天府雲創發表於2019-01-15

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

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

一. 系統架構

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

img

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做轉發。

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

img

二.基本概念

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典型的流程如下圖所示:

img

三.元件

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)”三種。

img

(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排程不會超出配額限制。

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

img

namaspace controller

img

使用者通過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

img

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 叢集訪問流程(服務發現)

img

在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映象,並啟動容器。

img

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管理、容器健康檢查、資源監控等部分。

img

節點註冊

在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/<當前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條目。

參考

《kubernetes權威指南》

相關文章