Kubernetes的Pod進階(十一)

一、Lifecycle

官網://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。

四、健康檢查

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

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

 

 

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

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

五、ConfifigMap

官網://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

 官網://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
Tags: