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-
汙點容忍
汙點容忍就是某個節點可能被排程,也可能不被排程