Kubernetes的Pod進階(十一)

童話述說我的結局發表於2022-01-27

一、Lifecycle

官網:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/

 通過前面的分享,關於pod是什麼相信看過前面的文章的朋友已經很清楚了,有開發經驗的朋友很清楚,物件的建立是具有生命週期的,對於Pod也一樣,他也有它的生命週期,接下來就是分享pod的建立、銷燬、以及他的狀態是什麼;簡單的來說,就是分享pod的生命週期。

 

 

 

 下圖是官網對Pod生命週期階段的描述

 

 

 通過官網可以發現有一個Running狀態,相信大家也非常喜歡Running狀態,因為這玩意就表示建立成功正常執行,但有時候建立pod時也有不隨人願的時候,因為有時pod偏偏會有一些奇怪的狀態,比哪下面幾個狀態

  • 掛起(Pending):Pod 已被 Kubernetes 系統接受,但有一個或者多個容器映象尚未建立。等待時間包括排程 Pod 的時間和通過網路下載映象的時間,這可能需要花點時間。
  • 執行中(Running):該 Pod 已經繫結到了一個節點上,Pod 中所有的容器都已被建立。至少有一個容器正在執行,或者正處於啟動或重啟狀態。
  • 成功(Succeeded):Pod 中的所有容器都被成功終止,並且不會再重啟。
  • 失敗(Failed):Pod 中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態退出或者被系統終止。
  • 未知(Unknown):因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通訊失敗。

其實對這Pod五大狀態瞭解後有問題時就可以很好解決了,因為知道狀態後就可以通過kubectl describe pod pod-name -n namespace去檢視pod日誌瞭解為什麼出現這狀態了。

二、重啟策略

 前面生命週期瞭解了後,下面瞭解下pod的重啟策略,之所以要了解這,是因為我們有時候在建立Pod時會發現Pod會不斷髮生重啟,官網對於重啟策略也有說明,通過官網可以知道,關於重啟我們可以在yaml檔案中通過restartPolicy這個屬性去進行一個配置,然後重啟的策略有三個,分別如下:
  • Always:容器失效時,即重啟
  • OnFailure:容器終止執行且退出碼不為0時重啟
  • Never:永遠不重啟
 

三、靜態Pod

靜態Pod是由kubelet進行管理的,並且存在於特定的Node上,比喻像master。不能通過API Server進行管理,它是由kubelet進行管理的,無法與ReplicationController,Ddeployment或者DaemonSet進行關聯,也無法進行健康檢查。這個東西怎麼理解呢?這樣說吧,我們在檢視kubectl get pods -n kube-system時會發現系統的這個名稱空間之下,我們一裝完網路外掛之後會有很多Pod,按照之前我寫的文章邏輯來想,這個pod至少要有一個yaml檔案才能建立的,但是我們發現剛剛命令下的系統空間的pod我們並沒有寫他們的pod,那麼它是怎麼來的呢?其實這東西很簡單,當我們用命令kubeadm-init命令時他會在我們的etc/kubernetes/目錄之下會有一個manifests目錄,這個manifests中會有很多系統需要的很多元件的pod.yaml檔案;這些玩意都是系統給我們提供的,這些元件的pod是由kubelet統一管理的,這些pod我們會習慣叫他靜態pod,之所以叫他靜態Pod是因為他不會有一個獨立的網路,可以通過檢視pod詳情命令kubectl get pods -n kube-system -o wide可以看到一個點,就是系統元件的pod用的是master節點的ip,並沒有用到虛擬ip,所以也驗證了他不是API Server進行管理的,是由kubelet進行統一管理的,所以也無法與ReplicationController,Ddeployment或者DaemonSet進行關聯和通訊,也無法進行健康檢查,所以我們習慣把他叫做靜態pod。

四、健康檢查

官網:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes

 經過前面幾個步驟,pod有生命週期了,有重啟策略了,也有固定ip了,接下來pod在進行建立的時候還需要進行健康檢查才能夠進行正常的建立,下面是官網對健康檢查的說明

 

 

 健康檢查是通過兩個屬性進行的:

  • LivenessProbe探針:判斷容器是否存活
  • ReadinessProbe探針:判斷容器是否啟動完成

五、ConfifigMap

官網:https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/

 

 

 官網的介紹說白了就是用來儲存配置資料的鍵值對,也可以儲存單個屬性,也可以儲存配置檔案。所有的配置內容都儲存在etcd中,建立的資料可以供Pod使用。下面來分享下三種建立的方式

5.1、命令列建立

建立一個名稱為my-config的ConfigMap,key值時db.port,value值是3306

kubectl create configmap my-config --from-literal=db.port='3306'

通過命令檢視,會發現在系統的預設空間下建立了一個my-config

kubectl get configmap

檢視yaml檔案對應的格式

kubectl get configmap myconfig -o yaml

5.2、從配置檔案中建立

建立一個檔案,名稱為app.properties,然後在建立的檔案中加入下面兩句話

name=ghy
age=2

然後根據檔案去建立

kubectl create configmap app --from-file=./app.properties

通過命令檢視,會發現在系統的預設空間下建立了一個app

kubectl get configmap

檢視yaml檔案對應的格式

kubectl get configmap app -o yaml

5.3、通過yaml檔案建立

新建一個configmaps.yaml,並把檔案放進去

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

啟動yaml檔案

kubectl apply -f configmaps.yaml

通過命令檢視,會發現在系統的預設空間下建立了一個env-config和special-config兩個

kubectl get configmap

建立CONFIGMAP的動作完成後接下來就是去使用他了。

5.4、ConfigMap的使用

使用方式:

  • 通過環境變數的方式,直接傳遞給pod
    • 使用configmap中指定的key
    • 使用configmap中所有的key
  • 通過在pod的命令列下執行的方式(啟動命令中)
  • 作為volume的方式掛載到pod內

注意

  • ConfigMap必須在Pod使用它之前建立
  • 使用envFrom時,將會自動忽略無效的鍵
  • Pod只能使用同一個名稱空間的ConfigMap

5.4.1、作為volume掛載使用

將建立的ConfigMap直接掛載至Pod的/etc/config目錄下,其中每一個key-value鍵值對都會生成一個檔案,key為檔名,value為內容。

建立一個pod-configmap.yaml檔案

apiVersion: v1
kind: Pod
metadata:
  name: pod-configmap2
spec:
  containers:
    - name: test-container
      image: busybox
      command: [ "/bin/sh", "-c", "ls /etc/config/" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

上面的意思很簡單就是pod裡面有一個busybox的containers,他會往虛擬機器的/etc/config目錄下把configMap的key和value以目錄的形式掛載進去;

啟動指令碼

kubectl apply -f pod-myconfigmap.yml

可以用下面命令看是否建立成功

kubectl get pods

進入容器目錄然後會找到上面說的東西

kubectl exec -it pod-configmap2 bash

 六、Secret

 官網:https://kubernetes.io/docs/concepts/configuration/secret/

這塊內容是關於資料安全性東西,前面的ConfigMap的配置檔案什麼的大家也看了,但現在的檔案配置都是明文的,如果有些東西不想明文展示,那怎麼搞呢

 

 6.1、Secret型別

secret一共有三種型別:

  • Opaque:使用base64編碼儲存資訊,可以通過`base64 --decode`解碼獲得原始資料,因此安全性弱。
  • kubernetes.io/dockerconfigjson:用於儲存docker registry的認證資訊。
  • kubernetes.io/service-account-token:用於被 serviceaccount 引用。serviceaccout 建立時 Kubernetes 會預設建立對應的 secret。Pod 如果使用了 serviceaccount,對應的 secret 會自動掛載到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目錄中。

6.2、Opaque Secret

 Opaque型別的Secret的value為base64位編碼後的值

 6.2.1、 從檔案中建立

echo -n "admin" > ./username.txt
echo -n "1f2d1e2e67df" > ./password.txt
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
kubectl get secret

6.2.2、 使用yaml檔案建立

(1)對資料進行64位編碼

echo -n 'admin' | base64
echo -n '1f2d1e2e67df' | base64

(2)定義mysecret.yaml檔案

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

(3)根據yaml檔案建立資源並檢視

kubectl create -f ./secret.yaml
kubectl get secret
kubectl get secret mysecret -o yaml

6.3 Secret使用

通過6.2.2的方式就得到了一個secret檔案,接下來就這個檔案使用進行說明下。他的使用有兩種方式

  • 以Volume方式
  • 以環境變數方式

6.3.1、 將Secret掛載到Volume中

(1)建立mypod.yaml檔案

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

(2)用命令啟動

kubectl apply -f mypod.yaml

(3)進入容器裡面

kubectl exec -it mypod bash

(4)進入在配置檔案定義的目錄會發現目錄是建立成功的

cd /etc/foo

(5)也可以用如下命令看建立的內容

cat /etc/foo/username
cat /etc/foo/password

6.3.2、 將Secret設定為環境變數

(1)配置檔案如下,重要環境變數配置我標記出來了

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
- name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
  restartPolicy: Never

6.4 、kubernetes.io/dockerconfigjson

kubernetes.io/dockerconfigjson用於儲存docker registry的認證資訊,可以直接使用`kubectl create secret`命令建立

6.5、 kubernetes.io/service-account-token

這個是用於被 serviceaccount 引用。serviceaccout 建立時 Kubernetes 會預設建立對應的 secret。Pod 如果使用了 serviceaccount,對應的 secret 會自動掛載到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目錄中。

kubectl get secret   # 可以看到service-account-token
kubectl run nginx --image nginx
kubectl get pods
kubectl exec -it nginx-pod-name bash
ls /run/secrets/kubernetes.io/serviceaccount
kubectl get secret
kubectl get pods pod-name -o yaml   
#  找到volumes選項,定位到-name,secretName
#  找到volumeMounts選項,定位到mountPath: /var/run/secrets/kubernetes.io/serviceaccount

總結:

無論是ConfigMap,Secret,還是DownwardAPI,都是通過ProjectedVolume實現的,可以通過APIServer將資訊放到Pod中進行使用。

七、指定Pod所執行的Node

(1)給node打上label

kubectl get nodes
kubectl label nodes worker02-kubeadm-k8s name=ghy

(2)檢視node是否有上述label

kubectl describe node worker02-kubeadm-k8s

(3)部署一個mysql的pod

vi mysql-pod.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql-rc
  labels:
    name: mysql-rc
spec:
  replicas: 1
  selector:
    name: mysql-pod
  template:
    metadata:
      labels: 
        name: mysql-pod
    spec:
      nodeSelector: 
        name: ghy
      containers:
      - name: mysql
        image: mysql
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "mysql"
      
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
  labels: 
    name: mysql-svc
spec:
  type: NodePort
  ports:
  - port: 3306
    protocol: TCP
    targetPort: 3306
    name: http
    nodePort: 32306
  selector:
    name: mysql-pod

(4)檢視pod執行詳情

kubectl apply -f mysql-pod.yaml
kubectl get pods -o wide

相關文章