學(xué)習(xí)本節(jié)內(nèi)容之前,希望你已經(jīng)對Kubernetes有了初步的概念。具體請參考這篇文章:
Pod是Kubernetes調(diào)度的最小單元。一個(gè)Pod可以包含一個(gè)或多個(gè)容器,因此它可以被看作是內(nèi)部容器的邏輯宿主機(jī)。Pod的設(shè)計(jì)理念是為了支持多個(gè)容器在一個(gè)Pod中共享網(wǎng)絡(luò)和文件系統(tǒng)。因此處于一個(gè)Pod中的多個(gè)容器共享以下資源:
- PID命名空間:Pod中不同的應(yīng)用程序可以看到其他應(yīng)用程序的進(jìn)程ID。
- network命名空間:Pod中多個(gè)容器處于同一個(gè)網(wǎng)絡(luò)命名空間,因此能夠訪問的IP和端口范圍都是相同的。也可以通過localhost相互訪問。
- IPC命名空間:Pod中的多個(gè)容器共享Inner-process Communication命名空間,因此可以通過SystemV IPC或POSIX進(jìn)行進(jìn)程間通信。
UTS命名空間:Pod中的多個(gè)容器共享同一個(gè)主機(jī)名。
Volumes:Pod中各個(gè)容器可以共享在Pod中定義分存儲卷(Volume)。
Pod,容器與Node(工作主機(jī))之間的關(guān)系如下圖所示:
1. Pod的定義
通過yaml文件或者json描述Pod和其內(nèi)容器的運(yùn)行環(huán)境和期望狀態(tài),例如一個(gè)最簡單的運(yùn)行nginx應(yīng)用的pod,定義如下:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
在生產(chǎn)環(huán)境中,推薦使用諸如Deployment,StatefulSet,Job或者CronJob等控制器來創(chuàng)建Pod,而不是直接創(chuàng)建。
將上述pod描述文件保存為nginx-pod.yaml,使用kubectl apply命令運(yùn)行pod
kubectl apply -f nginx-pod.yaml
下面簡要分析一下上面的Pod定義文件:
- apiVersion: 使用哪個(gè)版本的Kubernetes API來創(chuàng)建此對象
- kind:要?jiǎng)?chuàng)建的對象類型,例如Pod,Deployment等
- metadata:用于唯一區(qū)分對象的元數(shù)據(jù),包括:name,UID和namespace
- labels:是一個(gè)個(gè)的key/value對,定義這樣的label到Pod后,其他控制器對象可以通過這樣的label來定位到此Pod,從而對Pod進(jìn)行管理。(參見Deployment等控制器對象)
- spec: 其它描述信息,包含Pod中運(yùn)行的容器,容器中運(yùn)行的應(yīng)用等等。不同類型的對象擁有不同的spec定義。詳情參見API文檔:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/
Kubernetes在每個(gè)Pod啟動(dòng)時(shí),會自動(dòng)創(chuàng)建一個(gè)鏡像為gcr.io/google_containers/pause:version的容器,所有處于該P(yáng)od中的容器在啟動(dòng)時(shí)都會添加諸如
--net=container:pause --ipc=contianer:pause --pid=container:pause的啟動(dòng)參數(shù),因此pause容器成為Pod內(nèi)共享命名空間的基礎(chǔ)。所有容器共享pause容器的IP地址,也被稱為Pod IP。
如果我們希望從外部訪問這nginx應(yīng)用,那么我們還需要?jiǎng)?chuàng)建Service對象來暴露IP和port。具體請參考后面的這篇文章:Kubernetes對象之Service
2. Pod的生命周期
Pod的生命周期是Replication Controller進(jìn)行管理的。一個(gè)Pod的生命周期過程包括:
- 通過yaml或json對Pod進(jìn)行描述
- apiserver(運(yùn)行在Master主機(jī))收到創(chuàng)建Pod的請求后,將此Pod對象的定義存儲在etcd中
- scheduler(運(yùn)行在Master主機(jī))將此Pod分配到Node上運(yùn)行
- Pod內(nèi)所有容器運(yùn)行結(jié)束后此Pod也結(jié)束
在整個(gè)過程中,Pod通常處于以下的五種階段之一:
- Pending:Pod定義正確,提交到Master,但其所包含的容器鏡像還未完全創(chuàng)建。通常,Master對Pod進(jìn)行調(diào)度需要一些時(shí)間,Node進(jìn)行容器鏡像的下載也需要一些時(shí)間,啟動(dòng)容器也需要一定時(shí)間。(寫數(shù)據(jù)到etcd,調(diào)度,pull鏡像,啟動(dòng)容器)。
- Running:Pod已經(jīng)被分配到某個(gè)Node上,并且所有的容器都被創(chuàng)建完畢,至少有一個(gè)容器正在運(yùn)行中,或者有容器正在啟動(dòng)或重啟中。
- Succeeded:Pod中所有的容器都成功運(yùn)行結(jié)束,并且不會被重啟。這是Pod的一種最終狀態(tài)。
- Failed:Pod中所有的容器都運(yùn)行結(jié)束了,其中至少有一個(gè)容器是非正常結(jié)束的(exit code不是0)。這也是Pod的一種最終狀態(tài)。
- Unknown:無法獲得Pod的狀態(tài),通常是由于無法和Pod所在的Node進(jìn)行通信。
2.1 Restart policy
定義Pod時(shí),可以指定restartPolicy字段,表明此Pod中的容器在何種條件下會重啟。restartPolicy擁有三個(gè)候選值:
- Always:只要退出就重啟
- OnFailure:失敗退出時(shí)(exit code不為0)才重啟
- Never:永遠(yuǎn)不重啟
2.2 通過controller管理Pod
Pod本身不具備容錯(cuò)性,這意味著如果Pod運(yùn)行的Node宕機(jī)了,那么該P(yáng)od無法恢復(fù)。因此推薦使用Deployment等控制器來創(chuàng)建Pod并管理。
一般來說,Pod不會自動(dòng)消失,只能手動(dòng)銷毀或者被預(yù)先定義好的controller銷毀。但有一種特殊情況,當(dāng)Pod處于Succeeded或Failed階段,并且超過一定時(shí)間后(由master決定),會觸發(fā)超時(shí)過期從而被銷毀。
總體上來說,Kubernetes中擁有三種類型的controller:
- Job。通常用于管理一定會結(jié)束的Pod。如果希望Pod被Job controller管理,那么restartPolicy必須指定為OnFailure或Never。
- ReplicationController,ReplicaSet和Deployment。用于管理永遠(yuǎn)處于運(yùn)行狀態(tài)的Pod。如果希望Pod被此類controller管理,那么restartPolicy必須指定為Always。
- DaemonSet。它能夠保證你的Pod在每一臺Node都運(yùn)行一個(gè)副本。