深入解析Pod對象

現(xiàn)在戒幔,你已經(jīng)非常清楚:Kubernetes 項(xiàng)目中的最小編排單位是 Pod拌喉,而不是容器派诬。將這個設(shè)計落實(shí)到 API 對象上盟萨,容(Container)就成了 Pod 屬性里的一個普通的字段吝羞。那么兰伤,一個很自然的問題就是:到底哪些屬性屬于 Pod 對象,而又有哪些屬性屬于 Container 呢钧排?

要徹底理解這個問題敦腔,你就一定要牢記我在上一篇文章中提到的一個結(jié)論:Pod 扮演的是傳統(tǒng)部署環(huán)境里“虛擬機(jī)”的角色。這樣的設(shè)計恨溜,是為了使用戶從傳統(tǒng)環(huán)境(虛擬機(jī)環(huán)境)向 Kubernetes(容器環(huán)境)的遷移符衔,更加平滑。

而如果你能把 Pod 看成傳統(tǒng)環(huán)境里的“機(jī)器”糟袁、把容器看作是運(yùn)行在這個“機(jī)器”里的“用戶程序”判族,那么很多關(guān)于 Pod 對象的設(shè)計就非常容易理解了。

比如项戴,凡是調(diào)度五嫂、網(wǎng)絡(luò)、存儲肯尺,以及安全相關(guān)的屬性沃缘,基本上是 Pod 級別的。

這些屬性的共同特征是则吟,它們描述的是“機(jī)器”這個整體槐臀,而不是里面運(yùn)行的“程序”。比如氓仲,配置這個“機(jī)器”的網(wǎng)卡(即:Pod 的網(wǎng)絡(luò)定義)水慨,配置這個“機(jī)器”的磁盤(即:Pod 的存儲定義),配置這個“機(jī)器”的防火墻(即:Pod 的安全定義)敬扛。更不用說晰洒,這臺“機(jī)器”運(yùn)行在哪個服務(wù)器之上(即:Pod 的調(diào)度)。
接下來啥箭,我就先為你介紹 Pod 中幾個重要字段的含義和用法谍珊。

NodeSelector:是一個供用戶將 Pod 與 Node 進(jìn)行綁定的字段,用法如下所示:

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

這樣的一個配置急侥,意味著這個 Pod 永遠(yuǎn)只能運(yùn)行在攜帶了“disktype: ssd”標(biāo)簽(Label)的節(jié)點(diǎn)上砌滞;否則侮邀,它將調(diào)度失敗。

NodeName:一旦 Pod 的這個字段被賦值贝润,Kubernetes 項(xiàng)目就會被認(rèn)為這個 Pod 已經(jīng)經(jīng)過了調(diào)度绊茧,調(diào)度的結(jié)果就是賦值的節(jié)點(diǎn)名字。所以打掘,這個字段一般由調(diào)度器負(fù)責(zé)設(shè)置华畏,但用戶也可以設(shè)置它來“騙過”調(diào)度器,當(dāng)然這個做法一般是在測試或者調(diào)試的時候才會用到尊蚁。

HostAliases:定義了 Pod 的 hosts 文件(比如 /etc/hosts)里的內(nèi)容唯绍,用法如下:

apiVersion: v1
kind: Pod
...
spec:
  hostAliases:
  - ip: "10.1.2.3"
    hostnames:
    - "foo.remote"
    - "bar.remote"
...

在這個 Pod 的 YAML 文件中,我設(shè)置了一組 IP 和 hostname 的數(shù)據(jù)枝誊。這樣,這個 Pod 啟動后惜纸,/etc/hosts 文件的內(nèi)容將如下所示:

cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
...
10.244.135.10 hostaliases-pod
10.1.2.3 foo.remote
10.1.2.3 bar.remote

其中叶撒,最下面兩行記錄,就是我通過 HostAliases 字段為 Pod 設(shè)置的耐版。需要指出的是祠够,在 Kubernetes 項(xiàng)目中,如果要設(shè)置 hosts 文件里的內(nèi)容粪牲,一定要通過這種方法古瓤。否則,如果直接修改了 hosts 文件的話腺阳,在 Pod 被刪除重建之后落君,kubelet 會自動覆蓋掉被修改的內(nèi)容。
除了上述跟“機(jī)器”相關(guān)的配置外亭引,你可能也會發(fā)現(xiàn):
凡是跟容器的 Linux Namespace 相關(guān)的屬性绎速,也一定是 Pod 級別的。
這個原因也很容易理解:Pod 的設(shè)計焙蚓,就是要讓它里面的容器盡可能多地共享 Linux Namespace纹冤,僅保留必要的隔離和限制能力。這樣购公,Pod 模擬出的效果萌京,就跟虛擬機(jī)里程序間的關(guān)系非常類似了。
舉個例子宏浩,在下面這個 Pod 的 YAML 文件中知残,我定義了 shareProcessNamespace=true:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  shareProcessNamespace: true
  containers:
  - name: nginx
    image: nginx
  - name: shell
    image: busybox
    stdin: true
    tty: true

這就意味著這個 Pod 里的容器要共享 PID Namespace。
而在這個 YAML 文件中比庄,我還定義了兩個容器:一個是 nginx 容器橡庞,一個是開啟了 tty 和 stdin 的 shell 容器较坛。
在 Pod 的 YAML 文件里聲明開啟它們倆,其實(shí)等同于設(shè)置了 docker run 里的 -it(-i 即 stdin扒最,-t 即 tty)參數(shù)丑勤。
如果還是不太理解它們倆的作用的話,可以直接認(rèn)為 tty 就是 Linux 給用戶提供的一個常駐小程序吧趣,用于接收用戶的標(biāo)準(zhǔn)輸入法竞,返回操作系統(tǒng)的標(biāo)準(zhǔn)輸出。當(dāng)然强挫,為了能夠在 tty 中輸入信息岔霸,你還需要同時開啟 stdin(標(biāo)準(zhǔn)輸入流)。
于是俯渤,這個 Pod 被創(chuàng)建后呆细,你就可以使用 shell 容器的 tty 跟這個容器進(jìn)行交互了。我們一起實(shí)踐一下:

$ kubectl create -f nginx.yaml

接下來八匠,我們使用 kubectl attach 命令絮爷,連接到 shell 容器的 tty 上:

kubectl attach -it nginx -c shell

這樣,我們就可以在 shell 容器里執(zhí)行 ps 指令梨树,查看所有正在運(yùn)行的進(jìn)程:

$ kubectl attach -it nginx -c shell
/ # ps ax
PID   USER     TIME  COMMAND
    1 root      0:00 /pause
    8 root      0:00 nginx: master process nginx -g daemon off;
   14 101       0:00 nginx: worker process
   15 root      0:00 sh
   21 root      0:00 ps ax

可以看到坑夯,在這個容器里,我們不僅可以看到它本身的 ps ax 指令抡四,還可以看到 nginx 容器的進(jìn)程柜蜈,以及 Infra 容器的 /pause 進(jìn)程。這就意味著指巡,整個 Pod 里的每個容器的進(jìn)程淑履,對于所有容器來說都是可見的:它們共享了同一個 PID Namespace。

類似地藻雪,凡是 Pod 中的容器要共享宿主機(jī)的 Namespace鳖谈,也一定是 Pod 級別的定義,比如:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostNetwork: true
  hostIPC: true
  hostPID: true
  containers:
  - name: nginx
    image: nginx
  - name: shell
    image: busybox
    stdin: true
    tty: true

在這個 Pod 中阔涉,我定義了共享宿主機(jī)的 Network缆娃、IPC 和 PID Namespace。這就意味著瑰排,這個 Pod 里的所有容器贯要,會直接使用宿主機(jī)的網(wǎng)絡(luò)、直接與宿主機(jī)進(jìn)行 IPC 通信椭住、看到宿主機(jī)里正在運(yùn)行的所有進(jìn)程崇渗。

當(dāng)然,除了這些屬性,Pod 里最重要的字段當(dāng)屬“Containers”了宅广。而在上一篇文章中葫掉,我還介紹過“Init Containers”。其實(shí)跟狱,這兩個字段都屬于 Pod 對容器的定義俭厚,內(nèi)容也完全相同,只是 Init Containers 的生命周期驶臊,會先于所有的 Containers挪挤,并且嚴(yán)格按照定義的順序執(zhí)行。

Kubernetes 項(xiàng)目中對 Container 的定義关翎,和 Docker 相比并沒有什么太大區(qū)別扛门。我在前面的容器技術(shù)概念入門系列文章中,和你分享的 Image(鏡像)纵寝、Command(啟動命令)论寨、workingDir(容器的工作目錄)、Ports(容器要開發(fā)的端口)爽茴,以及 volumeMounts(容器要掛載的 Volume)都是構(gòu)成 Kubernetes 項(xiàng)目中 Container 的主要字段葬凳。不過在這里,還有這么幾個屬性值得你額外關(guān)注闹啦。

首先,是 ImagePullPolicy 字段辕坝。它定義了鏡像拉取的策略窍奋。而它之所以是一個 Container 級別的屬性,是因?yàn)槿萜麋R像本來就是 Container 定義中的一部分酱畅。

ImagePullPolicy 的值默認(rèn)是 Always琳袄,即每次創(chuàng)建 Pod 都重新拉取一次鏡像。另外纺酸,當(dāng)容器的鏡像是類似于 nginx 或者 nginx:latest 這樣的名字時窖逗,ImagePullPolicy 也會被認(rèn)為 Always。
最新版本 v1.16 默認(rèn)值是 IfNotPresent

https://kubernetes.io/docs/concepts/containers/images/

而如果它的值被定義為 Never 或者 IfNotPresent餐蔬,則意味著 Pod 永遠(yuǎn)不會主動拉取這個鏡像碎紊,或者只在宿主機(jī)上不存在這個鏡像時才拉取。

其次樊诺,是 Lifecycle 字段仗考。它定義的是 Container Lifecycle Hooks。顧名思義词爬,Container Lifecycle Hooks 的作用秃嗜,是在容器狀態(tài)發(fā)生變化時觸發(fā)一系列“鉤子”。我們來看這樣一個例子:

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]

    preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]

這是一個來自 Kubernetes 官方文檔的 Pod 的 YAML 文件。它其實(shí)非常簡單锅锨,只是定義了一個 nginx 鏡像的容器叽赊。不過,在這個 YAML 文件的容器(Containers)部分必搞,你會看到這個容器分別設(shè)置了一個 postStart 和 preStop 參數(shù)必指。這是什么意思呢?

先說 postStart 吧顾画。它指的是取劫,在容器啟動后,立刻執(zhí)行一個指定的操作研侣。需要明確的是谱邪,postStart 定義的操作,雖然是在 Docker 容器 ENTRYPOINT 執(zhí)行之后庶诡,但它并不嚴(yán)格保證順序惦银。也就是說末誓,在 postStart 啟動時扯俱,ENTRYPOINT 有可能還沒有結(jié)束。

當(dāng)然喇澡,如果 postStart 執(zhí)行超時或者錯誤迅栅,Kubernetes 會在該 Pod 的 Events 中報出該容器啟動失敗的錯誤信息,導(dǎo)致 Pod 也處于失敗的狀態(tài)晴玖。

而類似地读存,preStop 發(fā)生的時機(jī),則是容器被殺死之前(比如呕屎,收到了 SIGKILL 信號)让簿。而需要明確的是,preStop 操作的執(zhí)行秀睛,是同步的尔当。所以,它會阻塞當(dāng)前的容器殺死流程蹂安,直到這個 Hook 定義操作完成之后椭迎,才允許容器被殺死,這跟 postStart 不一樣田盈。

所以侠碧,在這個例子中,我們在容器成功啟動之后缠黍,在 /usr/share/message 里寫入了一句“歡迎信息”(即 postStart 定義的操作)弄兜。而在這個容器被刪除之前,我們則先調(diào)用了 nginx 的退出指令(即 preStop 定義的操作),從而實(shí)現(xiàn)了容器的“優(yōu)雅退出”替饿。

在熟悉了 Pod 以及它的 Container 部分的主要字段之后语泽,我再和你分享一下這樣一個的 Pod 對象在 Kubernetes 中的生命周期。

Pod 生命周期的變化视卢,主要體現(xiàn)在 Pod API 對象的 Status 部分踱卵,這是它除了 Metadata 和 Spec 之外的第三個重要字段。其中据过,pod.status.phase惋砂,就是 Pod 的當(dāng)前狀態(tài),它有如下幾種可能的情況:
1
Pending绳锅。這個狀態(tài)意味著西饵,Pod 的 YAML 文件已經(jīng)提交給了 Kubernetes,API 對象已經(jīng)被創(chuàng)建并保存在 Etcd 當(dāng)中鳞芙。但是眷柔,這個 Pod 里有些容器因?yàn)槟撤N原因而不能被順利創(chuàng)建。比如原朝,調(diào)度不成功驯嘱。
2
Running。這個狀態(tài)下喳坠,Pod 已經(jīng)調(diào)度成功鞠评,跟一個具體的節(jié)點(diǎn)綁定。它包含的容器都已經(jīng)創(chuàng)建成功壕鹉,并且至少有一個正在運(yùn)行中剃幌。
3
Succeeded。這個狀態(tài)意味著御板,Pod 里的所有容器都正常運(yùn)行完畢锥忿,并且已經(jīng)退出了牛郑。這種情況在運(yùn)行一次性任務(wù)時最為常見怠肋。
4
Failed。這個狀態(tài)下淹朋,Pod 里至少有一個容器以不正常的狀態(tài)(非 0 的返回碼)退出笙各。這個狀態(tài)的出現(xiàn),意味著你得想辦法 Debug 這個容器的應(yīng)用础芍,比如查看 Pod 的 Events 和日志杈抢。
5
Unknown。這是一個異常狀態(tài)仑性,意味著 Pod 的狀態(tài)不能持續(xù)地被 kubelet 匯報給 kube-apiserver惶楼,這很有可能是主從節(jié)點(diǎn)(Master 和 Kubelet)間的通信出現(xiàn)了問題。

更進(jìn)一步地,Pod 對象的 Status 字段歼捐,還可以再細(xì)分出一組 Conditions何陆。這些細(xì)分狀態(tài)的值包括:PodScheduled、Ready豹储、Initialized贷盲,以及 Unschedulable。它們主要用于描述造成當(dāng)前 Status 的具體原因是什么剥扣。

比如巩剖,Pod 當(dāng)前的 Status 是 Pending,對應(yīng)的 Condition 是 Unschedulable钠怯,這就意味著它的調(diào)度出現(xiàn)了問題佳魔。
而其中,Ready 這個細(xì)分狀態(tài)非常值得我們關(guān)注:它意味著 Pod 不僅已經(jīng)正常啟動(Running 狀態(tài))呻疹,而且已經(jīng)可以對外提供服務(wù)了吃引。這兩者之間(Running 和 Ready)是有區(qū)別的,你不妨仔細(xì)思考一下刽锤。

Pod 的這些狀態(tài)信息镊尺,是我們判斷應(yīng)用運(yùn)行情況的重要標(biāo)準(zhǔn),尤其是 Pod 進(jìn)入了非“Running”狀態(tài)后并思,你一定要能迅速做出反應(yīng)庐氮,根據(jù)它所代表的異常情況開始跟蹤和定位,而不是去手忙腳亂地查閱文檔宋彼。

實(shí)際上弄砍,Pod API 對象是整個 Kubernetes 體系中最核心的一個概念,也是后面講解各種控制器時都要用到的输涕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載音婶,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末莱坎,一起剝皮案震驚了整個濱河市衣式,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌檐什,老刑警劉巖碴卧,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異乃正,居然都是意外死亡住册,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門瓮具,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荧飞,“玉大人凡人,你說我怎么就攤上這事√纠” “怎么了划栓?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長条获。 經(jīng)常有香客問我忠荞,道長,這世上最難降的妖魔是什么帅掘? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任委煤,我火速辦了婚禮,結(jié)果婚禮上修档,老公的妹妹穿的比我還像新娘碧绞。我一直安慰自己,他們只是感情好吱窝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布讥邻。 她就那樣靜靜地躺著,像睡著了一般院峡。 火紅的嫁衣襯著肌膚如雪兴使。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天照激,我揣著相機(jī)與錄音发魄,去河邊找鬼。 笑死俩垃,一個胖子當(dāng)著我的面吹牛励幼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播口柳,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苹粟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了跃闹?” 一聲冷哼從身側(cè)響起嵌削,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辣卒,沒想到半個月后掷贾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睛榄,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荣茫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了场靴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啡莉。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡港准,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咧欣,到底是詐尸還是另有隱情浅缸,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布魄咕,位于F島的核電站衩椒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏哮兰。R本人自食惡果不足惜毛萌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喝滞。 院中可真熱鬧阁将,春花似錦、人聲如沸右遭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窘哈。三九已至吹榴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滚婉,已是汗流浹背腊尚。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留满哪,地道東北人婿斥。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像哨鸭,于是被迫代替她去往敵國和親民宿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容