一 Pod的常見狀态、pause容和init容器
1 pod常見的狀态
Unschedulable #pod不能被排程,kube-scheduler沒有比對到合适的node節點
PodScheduled #pod正處于排程中,在kube-schedulerg剛開始排程的時候,還沒有将pod配置設定到指定的node,在篩選出合适的節點後就會更新etcd資料,将pod配置設定到指定的node
Pending #正在建立的pod,但是pod中的容器還诶呦完全被建立完成(處于此狀态的pod應該檢查pod依賴的存儲是否有權限挂載等)
Failed #pod中有容器啟動失敗而導緻pod工作異常
Unknown #由于某種原因無法獲得Pod的目前狀态,通常是由于pod所在的node節點通信錯誤
initialized #所有的pod中的初始化容器已經完成了
imagePullBackOff #pod所在的node節點下載下傳鏡像失敗
Running # pod内部的容器已經被建立并且啟動
Ready #表示pod中的容器已經可以提供通路服務
Error # 啟動過程中發生錯誤
NodeLost #pod所在節點失聯
waiting #pod等待啟動
Terminating # pod正在被銷毀
CrashLoopBackOff #pod停止,但是kubelet正在将他重新開機
invalidlmagename # node節點無法解析鏡像名稱,導緻無法下載下傳
ImageinspectError #無法校驗鏡像,鏡像不完整導緻
ErrimageNeverPull #政策禁止拉取鏡像,鏡像中心權限是私有
RegistryUnavailable #鏡像伺服器不可用,網絡原因或者harbor當機
ErrimagePull #鏡像拉取出錯,逾時或者下載下傳被強制終止
createcontainerconfigerror #不能建立kubelet使用的容器配置
createcontainerError #建立容器失敗
RuncontainerError # pod運作失敗,容器中沒有初始化pid為1的守護程序等
containersNotlnitialized #pod沒有初始化完畢
containerNotReady #pod 沒有準備完畢
containerCreating #pod正在建立中
podinitializing #pod初始化中
DockerDaemonNotReady #node節點docker服務沒有啟動
NetworkPluginNotReady #網絡插件沒有啟動
2 pause容和init容器
2.1 pause 容器
pause 容器,又叫infra容器,是Pod的基礎容器,鏡像體積隻有幾百kb左右,配置在kubelet中,主要功能是一個pod中多個容器的網絡通信。
infra容器被建立後會初始化network namespace,之後其他容器劇可以加入的infra容器中共享infra容器的網絡了。
一個pod中的兩個容器A和bB,那麼關系如下:
1 a容器和B容器能夠直接使用localhost通信
2 a容器和b容器可以看到網卡,ip和端口監聽資訊。
3 pod隻有一個ip位址,也就是改pod的network,namespace對應的ip位址(由infra容器初始化并建立)
4 k8s環境中的每個pod有一個獨立的ip位址,并且此ip被目前pod中所有容器在内部共享使用。
5 pod删除後infra容器随機被删除,其ip被回收。

pause-主控端的namespace
然後到Pod所在的主控端驗證網卡
檢視一個pod的Ip,然後去主控端找到對應的ip
然後在node節點運作如下指令
[root@k8s-node1 pause-test-case]# nsenter --net=/run/docker/netns/e8097040db3f ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.100.36.125 netmask 255.255.255.255 broadcast 10.100.36.125
ether 0a:e4:27:eb:50:44 txqueuelen 0 (Ethernet)
RX packets 5 bytes 446 (446.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
e8097040db3f 這個就是namespace
2.2 示範執行個體:通過docker示範pause,需要準備一個nginx.conf和index.html
[root@k8s-node1 pause-test-case]# cat nginx.conf
error_log stderr;
events { worker_connections 1024; }
http {
access_log /dev/stdout;
server {
listen 80 default_server;
server_name www.mysite.com;
location / {
index index.html index.php;
root /usr/share/nginx/html;
}
location ~ \.php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
index.html和index.php
1 啟動一個pause容器
docker run -d -p80:80 --name pause-container-1 easzlab/pause:3.6
2 啟動一個nginx容器,網絡使用pause的網絡
docker run -d --name nginx-container-test -v `pwd`/nginx.conf:/etc/nginx/nginx.conf -v `pwd`/html:/usr/share/nginx/html/ --net=container:pause-container-1 nginx:1.20.0
3啟動一個php容器,網絡也使用pause的
docker run -d --name php-test --net=container:pause-container-1 -v `pwd`/html:/usr/share/nginx/html/ php:5.6.40-fpm
通路效果
2.3 init容器
2.3.1 init 容器的作用:
1 可以為業務容器提前準備好業務容器的運作環境,
2 可以在卞業務容器之前準備好需要的業務資料
3 檢查依賴的服務是否可以通路
2.3.2 init容器的特點:
1 一個pod可以有多個業務網容器,還能在有多個init容器,但是每個init容器和業務容器的運作環境都是隔離的
2 init容器會比業務容器先啟動
3 init 容器運作成功後,才運作業務容器
4如果一個pod有多個init容器,那麼需要從上到下逐個運作并且全部成功,最後才會運作業務容器。
5 init 容器不支援探針檢測,因為初始化完成後退出就再也不運作了
舉例:建立一個nginx的pod,需要初始化網站的資料,這裡用centos:7.9.2009 這個鏡像來做init的容器
[root@k8s-master1 init]# cat 1-init-container.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: myserver-myapp
name: myserver-myapp-deployment-name
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: myserver-myapp-frontend
template:
metadata:
labels:
app: myserver-myapp-frontend
spec:
containers:
- name: myserver-myapp-container
image: nginx:1.20.0
#imagePullPolicy: Always
volumeMounts:
- mountPath: "/usr/share/nginx/html/myserver"
name: myserver-data
initContainers:
- name: init-web-data
image: centos:7.9.2009
command: ['/bin/bash','-c',"for i in `seq 1 10`;do echo '<h1>'$i web page at $(date +%Y%m%d%H%M%S) '<h1>' >> /data/nginx/html/myserver/index.html;sleep 1;done"]
volumeMounts:
- mountPath: "/data/nginx/html/myserver"
name: myserver-data
- name: change-data-owner
image: busybox:1.28
command: ['/bin/sh','-c',"/bin/chmod 644 /data/nginx/html/myserver/* -R"]
volumeMounts:
- mountPath: "/data/nginx/html/myserver"
name: myserver-data
volumes:
- name: myserver-data
hostPath:
path: /tmp/data/html
---
kind: Service
apiVersion: v1
metadata:
labels:
app: myserver-myapp-service
name: myserver-myapp-service-name
namespace: myserver
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30080
selector:
app: myserver-myapp-frontend
效果如下:
二 pod的聲明周期和探針
2.1 生命周期
pod的聲明周期,從start後可以配置poststart檢查,運作過程中可以配置livenessprobe和readlinessprobe ,最後在stop前可以配置prestop配置
2.2 探針簡介
探針是由kubelet對容器執行的定期診斷,以保證pod的狀态始終處于運作狀态,要執行診斷,kubelet調用由容器實作的handler,也稱為鈎子,有是那種類型的處理程式
1 Execaction
在容器内部執行指定指令,如果指令退出時,傳回碼為0,則認為診斷成功
2 TcpSocketaction
對指定端口上的容器ip位址進行tcp檢查,如果端口打開,則認為是成功的
3 HTTPGetAction
對指定的端口和路徑上的容器的ip位址執行httpget請求,如果相應狀态碼大于等于200且小于400,則認為是成功的。
HTTP 探針 允許針對 httpGet 配置額外的字段:
host:連接配接使用的主機名,預設是 Pod 的 IP。也可以在 HTTP 頭中設定 “Host” 來代替。
scheme :用于設定連接配接主機的方式(HTTP 還是 HTTPS)。預設是 "HTTP"。
path:/index.html #通路 HTTP 服務的路徑。預設值為 "/"。
httpHeaders:請求中自定義的 HTTP 頭。HTTP 頭字段允許重複。
port:80 #通路容器的端口号或者端口名。如果數字必須在 1~65535 之間。
探針最終的三種結果
成功
失敗
未知:診斷失敗,是以不會采取任何行動
2.3 探針類型
1 startupProbe #啟動探針,v1.16引入
判斷容器内的應用程式是否已啟動完成。如果配置了啟動探測,則會先禁用所有其他的探測,直到startupprobe檢查成功為止,如果startupprobe,檢查失敗,則kubelet将殺死容器,
2 livenssprobe #存活探針
檢查容器是否正在運作,如果存活探測失敗,則kublet會殺死容器,并且容器将受到其重新開機政策的影響,如果容器不提供存活探針,則預設狀态為success,livessprobe使用者控制是否重新開機pod
3 readinessprobe # 就緒探針
如果就緒探針檢測失敗,端點控制器将從與pod比對的所有的service的端點中删除該pod的ip位址,初始延遲之前的就緒狀态預設為failure 失敗,如果容器不提供就緒探針,則預設為success,
readinessprobe用于控制pod是否添加到service裡。
2.3.1 strtupProbe執行個體
[root@k8s-master1 probe]# cat 4-startupProbe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
startupProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 5 #首次檢測延遲5s
failureThreshold: 3 #從成功轉為失敗的次數
periodSeconds: 3 #探測間隔周期
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 81 # k8s之間通路的端口
targetPort: 80 #容器裡的端口
nodePort: 40012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
2.3.2 三種探針全部加上
[root@k8s-master1 probe]# cat 5-startupProbe-livenessProbe-readinessProbe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
terminationGracePeriodSeconds: 60
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
startupProbe:
httpGet:
#path: /monitor/index.html
path: /index.html
port: 80
initialDelaySeconds: 5 #首次檢測延遲5s
failureThreshold: 3 #從成功轉為失敗的次數
periodSeconds: 3 #探測間隔周期
readinessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 81
targetPort: 80
nodePort: 40012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
2.4 探針通用配置參數
initialDelaySeconds:120 # 容器啟動後要等待多少秒後才啟動存活和就緒探測器, 預設是 0 秒,最小值是 0。
periodSeconds:60 #執行探測的時間間隔(機關是秒)。預設是 10 秒。最小值是 1。
timeoutSeconds:5 #探測的逾時後等待多少秒。預設值是 1 秒。最小值是 1。
successThreshold:1 # 探測器在失敗後,被視為成功的最小連續成功數。預設值是 1。 存活和啟動探測的這個值必須是 1。最小值是 1。
failureThreshold:3 #當探測失敗時,Kubernetes 的重試次數。 對存活探測而言,放棄就意味着重新啟動容器。 對就緒探測而言,放棄意味着 Pod 會被打上未就緒的标簽。預設值是 3。最小值是 1。
2.5 探針檢測方式示範
1 http類型探針
[root@k8s-master1 probe]# kubectl apply -f 1-http-Probe.yaml
deployment.apps/myserver-myapp-frontend-deployment created
service/myserver-myapp-frontend-service created
[root@k8s-master1 probe]# cat 1-http-Probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
#readinessProbe:
livenessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 80
targetPort: 80
nodePort: 40018
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
2 tcp檢查
[root@k8s-master1 probe]# cat 2-tcp-Probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
livenessProbe:
#readinessProbe:
tcpSocket:
#port: 80
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 80
targetPort: 80
nodePort: 40012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
3 exec-自定義指令
[root@k8s-master1 probe]# cat 3-exec-Probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-redis-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-redis-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-redis,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-redis-label
spec:
containers:
- name: myserver-myapp-redis-container
image: redis
ports:
- containerPort: 6379
livenessProbe:
#readinessProbe:
exec:
command:
#- /apps/redis/bin/redis-cli
- /usr/local/bin/redis-cli
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-redis-service
namespace: myserver
spec:
ports:
- name: http
port: 6379
targetPort: 6379
nodePort: 40016
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-redis-label
2.6 如何優雅的終止pod(prestop)
poststart:
pod被建立後立即執行檢查,及不等的pod中的服務啟動
如果poststart執行失敗pod不會被繼續建立
prestop:
在pod被停止之前執行一些操作
通俗的講就是等待一定時間,才會執行prestop的操作,在等待的時間,可以把pod從注冊中心移走,或者讓pod下線,這樣當執行prestop的之後,避免使用者發送通路請求,造成頁面打不開的故障。
示範:
[root@k8s-master1 probe]# cat 1-myserver-myapp1-postStart-preStop.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp1-lifecycle
labels:
app: myserver-myapp1-lifecycle
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: myserver-myapp1-lifecycle-label
template:
metadata:
labels:
app: myserver-myapp1-lifecycle-label
spec:
terminationGracePeriodSeconds: 60 #終止等待期就是說等待60秒之後,才會執行prestop裡的指令
containers:
- name: myserver-myapp1-lifecycle-label
image: tomcat:7.0.94-alpine
lifecycle:
postStart:
exec:
#command: 把自己注冊到注冊在中心
command: ["/bin/sh", "-c", "echo 'Hello from the postStart handler' >> /usr/local/tomcat/webapps/ROOT/index.html"]
#httpGet:
# #path: /monitor/monitor.html
# host: www.magedu.com
# port: 80
# scheme: HTTP
# path: index.html
preStop:
exec:
#command: 把自己從注冊中心移除
command: ["/usr/local/tomcat/bin/catalina.sh","stop"]
ports:
- name: http
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp1-lifecycle-service
namespace: myserver
spec:
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp1-lifecycle-label
大緻流程: