k8s之深入解剖Pod(一)

上文說了一下k8s的簡單使用,接下來就讓我們來具體深入了解一下Pod。為了避免篇幅太長,所以會分成幾篇。

目錄:

  • Pod定義詳解
  • 靜態Pod
  • Pod容器共享Volume

一、Pod定義詳解

先看一個簡單的nginx的Pod定義:

apiVersion: v1
kind: Pod
metadata:
  nam: nginx-test
  labels:
    app: nginx-test
spec:
  containers:
  - name: nginx-test
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80

  

上述是一個Pod內包含一個容器,容器中運行nginx,容器對外暴漏80埠

Pod定義主要分成四大塊:

(1)api

apiVersion: v1

  

(2)kind

kind: Pod

  

(3)metadata

metadata是Pod的元數據定義

metadata: #元數據
  name: string #Pod名稱
  namespace: string #Pod所屬命名空間,預設默認是default
  labels:  #自定義標籤列表
    - key: value
  annotations:  #自定義註解列表
    - key: value

  

(4)spec

spec是Pod中容器的詳細定義,主要分成以下幾塊

containers

containers是Pod中的容器列表,數組類型。

spec:
  containers:  #容器列表
  - name: string  #容器名稱
    image: string  #所用鏡像
    imagePullPolicy: [Always|Never|IfNotPresent]  #鏡像拉取策略
    command: [string]  #容器的啟動命令列表
    args: [string]  #啟動命令參數列表
    workingDir: string  #工作目錄
    volumeMounts:  #掛載在容器內部的存儲卷配置
    - name: string  #共享存儲卷名稱
      mountPath: string  #存儲卷絕對路徑
      readOnly: boolean  #是否只讀
    ports:  #容器需要暴露的埠號列表
    - name: string  #埠名稱
      containerPort: int  #容器監聽埠
      hostPort: int  #映射宿主機埠
      protocol: string  #埠協議
    env:  #環境變數
    - name: string
      value: string
    resources:  #資源限制
      limits:
        cpu: string  #單位是core
        memory: string  #單位是MiB、GiB
    livenessProbe:  #探針,對Pod各容器健康檢查的設置,如幾次無回應,則會自動重啟
      exec:
        command: [string]
      httpGet:
        path: string
        port: number
        host: string
        scheme: string
        httpHeaders:
        - name: string
          value: string
      tcpSocket:
        port: number
      initialDelaySeconds: 0  #啟動後多久進行檢測
      timeoutSeconds: 0  #超時時間
      periodSeconds: 0  #間隔時間
      successThreshold: 0  #
      failureThreshold: 0
    securityContext: #許可權設置
      privileged: false  #是否允許創建特權模式的Pod

  

探針測試:

列出文件或文件夾aaa(此目錄是不存在的),容器啟動後5s開始執行探針,每隔5s執行一次,

apiVersion: v1
kind: Pod
metadata:
  name: nginx-test
  labels:
    app: nginx-test
spec:
  containers:
  - name: nginx-test
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    livenessProbe:
      exec:
        command: ["ls","aaa"]
      initialDelaySeconds: 5
      timeoutSeconds: 5

  

查看探針三次失敗後是否有重啟容器:

使用如下命令查看容器的Event項

kubectl describe pods/nginx-test

  

 

從上圖可以看到,容器重啟了5次

restartPolicy

容器重啟策略:

spec:
  restartPolicy: [Always|Never|OnFailure]  

  

  • Always:Pod一旦終止運行,kubelet都會進行重啟,這也是默認值
  • Never:不會進行重啟
  • OnFailure:容器非正常退出(即是退出碼不為0),kubelet會重啟容器,反之不會重啟。

nodeSelector

指定Pod被調度到哪個節點運行。

spec:
  nodeSelector: 
    K: V

  

比如想把一個Pod調度給cnode-2節點運行:

獲取集群中所有節點列表:

 

給cnode-2節點打標籤:

kubectl label nodes/cnode-2 name=cnode-2

  

 

查看cnode-2節點標籤資訊:

 

定義Pod的yaml文件:nginx-ns.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-test
  labels:
    app: nginx-test
spec:
  containers:
  - name: nginx-test
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
  nodeSelector:
    name: cnode-2

  

使用如下命令創建Pod:

kubectl create -f nginx-ns.yaml

  

查看這個Pod運行在哪個節點:

 

imagePullSecrets

拉取鏡像時使用的Secret名稱,以name:secretKey格式指定

spec:
  imagePullSecrets:
    name: secretKey

  

Secret是用來保存私密憑據的,比如密碼等資訊

hostNetwork

是否使用主機網路模式

spec:
  hostNetwork: true|false

  

如果使用主機網路模式的話,Pod的IP就是跟宿主機IP是一樣的

例如:創建下列Pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx-test
  labels:
    app: nginx-test
spec:
  containers:
  - name: nginx-test
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
  nodeSelector:
    name: cnode-3
  hostNetwork: true

  

然後查看Pod被分配的IP與主機IP是否相同

 

volumes

Pod上定義的共享存儲列表:

spec:
  volumes:  #存儲卷
  - name: string
    emptyDir: {}  #表示與Pod同生命周期的一個臨時目錄
    hostPath:  #宿主機Host
      path: string
    secret: #掛載集群預定義的secret對象到容器內部
      secretName: string
      items:
      - key: string
        path: string
    configMap: #掛載集群預定義的configMap對象到容器內部
      name: string
      items:
      - key: string
        path: string

  

二、靜態Pod

由kubelet管理的僅存在於特定Node上的Pod,不能通過API Service進行管理,無法與RC、deployment或DaemonSet進行關聯,並且kubelet也無法對他們進行健康檢查,有kubelet創建並運行在kubelet所在的Node上運行。

靜態Pod的yaml文件在修改之後,kubelet會進行自動重啟該Pod至配置文件生效

創建靜態Pod有兩種方式:配置文件或者HTTP方式。

下面說一下配置文件的創建方式:

配置文件

需要設置kubelet啟動參數「–config」,指定kubelet需要監控的配置文件所在的目錄,kubelet會定期掃描該目錄,並根據目錄中的yaml或json文件進行創建操作

(1)如果集群是通過kubeadm創建的,那麼已經配置好了靜態pod的路徑

查看kubelet的啟動參數配置文件路徑:

systemctl status kubelet

  

 

查看配置文件:

 

啟動參數配置在一個叫/var/lib/kubelet/config.yaml的文件中

在此文件中會發現由下圖中的配置,也就是靜態Pod路徑配置為/etc/kubernetes/manifests路徑

 

所以只需要將靜態Pod的yaml文件放置在此目錄下即可。

 

這四個Master上運行的核心組件就是通過此方式進行創建的。

例如上圖中我將static-nginx.yaml放到/etc/kubernetes/manifests目錄下:

apiVersion: v1
kind: Pod
metadata:
  name: static-nginx
  labels:
    name: static-nginx
spec:
  containers:
  - name: static-nginx
    image: nginx
    ports:
    - containerPort: 80

  

此時使用kubelet get pods就可以查看到相應的Pod

 

(2)如果不是由kubeadm創建的集群,則需要在kubelet啟動參數配置文件中添加如下一行:

Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true

  

修改配置之後需要重啟kubelet

systemctl stop kubelet
systemctl daemon-reload
systemctl start kubelet

  

例如我在cnode-2上配置了kubelet的啟動參數,將靜態Pod文件目錄設置為/usr/soft/k8s/yaml/staticPod,然後重啟kubelet

 

此時在目錄下放置一個yaml文件

 

保存後就可以查看到相應的Pod是否已創建

 

【注意】如果Pod沒創建成功,可以使用如下命令查看日誌

systemctl status kubelet -l

  

 

我這邊因為是之前配置了Pod安全策略,所以導致無法創建,我排查了一天啊我天

 

,痛苦的教訓

Http方式

通過設置kubelet的啟動參數「–manifest-url」,kubelet將會定期從該URL地址下載Pod的定義文件,並以.yaml或.json文件的格式進行解析, 然後創建Pod。其實現方式與配置文件方式是一致的。

【注意】靜態Pod無法通過kubectl delete進行刪除,只能刪除對應的yaml文件

三、Pod容器共享Volume

在同一個Pod中的多個容器能夠共享Pod級別的存儲卷Volume,可以定義為各種類型,至於Volume是何種類型,在k8s基本概念中已有提到,多個容器各自進行掛載,將一個Volume掛在為容器內部需要的目錄

 

比如:Pod裡面有兩個容器,分別是tomcat和busybox,tomcat往/usr/local/tomcat/logs寫日誌,busybox從/logs目錄讀取日誌。

新建一個yaml文件:

這裡設置的Volume名為app-logs,類型為emptyDir,掛載到tomcat容器內 的/usr/local/tomcat/logs目錄,同時掛載到busybox容器內的/logs目錄。

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: app-logs
      mountPath: /usr/local/tomcat/logs
  - name: busybox
    image: busybox
    command: ["sh","-c","tail -f /logs/catalina*.log"]
    volumeMounts:
    - name: app-logs
      mountPath: /logs
  volumes:
  - name: app-logs
    emptyDir: {}

  

創建之後查看busybox的日誌輸出:

kubectl logs pods/volume-pod -c busybox

  

 

進入tomcat容器中查看日誌文件:

#進入tomcat容器,-c參數指明是哪個容器
kubectl exec -it pods/volume-pod -c tomcat /bin/bash

  

進入在Pod創建時設置的日誌目錄:

/usr/local/tomcat/logs

  

 

 

===============================

我是Liusy,一個喜歡健身的程式設計師。

歡迎關注微信公眾號【Liusy01】,一起交流Java技術及健身,獲取更多乾貨,領取Java進階乾貨,領取最新大廠面試資料,一起成為Java大神。

來都來了,關注一波再溜唄。