k8s之深入解剖Pod(一)

Liusy01發表於2020-12-20

上文說了一下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

  

k8s之深入解剖Pod(一)

 

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

restartPolicy

容器重啟策略:

spec:
  restartPolicy: [Always|Never|OnFailure]  

  

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

nodeSelector

指定Pod被排程到哪個節點執行。

spec:
  nodeSelector: 
    K: V

  

比如想把一個Pod排程給cnode-2節點執行:

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

k8s之深入解剖Pod(一)

 

給cnode-2節點打標籤:

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

  

k8s之深入解剖Pod(一)

 

檢視cnode-2節點標籤資訊:

k8s之深入解剖Pod(一)

 

定義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執行在哪個節點:

k8s之深入解剖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是否相同

k8s之深入解剖Pod(一)

 

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

  

k8s之深入解剖Pod(一)

 

檢視配置檔案:

k8s之深入解剖Pod(一)

 

啟動引數配置在一個叫/var/lib/kubelet/config.yaml的檔案中

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

k8s之深入解剖Pod(一)

 

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

k8s之深入解剖Pod(一)

 

這四個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

k8s之深入解剖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

k8s之深入解剖Pod(一)

 

此時在目錄下放置一個yaml檔案

k8s之深入解剖Pod(一)

 

儲存後就可以檢視到相應的Pod是否已建立

k8s之深入解剖Pod(一)

 

【注意】如果Pod沒建立成功,可以使用如下命令檢視日誌

systemctl status kubelet -l

  

k8s之深入解剖Pod(一)

 

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

k8s之深入解剖Pod(一)

 

,痛苦的教訓

Http方式

通過設定kubelet的啟動引數“--manifest-url”,kubelet將會定期從該URL地址下載Pod的定義檔案,並以.yaml或.json檔案的格式進行解析, 然後建立Pod。其實現方式與配置檔案方式是一致的。

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

三、Pod容器共享Volume

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

k8s之深入解剖Pod(一)

 

比如: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

  

k8s之深入解剖Pod(一)

 

進入tomcat容器中檢視日誌檔案:

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

  

進入在Pod建立時設定的日誌目錄:

/usr/local/tomcat/logs

  

k8s之深入解剖Pod(一)

 

 

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

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

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

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

相關文章