1. K8S中的資源
1.1 什麼是資源
K8S中所有的內容都抽象爲資源,資源實例化後叫做對象。實例化的含義的是指資源被調用執行。
1.2 資源分類
名稱空間級別的資源:僅在指定名稱空間下生效,kuberadm安裝K8S集羣默認把所有的系統組件放在kube-system名稱空間下運行,通過命令 kubect get pod 是獲取不到系統Pod的信息,這裏 kubect get pod 等價於kubect get pod -n default,只會獲取默認的名稱空間中的資源。
集羣級別的資源:不管什麼名稱下定義,在其它名稱空間下都能看得到,其實在定義的時候根本沒有指定名稱空間。一旦經過定義以後,在全集羣中都是可見的並且可以被調用的。
元數據型的資源:如HPA可以通過CPU的當前利用率進行平滑擴展,也就是通過指標進行操作
1.3 名稱空間級別資源
工作負載資源:Pod,ReplicaSet,Deploment,StatefulSet,DaemonSet,Job,CronJob(ReplicationController在v1.11版本中被廢棄)
服務發現及負載均衡型資源:Service,Ingress。這兩個都是爲了 把服務暴露出去
。
配置與存儲資源:Volume(存儲卷),CSI(容器存儲接口,可以擴展各種各樣的第三方存儲卷)在K8S中,很多資源比較靈活地能夠提供給所需要的容器運行
,只要存儲資源複合存儲規範,K8S中的Pod就可以調用存儲資源。
特殊類型的存儲卷:ConfigMap(通過其存儲配置文件達到i熱更新的狀態,當作配置中心來使用的資源類型),Secret(保護敏感數據),DownloadAPT(把外部環境中的信息輸出給容器)
1.3 集羣級別的資源
Namespace,Node,Role,ClusterRole,RoleBinding,CluserRoleBinding
1.4 元數據型資源
HPA,PodTemplate,LimitRange,也就是需要根據指標進行對應的操作
2. 資源清單
在K8S中一般 使用yaml格式的文件來創建符合我們期望的Pod
,這樣的yaml文件一般被稱之爲資源清單。
2.1 簡單說明
YAML文件是一個可讀性高,用來表達數據序列的格式。YAML的意思其實是:仍然是一種標記語言,但是爲了強調這種語言以數據爲中心,而不是以標記語言爲中心。
2.2 基本語法
縮進時不允許使用Tab,只能夠使用空格
縮進的空格數不重要,只要相同層級的元素左側對齊即可
#標識註釋,從這個字符一直到尾行都會被解釋器忽略
2.3 YAML支持的數據結構
對象:鍵值對集合,又稱爲映射/字典/哈希
數組:一組按照次序排列的值,又稱爲序列/列表
純量:單個的、不可再分的值
2.4 對象類型
對象的一組鍵值對使用冒號來表示:
name:Erics
age:23
也允許另外一種寫法,把所有的鍵值對寫成一個行內對象:
hash:{name:Erics,age:23}
2.5 數組類型
一組連詞線開頭的行構成一個數組:
animal:
- cat
- dog
數組也可以採用行內寫法:
animal:[cat,dog]
2.6 複合結構
對象和數組可以結合使用形成複合結構:
languages:
- Python
- Java
- C
websites:
YAML:yaml.org
Python:python.org
2.7 純量
純量時最基本的不可再分的值,以下都屬於純量:
# 字符串 布爾值 整數 浮點數 null 時間 日期
# 數值直接以字面量的形式表示:
number:123
# 布爾值以true和false標識:
isSet:true
# null用~表示,不寫也代表null:
parent:~
# 時間採用ISO8601格式:
ISO8601:2020-06-16t15:17:20.10-05:00
# 日期採用複合ISO8601格式的年、月、日表示:
date:2020-06-18
# YAML允許使用兩個!!強制轉換類型
e:!!str 123
f:!!str true
2.8 字符串
字符串不使用引號表示,
str:字符串
如果字符串之間包含空格,需要使用引號:
str:'字符串 '
單引號和雙引號都可以使用,雙引號不會對特殊字符轉義
:
s1:'\n'
s2:"\n"
單引號之中如果還有單引號,必須再加一個單引號轉義:
str:'labor''s day'
字符串可以寫成多行,從第二行開始必須有一個單空格縮進。換行符會被轉成空格:
str:第一行
第二行
第三行
多行字符串可以使用|保留換行符,也可以使用>摺疊換行:
this:|
Foo
Bar
that:>
Foo
Bar
+表示文字塊末尾的換行(默認),-表示刪除字符串末尾的換行:
s1:|
Foo
s2:|+
Foo
s3:|-
Foo
3. 常用字段解釋說明
3.1 必須存在的屬性
3.2 主要對象
主要對象不寫也可以,會使用默認值:
3.3 額外的參數項
3.4 自定義Pod模板
可以使用命令去查看這些參數的解釋:
[root@k8s-master-01 ~]# kubectl explain pod
[root@k8s-master-01 ~]# kubectl explain pod.spec
[root@k8s-master-01 ~]# kubectl explain pod.spec.containers
...
自己寫一個Pod模板:
pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
namespace: default
labels:
app: myapp
version: v1
spec:
containers:
- name: app
image: hub.atguigu.com/library/myapp:v1
- name: test
image: hub.atguigu.com/library/myapp:v1
Pod創建成功:
[root@k8s-master-01 ~]# kubectl apply -f pod.yaml
pod/myapp-pod created
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/2 Pending 0 2m13s
# 查看Pod的信息
[root@k8s-master-01 ~]# kubectl describe pod myapp-pod
# 查看容器運行日誌
[root@k8s-master-01 ~]# kubectl log myapp-pod -c app
[root@k8s-master-01 ~]# kubectl log myapp-pod -c test
第一個容器 app 運行正常,但是 test 不能正常運行,因爲 app 容器已經佔用了80端口。同一個Pod中的容器共享網絡棧
。下面修改 yaml 文件,把 test 容器刪除:
[root@k8s-master-01 ~]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
namespace: default
labels:
app: myapp
version: v1
spec:
containers:
- name: app
image: hub.atguigu.com/library/myapp:v1
# 刪除pod
[root@k8s-master-01 ~]# kubectl delete pod myapp-pod
# 按照yaml文件創建pod
[root@k8s-master-01 ~]# kubectl apply -f pod.yaml
# 查看pod的詳細信息
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-pod 1/1 Running 0 12s 10.244.1.20 k8s-node-01 <none> <none>
[root@k8s-master-01 ~]# curl 10.244.1.20
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
4. Pod生命週期
Pod在創建經歷了哪些過程,理解了這些過程才能直到如何探測。Pod裏面有兩個容器,如果兩個容器中的進程已經死亡或意外中斷了,由於某種故障這個Pod並沒有退出,造成這個Pod還處於運行狀態。這時候服務是不可用的,但是這個Pod還是處於可用狀態。這個時候就會出現問題,那麼如何來做探查?不着急,首先要了解容器是如何初始化的。Pod的生命週期:
一開始當我們的請求指令被下達到api接口被調度到kuberlet上,kuberlet操作對應的CRI去做容器環境的初始化,會先啓動Pause容器(基本容器,同一Pod容器的容器之間網絡和存儲卷共享
)。進入Pod生命週期內部,Pod創建的時候首先需要進行Init C(初始化容器)的創建過程,創建完成之後Init C就會死亡。不能同時運行兩個甚至多個Init C
,只能前面一個Init C運行結束後運行下一個Init C。要在Init C之前。Init C完成之後就會進入主容器,主容器可以有多個
。在主容器運行之前和之後都可以運行指令,即:Start和Stop操作,執行命令或者腳本
。
readiness,即就緒檢測模塊,可以根據命令或TCP連接或HTTP協議獲取狀態,判斷Pod中服務是否可用
,如果可用纔會把運行狀態改爲Running,防止雖然處於Running狀態,但是無法提供給外網訪問。
liveness,即生存檢測模塊。如果Pod裏面運行一個主容器,主容器中運行一個Nginx的進程,但是處於假死狀態(殭屍進程)。進程沒有死掉,則這個主容器就會運行着
,Pod的狀態就會顯示Running,能夠繼續爲外網提供訪問。我們需要需要有種機制,當發現容器內部(Nginx)不能提供對外訪問的時候,可以 重啓進程或者重建Pod等操作
,這就用到了liveness。
5. Init 容器
5.1 Init 容器概述
Pod能夠具有多個容器,應用運行在容器裏面,但是它也可能有一個或多個先於應用容器啓動的Init容器,Init容器與普通的容器非常像,除了如下兩點:
① Init容器總是運行到成功完成爲止
② 每個Init容器都必須在下一個Init容器啓動之前成功完成
對應 Init 容器和主容器是不一樣的,主容器如果退出,Pod也就結束了。Init C的退出與Pod生命週期沒有關係,Pod並不會結束。但是,Init C如果不是正常退出,就到達不了主容器。並且,如果Init C如果如果沒有正常退出,Pod是需要進行對應的流程處理,比如Pod重啓。
如果Pod的Init容器失敗,Kubernetes會不斷地重啓該Pod,直到Init容器成功爲止。然而,如果Pod對應的restartPolicy爲Never,它不會重新啓動
。
5.2 Init容器的作用
因爲Init容器具有與應用程序容器分離的單獨鏡像,所以它們的啓動相關代碼具有如下優勢:
① 它們可以包含並運行實用工具,但是出於安全考慮,是不建議在應用程序容器鏡像中包含這些實用工具的(安全性
)
② 它們可以包含使用工具和定製化代碼來安裝,但是不能出現在應用程序鏡像中。例如,創建鏡像沒必要FROM另一個鏡像,只需要在安裝過程中使用類似sed、awk、python或dig這樣的工具。(冗餘性
)
把主容器要使用的工具寫入Init C,在初始化的時候把主容器需要的文件提前創建出來。主容器不需要包含這些文件,這些工具並不是主容器一直都要用的,防止造成冗餘
③ 應用程序鏡像可以分離出創建和部署的角色,而沒有必要聯合它們構建一個單獨的鏡像
④ Init容器使用LinuxNamespace,所以相對應用程序容器來說具有不同的文件系統視圖。因此,它們能夠具有訪問Secret的權限,而應用程序容器則不能
有一些需要主容器去調用的文件,但是主容器(Main C)對這些文件沒有訪問權限。這個文件所在的目錄還有其它重要的文件,如果把這個文件的目錄賦予權限給主容器,那麼主容器就可以隨便調用目錄下的所有文件。這樣安全性就出現隱患,這個時候完全可以把權限賦予給Init C,讓Init C獲取文件後寫入到主容器,Init C寫入文件後就退出了。主容器沒有獲取文件的權限,主容器安全性就會提高。這是採用分權限進行處理。
⑤ 它們必須在應用程序容器啓動之前運行完成,而 應用程序容器是並行運行的
,所以Init容器能夠提供了一種簡單的阻塞或延遲應用容器的啓動的方法,直到滿足了一組先決條件
如有兩個主容器,一個是Apache+PHP,另外一個是MySQL。要求啓動mysql後再啓動Apache+PHP容器,這是爲了防止Apache+PHP容器連接MySQL連接不上,認爲容器有問題就退出容器,然後不斷重啓。這種情況下可以在Apache+PHP容器加入的Init C,可以探測MySQL連接是否正常,如果正常啓動,Init C會退出容器,主容器啓動連接MySQL。
5.3 Init 容器實例
node1和node2下載busybox鏡像,也可以不下載等待自動下載:
[root@k8s-node-01 ~]# docker pull busybox
[root@k8s-node-02 ~]# docker pull busybox
[root@k8s-master-01 ~]# vim init-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh','-c','until nslookup myservice; do echo waiting for myservice; sleep 2;done;']
- name: init-mydb
image: busybox
command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
# deployment和pod默認使用的名稱空間是default
[root@k8s-master-01 ~]# kubectl delete deployment --all
[root@k8s-master-01 ~]# kubectl delete pod --all
# 刪除svc
[root@k8s-master-01 ~]# kubectl get svc
[root@k8s-master-01 ~]# kubectl delete svc nginx-deployment
# grace-period表示過渡存活期,默認30s,在刪除POD之前允許POD慢慢終止其上的容器進程,從而優雅退出,0表示立即終止POD
[root@k8s-master-01 ~]# kubectl delete pod --all --force --grace-period=0
[root@k8s-master-01 ~]# kubectl create -f init-pod.yaml
pod/myapp-pod created
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 3s
[root@k8s-master-01 ~]# kubectl describe pod myapp-po
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 101s
# 查看init-myservice 初始化容器的日誌,發現解析不成功
[root@k8s-master-01 ~]# kubectl log myapp-pod -c init-myservice
創建svc:
[root@k8s-master-01 ~]# vim myservice.yaml
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
[root@k8s-master-01 ~]# kubectl create -f myservice.yaml
[root@k8s-master-01 ~]# vim myservice.yaml
[root@k8s-master-01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d2h
myservice ClusterIP 10.107.163.130 <none> 80/TCP 85s
# 其中一個初始化容器已經運行成功並退出
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:1/2 0 10m
創建一個名字爲myservice的service,myservice創建之後會被本機集羣內部解析。也就是說,內部的所有容器會把兩臺機器的內部IP配置成DNS服務器。myapp-pod會請求這個DNS服務器,又沒有名字爲myservice的svc,如果創建了svc,就會被寫入到DNS。DNS就會返回對應的數據,成功之後,初始化容器檢測到就退出。
# coredns-5c98db65d4-dc5h7是DNS
[root@k8s-master-01 ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5c98db65d4-dc5h7 1/1 Running 0 10m
coredns-5c98db65d4-f2lbc 1/1 Running 0 10m
coredns-5c98db65d4-r6sbc 1/1 Terminating 17 7d2h
coredns-5c98db65d4-zq2xf 1/1 Terminating 17 7d2h
etcd-k8s-master-01 1/1 Running 18 7d2h
kube-apiserver-k8s-master-01 1/1 Running 18 7d2h
kube-controller-manager-k8s-master-01 1/1 Running 1 7d2h
kube-flannel-ds-amd64-gd55v 1/1 Running 12 7d1h
kube-flannel-ds-amd64-l8xtd 1/1 Running 21 7d2h
kube-flannel-ds-amd64-xcwmt 1/1 Running 7 6d23h
kube-proxy-5gm9j 1/1 Running 18 7d2h
kube-proxy-n2gkx 1/1 Running 8 6d23h
kube-proxy-zl82c 1/1 Running 12 7d1h
kube-scheduler-k8s-master-01 1/1 Running 27 7d2h
第二個Init C檢測的是mydb,所以需要創建一個mydb的svc:
[root@k8s-master-01 ~]# vim mydb.yaml
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
[root@k8s-master-01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d3h
mydb ClusterIP 10.106.42.42 <none> 80/TCP 32s
myservice ClusterIP 10.107.163.130 <none> 80/TCP 13m
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 21m
# 如果出錯可以查看
[root@k8s-master-01 ~]# kubectl decribe pod myapp-pod
busybox在沒有指定版本的情況下,默認用latest來ag,在K8S中如果使用latest標籤來保存,每次在使用鏡像的時候都會從倉庫去下載。latest在不同時期代表不同版本。
4.4 特殊說明
① 在Pod啓動過程中,Init容器會按順序在網絡和數據卷初始化(在pause中完成
)之後啓動。每個容器必須在下一個容器啓動之前成功退出
② 如果由於運行時或失敗退出,將導致容器啓動失敗,它會根據Pod的restartPolicy指定的策略進行重試,直到達到最大上限
。然而,如果Pod的restartPolicy設置爲Always,Init容器失敗時會使用RestartPolicy策略
③ 在所有的Init容器沒有成功之前,Pod將不會變成Ready狀態。Init容器的端口將不會在Service中進行聚集。正在初始化中的Pod處於Pending狀態,但應該會將Initializing狀態設置爲true
④ 如果Pod重啓,所有Init容器必須重新執行
⑤ 對Init容器spec的修改被限制在容器image字段,修改其他字段都不會生效。更改Init容器的image字段,等價於重啓該Pod
[root@k8s-master-01 ~]# kubectl edit pod myapp-pod
initContainers:
- command:
- sh
- -c
- until nslookup myservice; do echo waiting for myservice; sleep 2;done;
image: busybox # 其它修改不會生效,但是被修改會觸發init C容器,相當於Pod被重啓了
...
⑥ Init容器具有應用容器的所有字段。除了readinessProbe,因爲Init容器無法定義不同於完成(completion)的就緒(readiness)之外的其他狀態,這會在驗證過程中強制執行。沒有存活檢測和就緒檢測字段
,因爲完成之後就退出了,如果有也不會生效。
⑦ 在 Pod中的每個app和Init容器的名稱必須唯一
,與任何其它容器共享同一個名稱,會在驗證時拋出錯誤,端口可以是一致的,Init C容器是線性運行的
,一個運行結束纔會運行下一個。
6. 容器探針
6.1 探針
探針不是由主服務發起的,而是由每一個Node所在的kubelet對容器執行的定期診斷,這樣主調度的壓力就會更小。要執行診斷,kubelet調用由容器實現的Handler。有三種類型的處理程序:
① ExecAction:在容器內執行指定命令。如果命令退出時返回碼爲0則認爲診斷成功
② TCPSocketAction:對指定端口上的容器的IP地址進行TCP檢查。如果端口打開,則診斷被認爲是成功的
③ HTTPGetAction:對指定的端口和路徑上的容器的IP地址執行HTTPGet請求。如果響應的狀態碼大於等於200且小於400,則診斷被認爲是成功的
每次探測都將獲得以下三種結果之一:
① 成功:容器通過了診斷
② 失敗:容器未通過診斷
③ 未知:診斷失敗,因此不會採取任何行動
6.2 探測方案
livenessProbe:指示容器是否正在運行。如果存活探測失敗,則kubelet會殺死容器,並且容器將受到其重啓策略的影響。如果容器不提供存活探針,則默認狀態爲Success(會跟隨容器整個生命週期,從liveness啓動到Pod結束都會存在,會持續循環地檢測這個容器裏面的應用程序資源是否可用,不可用就會殺死這個容器。
)
readinessProbe:指示容器是否準備好服務請求。如果就緒探測失敗,端點控制器將從與Pod匹配的所有Service的端點中刪除該Pod的IP地址。初始延遲之前的就緒狀態默認爲Failure。如果容器不提供就緒探針,則默認狀態爲Success(檢測成功之後,主容器才能夠宣佈對外正常訪問。
)
6.3 就緒檢測
就緒檢測的實現,通過httpget方案:
[root@k8s-node-01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 1c35c4412082 2 weeks ago 1.22MB
quay.io/coreos/flannel v0.12.0-amd64 4e9f801d2217 3 months ago 52.8MB
k8s.gcr.io/kube-apiserver v1.15.1 68c3eb07bfc3 11 months ago 207MB
k8s.gcr.io/kube-scheduler v1.15.1 b0b3c4c404da 11 months ago 81.1MB
k8s.gcr.io/kube-controller-manager v1.15.1 d75082f1d121 11 months ago 159MB
k8s.gcr.io/kube-proxy v1.15.1 89a062da739d 11 months ago 82.4MB
k8s.gcr.io/coredns 1.3.1 eb516548c180 17 months ago 40.3MB
k8s.gcr.io/etcd 3.3.10 2c4adeb21b4f 18 months ago 258MB
hub.atguigu.com/library/myapp v1 d4a5e0eaa84f 2 years ago 15.5MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 2 years ago 742kB
[root@k8s-master-01 ~]# vim readness.yaml
apiVersion: v1 # api的版本
kind: Pod # kind的類型
metadata: # 元數據信息
name: readiness-httpget-pod # pod的名稱
namespace: default # pod所在的名稱空間
spec: # 詳細的描述
containers: # 描述容器
- name: readiness-httpget-container # 容器的名稱
image: hub.atguigu.com/library/myapp:v1 # 容器的鏡像
imagePullPolicy: IfNotPresent # 鏡像的下載策略:如果有就不下載了
readinessProbe: # 就緒檢測
httpGet: # 檢測的方案:httpGet
port: 80 # 端口,或者寫爲http
path: /index1.html # 檢測的路徑
initialDelaySeconds: 1 # 初始化檢測的延時:容器啓動1s後開始檢測
periodSeconds: 3 # 重試的檢測時間:3s後重試檢測
[root@k8s-master-01 ~]# kubectl create -f readness.yaml
# 雖然是Runngin狀態但是並不是Ready狀態
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-pod 1/1 Running 4 3h28m 10.244.1.38 k8s-node-01 <none> <none>
readiness-httpget-pod 0/1 Running 0 4s 10.244.1.42 k8s-node-01 <none> <none>
# 發現沒有index1.html,即探針檢測出來是404
[root@k8s-master-01 ~]# kubectl describe pod readiness-httpget-pod
Warning Unhealthy 3s (x16 over 48s) kubelet, k8s-node-01 Readiness probe failed: HTTP probe failed with statuscode: 404
# 進入容器中,如果Pod中只有一個容器不需要指定容器名稱,指定的時候加上-c參數,-t交互和打開tty
[root@k8s-master-01 ~]# kubectl exec readiness-httpget-pod -it -- /bin/sh
/ # cd /usr/share/nginx/
/usr/share/nginx # cd html/
/usr/share/nginx/html # ls
50x.html index.html
/usr/share/nginx/html # echo '123'>index1.html
/usr/share/nginx/html # ls
50x.html index.html index1.html
/usr/share/nginx/html # exit
# 檢測成功
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 4 3h34m
readiness-httpget-pod 1/1 Running 0 6m49s
如果有個主容器apache+php想檢測mysql狀態,使用Init C是不友好的,Init C作爲環境初始化工具即可。在主容器中使用readinessProbe對mysql進行檢測是比較合適的。
6.4 存活檢測
通過exec的方案來實現存活檢測:
# 刪除默認名稱空間下的所有Pod
[root@k8s-master-01 ~]# kubectl delete pod --all
[root@k8s-master-01 ~]# kubectl delete svc mydb myservice
[root@k8s-master-01 ~]# kubectl create -f liveness.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
namespace: default
spec:
containers:
- name: liveness-exec-container
image: busybox # 如果沒有加版本號,默認爲latest,會從遠程下載(前提條件:默認的,也就是Always)
imagePullPolicy: IfNotPresent # 不是默認,不會去遠程下載
command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep3600"]
livenessProbe: # 和容器綁定
exec:
command: ["test","-e","/tmp/live"] # 檢測這個文件是否存在
initialDelaySeconds: 1 # 1s之後纔會進行liveness的檢測
periodSeconds: 3 # 3s檢測一次
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
liveness-exec-pod 1/1 Running 0 15s
[root@k8s-master-01 ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-exec-pod 0/1 CrashLoopBackOff 2 3m29s
liveness-exec-pod 1/1 Running 3 3m45s
liveness-exec-pod 0/1 Error 3 4m46s
liveness-exec-pod 0/1 CrashLoopBackOff 3 4m47s
# 已經重啓了4次
[root@k8s-master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
liveness-exec-pod 1/1 Running 4 6m2s
容器重啓的方案默認RestartPolicy是always,即總是重啓!
通過httpget的方案來實現存活檢測:
# 因爲防止端口衝突
[root@k8s-master-01 ~]# kubectl delete pod liveness-exec-pod
[root@k8s-master-01 ~]# vim liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-pod
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: hub.atguigu.com/library/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http # http可以複用,也就是80
path: /index.html # 檢查能不能訪問到index.html
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
[root@k8s-master-01 ~]# kubectl create -f liveness-httpget.yaml
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
liveness-httpget-pod 1/1 Running 0 2m3s 10.244.1.44 k8s-node-01 <none> <none>
[root@k8s-master-01 ~]# curl 10.244.1.44
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
# 把文件刪除
[root@k8s-master-01 ~]# kubectl exec liveness-httpget-pod -it -- /bin/sh
/ # rm -rf /usr/share/nginx/html/index.html
/ # exit
# 可以看到重啓次數變爲2
[root@k8s-master-01 ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-httpget-pod 1/1 Running 2 5m15s
通過tcp的方案來實現存活檢測:
[root@k8s-master-01 ~]# vim liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
name: probe-tcp
spec:
containers:
- name: nginx
image: hub.atguigu.com/library/myapp:v1
livenessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 80
# 不指定端口也可以正常運行,和前面方案設置的80端口不衝突
[root@k8s-master-01 ~]# kubectl create -f liveness-tcp.yaml
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
liveness-httpget-pod 1/1 Running 2 10m 10.244.1.44 k8s-node-01 <none> <none>
probe-tcp 1/1 Running 0 38s 10.244.1.45 k8s-node-01 <none> <none>
[root@k8s-master-01 ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-httpget-pod 1/1 Running 2 16m
probe-tcp 1/1 Running 0 20s
probe-tcp 1/1 Running 1 30s
probe-tcp 1/1 Running 2 57s
probe-tcp 1/1 Running 3 88s
就緒檢測和存活檢測可以放在一起!就緒檢測值是改狀態,存活檢測只要不是存活就退出容器!
7. 啓動退出動作
[root@k8s-master-01 ~]# vim start_end.yaml
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: ["/bin/sh", "-c", "echo Hello from the postStop handler >/usr/share/message"]
[root@k8s-master-01 ~]# kubectl get pod lifecycle-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lifecycle-demo 1/1 Running 0 75s 10.244.1.47 k8s-node-01 <none> <none>
[root@k8s-master-01 ~]# kubectl exec lifecycle-demo -it -- /bin/sh
# cat /usr/share/message
Hello from the postStart handler
# exit
8. Pod phase
8.1 Pod phase簡介
Pod的status字段是一個PodStatus對象,PodStatus中有一個phase字段。Pod的相位(phase)是Pod在其生命週期中的簡單宏觀概述。該階段並不是對容器或Pod的綜合彙總,也不是爲了做爲綜合狀態機。Pod相位的數量和含義是嚴格指定的。除了本文中列舉的狀態外,不應該再假定Pod有其他的phase值。
8.2 Pod phase可能存在的值
掛起(Pending):Pod已被Kubernetes系統接受,但有一個或者多個容器鏡像尚未創建。等待時間包括調度Pod的時間和通過網絡下載鏡像的時間,這可能需要花點時間
運行中(Running):該Pod已經綁定到了一個節點上,Pod中所有的容器都已被創建。至少有一個容器正在運行,或者正處於啓動或重啓狀態
成功(Succeeded):Pod中的所有容器都被成功終止,並且不會再重啓(顯示在Job和CronJob中
)
失敗(Failed):Pod中的所有容器都已終止了,並且至少有一個容器是因爲失敗終止。也就是說,容器以非0狀態退出或者被系統終止(Pod中有很多容器,只要有一個容器是非正常退出狀態就是Failed
)
未知(Unknown):因爲某些原因無法取得Pod的狀態,通常是因爲與Pod所在主機通信失敗
9. 重啓策略
PodSpec中有一個restartPolicy字段,可能的值爲Always、OnFailure和Never。默認爲Always。restartPolicy適用於Pod中的所有容器。restartPolicy僅指通過同一節點上的kubelet重新啓動容器。失敗的容器由kubelet以五分鐘爲上限的指數退避延遲(10秒,20秒,40秒…)重新啓動,並在成功執行十分鐘後重置。如Pod文中所述,一旦綁定到一個節點,Pod將永遠不會重新綁定到另一個節點。
10. Pod hook
Podhook(鉤子)是由Kubernetes管理的kubelet發起的,當容器中的進程啓動前或者容器中的進程終止之前運行,這是包含在容器的生命週期之中。可以同時爲Pod中的所有容器都配置hook。Hook的類型包括兩種:
exec:執行一段命令
HTTP:發送HTTP請求