K8S 實(shí)戰(zhàn)(三)| Pod 的本質(zhì)

前言

上一節(jié)發(fā)布了一個(gè)容器到 K8S 中,但其實(shí)實(shí)際操作的是 Pod 芯杀,那么為什么是 Pod,而不是容器。

更新歷史

Pod 的本質(zhì)

Pod 包裝了一個(gè)或多個(gè)容器边篮。
Pod 是 K8S 的最小執(zhí)行單元。
Pod 是 K8S 中的一個(gè)進(jìn)程奏甫。
Pod 可包裝 Docker戈轿,也支持包裝其他類型容器。
Pod 包含封裝的容器阵子、存儲(chǔ)資源思杯、網(wǎng)絡(luò)資源、以及指導(dǎo)容器如何運(yùn)行的配置挠进。

可以把容器理解為一個(gè)無(wú)掛鉤的光禿禿的集裝箱色乾,K8S 這艘大船無(wú)法直接掛載它,通過(guò)給集裝箱(容器)加裝掛鉤(IP地址)等形成一個(gè) Pod领突,方便 K8S 來(lái)操作暖璧。

也可以把 Pod 理解為傳統(tǒng)的虛擬機(jī),而容器是傳統(tǒng)虛擬機(jī)中運(yùn)行的程序君旦,只不過(guò)虛擬機(jī)是一個(gè)實(shí)體澎办,而 Pod 是一個(gè)邏輯概念。

K8S 通過(guò)編排 Pod 來(lái)調(diào)度容器金砍,而不是直接操作容器局蚀,K8S 無(wú)法直接操縱容器。

Pod 中的共享資源

Pod 為其中運(yùn)行的多容器提供共享的網(wǎng)絡(luò)恕稠、存儲(chǔ)資源琅绅、命名空間。

網(wǎng)絡(luò)

Pod 具有唯一 IP 地址谱俭,Pod 中的多個(gè)容器共享一個(gè) IP 地址和網(wǎng)絡(luò)端口等網(wǎng)絡(luò)資源
Pod 中多容器可使用 localhost 通信
Pod 中容器和外部通信時(shí)候奉件,多容器需要協(xié)調(diào)網(wǎng)絡(luò)端口
Pod 中的容器獲取的系統(tǒng)主機(jī)名與為 Pod 配置的 name 相同

存儲(chǔ)

Pod 可指定一組存儲(chǔ)卷
Pod 中多容器均可以訪問(wèn)該存儲(chǔ)卷宵蛀,以便互相共享數(shù)據(jù)
Pod 中的共享卷可以持久保存,防止容器重啟丟失數(shù)據(jù)

Pod 的特點(diǎn)

如果使用 kind: Pod 的 yaml 文件來(lái)創(chuàng)建 Pod县貌,當(dāng)前節(jié)點(diǎn)服務(wù)器出現(xiàn)問(wèn)題后术陶,Pod 不能被自動(dòng)調(diào)度到其他可用服務(wù)器。

一般使用 kind: Deployment 的 yaml 來(lái)創(chuàng)建 Pod煤痕。

Deployment 是一種控制器梧宫,可以用來(lái)創(chuàng)建、管理 Pod摆碉。如創(chuàng)建多副本 Pod塘匣,滾動(dòng)更新 Pod。

當(dāng) Pod 所在節(jié)點(diǎn)出現(xiàn)問(wèn)題巷帝,Deployment 控制器可以在集群中其他節(jié)點(diǎn)啟動(dòng)新 Pod忌卤。

Pod 模板

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']

鏡像拉取策略

不具體指定的情況下,imagePullPolicy 是 Always楞泼,即 kubelet 會(huì)嘗試從指定的倉(cāng)庫(kù)拉取每個(gè)鏡像驰徊。
如果容器屬性 imagePullPolicy 設(shè)置為 IfNotPresent , 則會(huì)優(yōu)先使用本地鏡像堕阔。
如果容器屬性 imagePullPolicy 設(shè)置為 IfNotPresent Never棍厂, 則會(huì)一定使用本地鏡像。

apiVersion: v1
kind: Pod
metadata:
  name: private-image-test-1
spec:
  containers:
    - name: uses-private-image
      image: nginx
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]

Pod 常用參數(shù)

NodeSelector

功能:將 Pod 與 Node 綁定

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

該 Pod 只能運(yùn)行在攜帶了“disktype:ssd”標(biāo)簽(Label)的節(jié)點(diǎn)上超陆,如果沒(méi)有這種標(biāo)簽的節(jié)點(diǎn)牺弹,調(diào)度將失敗。

NodeName

該字段一般由調(diào)度器設(shè)置时呀,但我們測(cè)試時(shí)候可以手工設(shè)置該字段张漂,讓調(diào)度器認(rèn)為該 Pod 已經(jīng)被調(diào)度過(guò)了。

HostAliase

給 Pod 里各容器的 /etc/hosts 文件設(shè)置內(nèi)容

apiVersion: v1
kind: Pod
......
spec:
  hostAliases:
  - ip: "10.20.20.20"
    hostnames:
    - "test1.com"
    - "test2.com"

進(jìn)容器檢查一下

[root@master01 ~]# kubectl exec -it nginx -- bash
root@nginx:/# cat /etc/hosts
......
# Entries added by HostAliases.
10.20.20.20     test1.com       test2.com

shareProcessNamespace

定義參數(shù) shareProcessNamespace=true退唠,那么該 Pod 中所有容器將共享 PID Namespace

創(chuàng)建一個(gè)包含兩個(gè)容器的 Pod

[root@master01 ~]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  shareProcessNamespace: true
  containers:
  - name: nginx
    image: nginx
  - name: shell
    image: busybox
    stdin: true
    tty: true

查看運(yùn)行情況

[root@master01 ~]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP               NODE     NOMINATED NODE   READINESS GATES
nginx   2/2     Running   0          117s   192.10.137.131   work03   <none>           <none>

進(jìn)入到 Pod nginx 中的名為 shell 的容器中

[root@master01 ~]# kubectl attach -it nginx -c shell
If you don't see a command prompt, try pressing enter.
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /pause
    6 root      0:00 nginx: master process nginx -g daemon off;
   33 101       0:00 nginx: worker process
   34 root      0:00 sh
   39 root      0:00 ps aux

可以看到鹃锈,shell 容器中可以看到 nginx 容器的進(jìn)程

Pod 的預(yù)設(shè)參數(shù) PodPreset

我們可以預(yù)先設(shè)置好一些通用的配置,當(dāng)用戶提交自己的個(gè)性化 Pod 配置時(shí)瞧预,PodPreset 就可以自動(dòng)附加通用配置到對(duì)應(yīng)的 Pod 上屎债。

PodPreset 里定義的內(nèi)容,只會(huì)在 Pod API 對(duì)象被創(chuàng)建之前追加在這個(gè)對(duì)象本身 上垢油,而不會(huì)影響任何 Pod 的控制器的定義盆驹。

比如,我們現(xiàn)在提交的是一個(gè) nginx-deployment滩愁,那么這個(gè) Deployment 對(duì)象本身是永遠(yuǎn)不會(huì)被 PodPreset 改變的躯喇,被修改的只是這個(gè) Deployment 創(chuàng)建出來(lái)的所有 Pod。

未啟用 PodPreset 特性時(shí)

# kubectl get podpresets
error: the server doesn't have a resource type "podpresets"

啟用 PodPreset 特性

修改
[/etc/kubernetes/manifests/kube-apiserver.yaml] 
中的
spec.containers.command: 
修改原
- --runtime-config=api/all=true
為
- --runtime-config=api/all=true,settings.k8s.io/v1alpha1=true
新加一行
- --enable-admission-plugins=PodPreset

3臺(tái)MASTER均執(zhí)行重啟 kubelet
systemctl restart kubelet

預(yù)設(shè)值配置 preset.yaml

apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-tz-env
spec:
  selector:
    matchLabels:
  env:
    - name: TZ
      value: Asia/Shanghai

Pod配置 nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx

創(chuàng)建 PodPreset

# kubectl get podpreset
No resources found in default namespace.

# kubectl apply -f podpreset.yaml
podpreset.settings.k8s.io/allow-tz-env created

# kubectl get podpreset
NAME           CREATED AT
allow-tz-env

創(chuàng)建 Pod

[root@master01 ~]# kubectl apply -f nginx.yaml 
pod/nginx created

查看該 Pod 是否被注入

# kubectl get pod nginx -o yaml 
...省略
spec:
  containers:
  - env:
    - name: TZ
      value: Asia/Shanghai
    image: nginx
    imagePullPolicy: Always
    name: nginx
    resources: {}
...省略

可以看到 Pod 被注入了名為 TZ 的 env

Init 容器

特點(diǎn)

  1. Init 容器在 Pod 內(nèi)應(yīng)用容器啟動(dòng)之前運(yùn)行。
  2. 一個(gè) Pod 可以有一個(gè)或多個(gè) Init 容器廉丽。
  3. 每個(gè) Init 容器運(yùn)行必須完成倦微。
  4. 如果 Init 容器運(yùn)行失敗,K8S 會(huì)不斷重啟該 Pod正压,直到 Init 容器運(yùn)行成功欣福。
  5. 但如果 Pod 對(duì)應(yīng)的 restartPolicy 值為 Never,它不會(huì)重新啟動(dòng)焦履。
  6. 如果一個(gè) Pod 有多個(gè) Init 容器拓劝,這些容器會(huì)按順序逐個(gè)運(yùn)行。每個(gè) Init 容器必須運(yùn)行成功嘉裤,下一個(gè)才能夠運(yùn)行郑临。
  7. Init 容器可以包含一些安裝過(guò)程中應(yīng)用容器中不存在的實(shí)用工具或個(gè)性化代碼。例如屑宠,沒(méi)有必要僅為了在安裝過(guò)程中使用類似 sed厢洞、 awk、 python 或 dig 這樣的工具而去FROM 一個(gè)鏡像來(lái)生成一個(gè)新的鏡像典奉。
  8. Init 容器可以安全地運(yùn)行這些工具犀变,避免這些工具導(dǎo)致應(yīng)用鏡像的安全性降低。
  9. 應(yīng)用鏡像的創(chuàng)建者和部署者可以各自獨(dú)立工作秋柄,而沒(méi)有必要聯(lián)合構(gòu)建一個(gè)單獨(dú)的應(yīng)用鏡像。
  10. Init 容器能以不同于 Pod 內(nèi)應(yīng)用容器的文件系統(tǒng)視圖運(yùn)行蠢正。因此骇笔,Init容器可具有訪問(wèn) Secrets 的權(quán)限,而應(yīng)用容器不能夠訪問(wèn)嚣崭。
  11. 由于 Init 容器必須在應(yīng)用容器啟動(dòng)之前運(yùn)行完成笨触,因此 Init 容器提供了一種機(jī)制來(lái)阻塞或延遲應(yīng)用容器的啟動(dòng),直到滿足了一組先決條件雹舀。一旦前置條件滿足芦劣,Pod 內(nèi)的所有的應(yīng)用容器會(huì)并行啟動(dòng)。
  12. 在所有的 Init 容器沒(méi)有成功之前说榆,Pod 將不會(huì)變成 Ready 狀態(tài)虚吟。
  13. Init 容器鏡像的變更會(huì)引起 Pod 重啟, 應(yīng)用容器鏡像的變更僅會(huì)重啟應(yīng)用容器签财。
  14. Pod 中每一個(gè)容器副本啟動(dòng)之前串慰,都會(huì)執(zhí)行一遍 Init 容器。

如何使用

  1. 定義一個(gè)具有 2 個(gè) Init 容器的 Pod唱蒸。
  2. init 容器為 myservice 和 mydb邦鲫。 這兩個(gè) Init 容器都啟動(dòng)完成,Pod 才能啟動(dòng) spec 區(qū)域中的應(yīng)用容器 myapp-container

創(chuàng)建 Pod 的 YAML 文件:

cat myapp.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

創(chuàng)建 mydb 和 myservice 兩個(gè) Service 的 YAML 文件:

cat myservice.yaml

kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

要啟動(dòng)這個(gè) Pod神汹,可以執(zhí)行如下命令:

kubectl apply -f myapp.yaml
pod/myapp-pod created

檢查其狀態(tài):

kubectl get -f myapp.yaml
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

使用下面命令查看更詳細(xì)的信息:

kubectl describe -f myapp.yaml

Name:          myapp-pod
Namespace:     default
[...]
Labels:        app=myapp
Status:        Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Containers:
  myapp-container:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]

查看Pod內(nèi) Init 容器的日志

$ kubectl logs myapp-pod -c init-myservice
$ kubectl logs myapp-pod -c init-mydb

此時(shí)庆捺,Init 容器將會(huì)等待直到發(fā)現(xiàn)名稱為mydb和myservice的 Service古今。

創(chuàng)建mydb和myservice的 service:

$ kubectl create -f services.yaml
service "myservice" created
service "mydb" created

可以看到這些 Init 容器執(zhí)行完畢,隨后my-app的Pod轉(zhuǎn)移進(jìn)入 Running 狀態(tài):

$ kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

只有我們啟動(dòng)了 mydb 和 myservice 這兩個(gè) Service滔以,Init 容器完成捉腥,myapp-pod 才能被創(chuàng)建。

Debug Pod

如果 Pod 被終止醉者,可通過(guò)如下命令查看原因

kubectl describe pod pod名稱

kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}'  pod名稱

結(jié)束語(yǔ)

Pod 包裝了容器但狭,K8S 通過(guò)操作 Pod 來(lái)操作容器。

Pod 可以包含多個(gè)應(yīng)用容器和多個(gè) Init 容器撬即。

人工直接創(chuàng)建的 Pod 在服務(wù)器節(jié)點(diǎn)故障時(shí)立磁,沒(méi)有自愈能力,需要使用控制器來(lái)解決這個(gè)問(wèn)題剥槐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末唱歧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子粒竖,更是在濱河造成了極大的恐慌颅崩,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蕊苗,死亡現(xiàn)場(chǎng)離奇詭異沿后,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)朽砰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)尖滚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瞧柔,你說(shuō)我怎么就攤上這事漆弄。” “怎么了造锅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵撼唾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我哥蔚,道長(zhǎng)倒谷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任肺素,我火速辦了婚禮恨锚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘倍靡。我一直安慰自己猴伶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著他挎,像睡著了一般筝尾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上办桨,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天筹淫,我揣著相機(jī)與錄音,去河邊找鬼呢撞。 笑死损姜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的殊霞。 我是一名探鬼主播摧阅,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼绷蹲!你這毒婦竟也來(lái)了棒卷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祝钢,失蹤者是張志新(化名)和其女友劉穎比规,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拦英,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜒什,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疤估。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吃谣。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖做裙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肃晚,我是刑警寧澤锚贱,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站关串,受9級(jí)特大地震影響拧廊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晋修,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一吧碾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧墓卦,春花似錦倦春、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尿庐。三九已至,卻和暖如春呢堰,著一層夾襖步出監(jiān)牢的瞬間抄瑟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工枉疼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留皮假,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓骂维,卻偏偏與公主長(zhǎng)得像惹资,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子席舍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354