1. 程式人生 > 其它 >7.Kubernetes核心技術Pod

7.Kubernetes核心技術Pod

一、Pod概述

Pod是K8S系統中可以建立和管理的最小單元,是資源物件模型中由使用者建立或部署的最小資源物件模型,也是在K8S上執行容器化應用的資源物件,其它的資源物件都是用來支撐或者擴充套件Pod物件功能的,比如控制器物件是用來管控Pod物件的,Service或者Ingress資源物件是用來暴露Pod引用物件的,PersistentVolume資源物件是用來為Pod提供儲存等等,K8S不會直接處理容器,而是Pod,Pod是由一個或多個container組成。

Pod是Kubernetes的最重要概念,每一個Pod都有一個特殊的被稱為 “根容器”的Pause容器。Pause容器對應的映象屬於Kubernetes平臺的一部分,除了Pause容器,每個Pod還包含一個或多個緊密相關的使用者業務容器。

Pod基本概念

  • 最小部署的單元
  • Pod裡面是由一個或多個容器組成【一組容器的集合】
  • 一個pod中的容器是共享網路名稱空間
  • Pod是短暫的
  • 每個Pod包含一個或多個緊密相關的使用者業務容器

Pod存在的意義

  • 建立容器使用docker,一個docker對應一個容器,一個容器執行一個應用程序
  • Pod是多程序設計,運用多個應用程式,也就是一個Pod裡面有多個容器,而一個容器裡面執行一個應用程式

  • Pod的存在是為了親密性應用
    • 兩個應用之間進行互動
    • 網路之間的呼叫【通過127.0.0.1 或 socket】
    • 兩個應用之間需要頻繁呼叫

Pod實現機制

主要有以下兩大機制

  • 共享網路
  • 共享儲存

共享網路

容器本身之間相互隔離的,一般是通過 namespace 和 group進行隔離,那麼Pod裡面的容器如何實現通訊?

  • 首先需要滿足前提條件,也就是容器都在同一個namespace之間

關於Pod實現原理,首先會在Pod會建立一個根容器:pause容器,然後我們在建立業務容器 【nginx,redis 等】,在我們建立業務容器的時候,會把它新增到info容器

而在info容器中會獨立出 ip地址,mac地址,port 等資訊,然後實現網路的共享

完整步驟如下

  • 通過 Pause 容器,把其它業務容器加入到Pause容器裡,讓所有業務容器

共享儲存

Pod持久化資料,專門儲存到某個地方中

使用 Volumn資料捲進行共享儲存,案例如下所示

二、Pod映象拉取策略

我們以具體例項來說,拉取策略就是imagePullPolicy

拉取策略主要分為了以下幾種

  • IfNotPresent:預設值,映象在宿主機上不存在才拉取
  • Always:每次建立Pod都會重新拉取一次映象
  • Never:Pod永遠不會主動拉取這個映象

三、Pod資源限制

也就是我們Pod在進行排程的時候,可以對排程的資源進行限制,例如我們限制 Pod排程是使用的資源是 2c4g,那麼在排程對應的node節點時,只會佔用對應的資源,對於不滿足資源的節點,將不會進行排程

示例

我們在下面的地方進行資源的限制

這裡分了兩個部分

  • request:表示排程所需的資源
  • limits:表示最大所佔用的資源

四、Pod重啟機制

因為Pod中包含了很多個容器,假設某個容器初選問題了,那麼就會觸發Pod重啟機制

重啟策略主要分為以下三種

  • Always:當容器終止退出後,總是重啟容器,預設策略 【nginx等,需要不斷提供服務】
  • OnFailure:當容器異常退出(退出狀態碼非0)時,才重啟容器。
  • Never:當容器終止退出,從不重啟容器 【批量任務】

五、Pod健康檢查

通過容器檢查,原來我們使用下面的命令來檢查

kubectl get pod

但是有的時候,程式可能出現了java堆記憶體溢位,程式還在執行,但是不能對外提供服務了,這個時候就不能通過 容器檢查來判斷服務是否可用了

這個時候就可以使用應用層面的檢查

# 存活檢查,如果檢查失敗,將殺死容器,根據Pod的restartPolicy【重啟策略】來操作
livenessProbe

# 就緒檢查,如果檢查失敗,Kubernetes會把Pod從Service endpoints中剔除
readinessProbe

Probe支援以下三種檢查方式

  • http Get:傳送HTTP請求,返回200 - 400 範圍狀態碼為成功
  • exec:執行Shell命令返回狀態碼是0為成功
  • tcpSocket:發起TCP socket建立成功

六、Pod排程策略

建立Pod流程

  • 首先建立一個pod,然後建立一個API Server 和 Etcd【把創建出來的資訊儲存在etcd中】
  • 然後建立 Scheduler,監控API Server是否有新的Pod,如果有的話,會通過排程演算法,把pod排程某個node上
  • 在node節點,會通過kubelet -- apiserver讀取etcd 拿到分配在當前node節點上的pod,然後通過docker建立容器

影響Pod排程的屬性

Pod資源限制對Pod的排程會有影響

根據request找到足夠node節點進行排程

節點選擇器標籤影響Pod排程

關於節點選擇器,其實就是有兩個環境,然後環境之間所用的資源配置不同

我們可以通過以下命令,給我們的節點新增標籤,然後節點選擇器就會進行排程了

kubectl label node node1 env_role=prod

節點親和性

節點親和性nodeAffinity和 之前nodeSelector 基本一樣的,根據節點上標籤約束來決定Pod排程到哪些節點上

  • 硬親和性:約束條件必須滿足
  • 軟親和性:嘗試滿足,不保證

支援常用操作符:in、NotIn、Exists、Gt、Lt、DoesNotExists

反親和性:就是和親和性剛剛相反,如 NotIn、DoesNotExists等

汙點和汙點容忍

概述

nodeSelector 和 NodeAffinity,都是Prod排程到某些節點上,屬於Pod的屬性,是在排程的時候實現的。

Taint 汙點:節點不做普通分配排程,是節點屬性

場景

  • 專用節點【限制ip】
  • 配置特定硬體的節點【固態硬碟】
  • 基於Taint驅逐【在node1不放,在node2放】

檢視汙點情況

kubectl describe node k8smaster | grep Taint

汙點值有三個

  • NoSchedule:一定不被排程
  • PreferNoSchedule:儘量不被排程【也有被排程的機率】
  • NoExecute:不會排程,並且還會驅逐Node已有Pod

未節點新增汙點

kubectl taint node [node] key=value:汙點的三個值

舉例:

kubectl taint node k8snode1 env_role=yes:NoSchedule

刪除汙點

kubectl taint node k8snode1 env_role:NoSchedule-

演示

我們現在建立多個Pod,檢視最後分配到Node上的情況

首先我們建立一個 nginx 的pod

kubectl create deployment web --image=nginx

然後使用命令檢視

kubectl get pods -o wide

我們可以非常明顯的看到,這個Pod已經被分配到 k8snode1 節點上了

下面我們把pod複製5份,在檢視情況pod情況

kubectl scale deployment web --replicas=5

我們可以發現,因為master節點存在汙點的情況,所以節點都被分配到了 node1 和 node2節點上

我們可以使用下面命令,把剛剛我們建立的pod都刪除

kubectl delete deployment web

現在給了更好的演示汙點的用法,我們現在給 node1節點打上汙點

kubectl taint node k8snode1 env_role=yes:NoSchedule

然後我們檢視汙點是否成功新增

kubectl describe node k8snode1 | grep Taint

然後我們在建立一個 pod

# 建立nginx pod
kubectl create deployment web --image=nginx
# 複製五次
kubectl scale deployment web --replicas=5

然後我們在進行檢視

kubectl get pods -o wide

我們能夠看到現在所有的pod都被分配到了 k8snode2上,因為剛剛我們給node1節點設定了汙點

最後我們可以刪除剛剛新增的汙點

kubectl taint node k8snode1 env_role:NoSchedule-

汙點容忍

汙點容忍就是某個節點可能被排程,也可能不被排程