天天看點

4 pod的狀态以及探針類型和方式

一 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被回收。

4 pod的狀态以及探針類型和方式

pause-主控端的namespace

4 pod的狀态以及探針類型和方式

然後到Pod所在的主控端驗證網卡

4 pod的狀态以及探針類型和方式

檢視一個pod的Ip,然後去主控端找到對應的ip

4 pod的狀态以及探針類型和方式

然後在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

4 pod的狀态以及探針類型和方式

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      

通路效果

4 pod的狀态以及探針類型和方式
4 pod的狀态以及探針類型和方式

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      

效果如下:

4 pod的狀态以及探針類型和方式

二 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      

大緻流程:

4 pod的狀态以及探針類型和方式

繼續閱讀