kubernetes 學(xué)習(xí)實(shí)踐 -- pod

云原生現(xiàn)在是炙手可熱的技術(shù),而這里面最核心的當(dāng)屬大名鼎鼎的Kubernetes;K8S號(hào)稱是未來時(shí)代的操作系統(tǒng),是云原生時(shí)代IT工程師必備的技能。

學(xué)習(xí)應(yīng)當(dāng)有輸出,下面是對(duì)pod相關(guān)知識(shí)的學(xué)習(xí)


pod 的一些基礎(chǔ)概念:

pod是K8S中最小的調(diào)度單位,那么為啥不是docker容器呢?答案可能是從最開始K8S就沒有將容器作為架構(gòu)的核心,正如K8S的前身--Google的Borg系統(tǒng)研究人員提出的:

運(yùn)行在大規(guī)模集群中的各種任務(wù)之間,實(shí)際上存在各種各樣的關(guān)系。這些關(guān)系的處理,才是作業(yè)編排和管理系統(tǒng)最困難的地方

pod扮演的是傳統(tǒng)部署環(huán)境中“虛擬機(jī)”的角色,而容器則是這個(gè)“虛擬機(jī)”中運(yùn)行的用戶程序。

pod只是一個(gè)邏輯概念,K8S真正處理的是宿主機(jī)OS上容器的namespace和cgroups,并不存在所謂的pod邊界或者隔離,pod內(nèi)部是有一個(gè)infra容器存在的,它是pod內(nèi)的第一個(gè)容器。

infra容器是一個(gè)用匯編語言編寫的,永遠(yuǎn)處于“暫停”狀態(tài)的容器,大小只有幾百KB,舉例:

image

pod的生命周期,只跟其內(nèi)部的infra容器有關(guān)系,而與其他容器無關(guān);infra容器永遠(yuǎn)是第一個(gè)被創(chuàng)建的容器

pod是一組共享了某些資源的容器,這些容器可共享的資源有: 網(wǎng)絡(luò)namespace、pv卷、security context

用戶定義的容器,則可通過join network namespace的方式與infra容器關(guān)聯(lián)一起;對(duì)同一個(gè)pod里的所有用戶來講,進(jìn)出的流量都可認(rèn)為是通過infra容器完成的。

對(duì)于volume,K8S只需要把volume的定義設(shè)計(jì)在pod層級(jí)即可,一個(gè)volume對(duì)應(yīng)的宿主機(jī)目錄對(duì)于pod來說就只有一個(gè),pod里的容器只要聲明掛載這個(gè)volume,就可以共享這個(gè)volume對(duì)應(yīng)的宿主機(jī)目錄。

pod內(nèi)部容器之間的超親密關(guān)系,形成了sidecar模式,即容器設(shè)計(jì)模式,常見的場(chǎng)景包括日志收集、通信適配等,而這也是service mesh項(xiàng)目如istio微服務(wù)治理的原理。

pod相關(guān)的屬性:

pod級(jí)別的屬性應(yīng)該是如下所描述的屬性:

  • 和調(diào)度、網(wǎng)絡(luò)、存儲(chǔ)、安全相關(guān)的屬性
  • 和容器linux namespace相關(guān)的屬性
  • 容器要共享宿主機(jī)的namespace,也一定是pod級(jí)別的定義

pod的四大類屬性(應(yīng)該是API對(duì)象的四大類屬性),及每個(gè)大類里常見的子屬性:

  • typemeta: 最基本的定義
    • Group
    • Kind
    • Version
  • metadata:內(nèi)有2個(gè)最重要的屬性,即namespace和name,它倆可唯一確定某個(gè)對(duì)象實(shí)例;其余常見的字段還有
    • Label
    • Annotation
    • Finalizer
    • ResourceVersion
  • spec : 核心屬性,每個(gè)對(duì)象獨(dú)有,用戶的期望狀態(tài),由創(chuàng)建對(duì)象的用戶端來定義
  • status : 核心屬性,每個(gè)對(duì)象獨(dú)有,對(duì)象的實(shí)際狀態(tài),由對(duì)應(yīng)的控制器收集狀態(tài)并更新

pod的status狀態(tài):

  • pending :api對(duì)象已創(chuàng)建在etcd中,pod里的有些容器因?yàn)槟撤N原因無法順利創(chuàng)建

  • running :至少有一個(gè)容器已經(jīng)在運(yùn)行了

  • succeeded :pod里的所有容器都跑完且退出,在運(yùn)行job任務(wù)時(shí)常見

  • failed :至少有一個(gè)容器是不正常的狀態(tài)

  • unknown :異常狀態(tài),pod狀態(tài)無法被kubelet匯報(bào)給kube-apiserver,比如從節(jié)點(diǎn)掛了

  • CrashLoopBackOff :比如拉鏡像失敗

對(duì)于pod的狀態(tài)并不需要死記硬背,記住下面兩個(gè)原理即可:

  • 只要pod的restartPolicy指定的策略允許重啟異常容器(eg:always),那么這個(gè)pod就會(huì)保持running狀態(tài),并進(jìn)行容器重啟; 否則就會(huì)進(jìn)入failed狀態(tài)

  • 對(duì)于包含多個(gè)容器的pod,只有它里面所有容器都進(jìn)入異常狀態(tài),pod才會(huì)進(jìn)入failed狀態(tài);在此之前pod都是running狀態(tài),且此時(shí)ready字段會(huì)顯示正常容器個(gè)數(shù)

一些命令與操作:

  • 首先可以設(shè)置kubectl命令別名,因?yàn)樗鼘?shí)在有點(diǎn)長(zhǎng):
    alias k=kubectl

  • 通過explain可以獲取字段的詳細(xì)解釋,可以快速了解對(duì)象字段的意義:
    k explain xxx

root@ubuntu:/home/kubeyaml# k explain pods
KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
  ...

并且可以指定下層屬性:

root@ubuntu:/home/kubeyaml# k explain pods.apiVersion
KIND:     Pod
VERSION:  v1

FIELD:    apiVersion <string>

DESCRIPTION:
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
  • 獲取已創(chuàng)建pod的完整信息,可以選擇是yaml或json格式:

k get pod name -o yaml/json

  • label相關(guān)

label可以附加到任何K8S對(duì)象上,不僅僅是pod

修改現(xiàn)有pod的label:
k label po nginx app=label1

如果修改的是已經(jīng)存在的label,要加上--overwirte參數(shù):
k label po nginx app=label1 --overwrite

刪除label:
k label po nginx app- (后邊帶一個(gè) - 號(hào))

獲取pod有哪些label:
k get pod xx --show-labels

只對(duì)某些label感興趣,可以指定-L參數(shù)指定它們,如果label不存在,這一列就會(huì)為空:
k get pod -L app,bpp

root@ubuntu:/home/kubeyaml# k get po curl-custom-ambassador -L app,bpp,cpp
NAME                     READY   STATUS    RESTARTS   AGE   APP      BPP      CPP
curl-custom-ambassador   2/2     Running   29         62d   label1   label2   

使用label選擇器列出想要的 pod,超多寫法:
k get po -l xx=yy (找出帶有xx標(biāo)簽,且值等于yy的pod)
k get po -l xx!=yy (選擇帶有xx標(biāo)簽,且值不等于yy的pod)
k get po -l xx (選擇帶有xx標(biāo)簽的pod)
k get po -l '!xx' (注意單引號(hào))
k get po -l env in (prod,dev)
k get po -l env not in (prod,dev)
k get po -l env=prod,app=label1 (多個(gè)標(biāo)簽的情況,全部匹配才算成功)

  • 注解
    注解也是鍵值對(duì)的形式,與label不同的是,注解并不是為了保存標(biāo)識(shí)信息而存在,它們不能像標(biāo)簽一樣用于對(duì)象分組;注解的目的主要是為了添加說明,比如指定創(chuàng)建對(duì)象的人員姓名,可以讓集群中的工作人員之間協(xié)作更便利。

添加注解:
k annotate pod xx mycompany.com/somenot="foo bar"
同樣的,如果想覆蓋之前的注解,可添加--overwrite參數(shù)

查看剛剛添加的注解:
k describe po curl-custom-ambassador | grep Annotation

root@ubuntu:~# k describe po curl-custom-ambassador | grep Annotation
Annotations:  mycomp.com/somenot: foo bar
  • namespace

創(chuàng)建一個(gè)namespace,可以不用yaml文件,直接用命令:
k create namespace xxxx
不同namespace中的pod對(duì)象是可以重名的。
大多數(shù)對(duì)象的名稱必須符合RFC1035域名規(guī)定的命名規(guī)范,即只能包含字母、數(shù)字、橫杠-,點(diǎn)號(hào),但namespace中是不能有點(diǎn)號(hào)的。

如何快速切換到不同的namespace:
alias kcd='kubectl config set-context $(kubectl config current-context) --namespace'
然后,就可以使用 kcd some-namespace在namespace之間快速切換
舉例,先切換到my這個(gè)namespace下,查看pod,發(fā)現(xiàn)是空的

root@ubuntu:~# kcd my
Context "minikube" modified.
root@ubuntu:~# k get po
No resources found in my namespace.

然后切到default namespace下,pod又出現(xiàn)了

root@ubuntu:~# kcd default
Context "minikube" modified.
root@ubuntu:~# k get po
NAME                                            READY   STATUS             RESTARTS   AGE
curl-custom-ambassador                          2/2     Running            31         62d
grafana-69855b9d58-5g86k                        1/1     Running            11         56d
prometheus-alertmanager-998d6d5f8-kkhz7         2/2     Running            22         56d

可以通過-A參數(shù)來快速查詢所有namespace下的資源,例如:
k get po -A

  • 刪除操作

通過標(biāo)簽選擇器刪除:
k delete po -l xx=yy
刪除namespace時(shí),其下的所有pod也會(huì)被刪除:
k delete ns xx
也可以只刪除namespace下的所有pod,保留namespace:
k delete po --all
當(dāng)然可以更暴力一些:
k delete all --all
此時(shí)該namespace下絕大部分的資源類型的實(shí)例,都將會(huì)刪除,比如pod,rc,rs等;也有一些資源此時(shí)不會(huì)刪除,比如secret

  • 保持pod的健康---存活探針

存活探針 liveness probe (還有就緒探針readiness probe, 他們倆的使用場(chǎng)景完全不一樣)
1. 當(dāng)pod調(diào)度到某個(gè)node,該node上的kubelet就會(huì)運(yùn)行該pod;如果容器的主進(jìn)程崩潰,kubelet就會(huì)重啟容器。
2. 即使進(jìn)程沒有崩潰,比如JVM發(fā)生了OOM,進(jìn)程依然可以運(yùn)行,但此時(shí)希望能有辦法向K8S發(fā)送信號(hào)。
3. 當(dāng)應(yīng)用死循環(huán)或者死鎖,就會(huì)停止響應(yīng),為了確保程序此時(shí)可以重啟,應(yīng)當(dāng)從外部檢查應(yīng)用的情況,而不是依賴程序內(nèi)部的檢測(cè)

存活探針的3種機(jī)制:

  1. HTTP GET,通過get請(qǐng)求的響應(yīng)碼來判斷是否要重啟容器
  2. tcp套接字,與容器指定端口建立tcp連接,如果建立不成功則重啟容器
  3. exec, 在容器內(nèi)執(zhí)行任意命令,并檢查命令的退出碼

存活探針中重要的附加屬性:

  1. timeoutSeconds: 容器必須在這個(gè)時(shí)間值內(nèi)做出響應(yīng),否則就被認(rèn)為失敗,默認(rèn)為1s
  2. periodSeconds: 多長(zhǎng)時(shí)間探測(cè)一次,默認(rèn)10s
  3. failureThreshold: 連續(xù)探測(cè) x 次失敗之后,重啟容器,默認(rèn)為1
  4. successThreshold: 連續(xù)探測(cè) x 次成功之后才算成功,默認(rèn)為1
  5. initialDelaySeconds: 初始延遲,務(wù)必設(shè)置,如果不設(shè)置,探針會(huì)在容器啟動(dòng)時(shí)立即開始探測(cè),默認(rèn)為0
livenessProbe:
  httpGet:
    path: /
    port: 8080
  initialDelaySeconds: 15

在生產(chǎn)中的pod,一定要定義存活探針;如果沒有定義,k8s是不會(huì)知道應(yīng)用是否還活著的。

一些推薦的做法:

  1. 確保探針的請(qǐng)求端點(diǎn)不需要認(rèn)證,比如/health,否則探測(cè)會(huì)一直失敗
  2. 要檢查程序內(nèi)部的狀態(tài)(從內(nèi)部對(duì)運(yùn)行的所有重要組件執(zhí)行狀態(tài)檢查),而不受到外部因素的影響。例如,當(dāng)web服務(wù)器無法連接到后端數(shù)據(jù)庫(kù)時(shí),web服務(wù)器的存活探針不應(yīng)該返回失敗;因?yàn)槿绻麊栴}是出在數(shù)據(jù)庫(kù),重啟web服務(wù)器不會(huì)解決問題的。
  3. 保持探針輕量,因?yàn)樘綔y(cè)器執(zhí)行頻率相對(duì)較高,探針的CPU時(shí)間會(huì)計(jì)入容器的CPU時(shí)間配額,過重的探針會(huì)影響容器的運(yùn)行
  4. 不要在探針中實(shí)現(xiàn)重試循環(huán),k8s本身會(huì)進(jìn)行若干次的嘗試

參考內(nèi)容:

極客時(shí)間《深入剖析kubernetes》
《Kubernetes in action中文版》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容