沈陽網站制作定制廠家站內營銷推廣方式
文章目錄
- 一.pod集群調度概念
- 1.調度約束( List-Watch組件)
- 2.List-Watch的工作機制
- (1)List-Watch的工作機制流程
- (2)List-Watch的工作機制圖示
- 3.調度的過程
- (1)調度的任務
- (2)調度選擇pod節(jié)點
- (3)調度的過程
- (4)調度的算法
- (5)調度的優(yōu)先級
- 二.pod集群調度示例
- 1.指定調度節(jié)點示例
- 2.通過節(jié)點標簽調度(nodeSelector)示例
- 3.平均調度節(jié)點示例
- 三.親和性(節(jié)點親和、pod親和)
- 1.節(jié)點親和
- (1)節(jié)點親和概念
- (2)鍵值運算關系
- (3)創(chuàng)建節(jié)點硬策略親和示例:
- (4)創(chuàng)建節(jié)點軟策略親和示例:
- (5)節(jié)點軟硬策略親和示例
- 2.pod親和性與反親和性
- (1)Pod親和性與反親和性的調整策略
- (2)Pod親和性示例
- (3)Pod 反親和性調度示例1
- (4)Pod 反親和性調度示例2
- 四.污點(Taint) 和 容忍(Tolerations)
- 1.污點(Taint)
- (1)污點概念
- (2)污點的組成格式及污點的存在選項
- (3)查看節(jié)點污點
- (4)節(jié)點污點示例
- 2.容忍(Tolerations)
- (1)容忍(Tolerations)概念
- (2)節(jié)點容忍示例
- (3)污點注意事項
- 五.維護操作
- 1.cordon調度器
- (1)對節(jié)點執(zhí)行維護操作
- (2)cordon調度器
- 2.drain命令
- 六.Pod啟動階段(相位 phase)
- 1.pod啟動過程
- 2.phase 的可能狀態(tài)
- 3.故障排除步驟
- 總:
- 1.list-watch
- 2.scheduler
- 3.pod 調度到指定節(jié)點的方法
- 4.節(jié)點親和性和反親和性
- 5.相關標簽命令
- 6.污點和容忍
- 7.Pod啟動階段(相位) 5個狀態(tài)
- 8.排除故障方法
一.pod集群調度概念
1.調度約束( List-Watch組件)
Kubernetes 是通過 List-Watch的機制進行每個組件的協(xié)作,保持數據同步的,每個組件之間的設計實現了解耦。
用戶是通過 kubectl 根據配置文件,向 APIServer 發(fā)送命令,在 Node 節(jié)點上面建立 Pod 和 Container。
APIServer 經過 API 調用,權限控制,調用資源和存儲資源的過程,實際上還沒有真正開始部署應用。這里 需要 Controller Manager、Scheduler 和 kubelet 的協(xié)助才能完成整個部署過程。
2.List-Watch的工作機制
(1)List-Watch的工作機制流程
在 Kubernetes 中,所有部署的信息都會寫到 etcd 中保存。實際上 etcd 在存儲部署信息的時候,會發(fā)送 Create 事件給 APIServer,而 APIServer 會通過監(jiān)聽(Watch)etcd 發(fā)過來的事件。其他組件也會監(jiān)聽(Watch)APIServer 發(fā)出來的事件。
Pod 是 Kubernetes 的基礎單元,Pod 啟動典型創(chuàng)建過程如下:工作機制
(1)這里有三個 List-Watch,分別是 Controller Manager(運行在 Master),Scheduler(運行在 Master),kubelet(運行在 Node)。 他們在進程已啟動就會監(jiān)聽(Watch)APIServer 發(fā)出來的事件。
(2)用戶通過 kubectl 或其他 API 客戶端提交請求給 APIServer 來建立一個 Pod 對象副本。
(3)APIServer 嘗試著將 Pod 對象的相關元信息存入 etcd 中,待寫入操作執(zhí)行完成,APIServer 即會返回確認信息至客戶端。
(4)當 etcd 接受創(chuàng)建 Pod 信息以后,會發(fā)送一個 Create 事件給 APIServer。
(5)由于 Controller Manager 一直在監(jiān)聽(Watch,通過https的6443端口)APIServer 中的事件。此時 APIServer 接受到了 Create 事件,又會發(fā)送給 Controller Manager。
(6)Controller Manager 在接到 Create 事件以后,調用其中的 Replication Controller 來保證 Node 上面需要創(chuàng)建的副本數量。一旦副本數量少于 RC 中定義的數量,RC 會自動創(chuàng)建副本??傊潜WC副本數量的 Controller(PS:擴容縮容的擔當)。
(7)在 Controller Manager 創(chuàng)建 Pod 副本以后,APIServer 會在 etcd 中記錄這個 Pod 的詳細信息。例如 Pod 的副本數,Container 的內容是什么。
(8)同樣的 etcd 會將創(chuàng)建 Pod 的信息通過事件發(fā)送給 APIServer。
(9)由于 Scheduler 在監(jiān)聽(Watch)APIServer,并且它在系統(tǒng)中起到了“承上啟下”的作用,“承上”是指它負責接收創(chuàng)建的 Pod 事件,為其安排 Node;“啟下”是指安置工作完成后,Node 上的 kubelet 進程會接管后繼工作,負責 Pod 生命周期中的“下半生”。 換句話說,Scheduler 的作用是將待調度的 Pod 按照調度算法和策略綁定到集群中 Node 上。
(10)Scheduler 調度完畢以后會更新 Pod 的信息,此時的信息更加豐富了。除了知道 Pod 的副本數量,副本內容。還知道部署到哪個 Node 上面了。并將上面的 Pod 信息更新至 API Server,由 APIServer 更新至 etcd 中,保存起來。
(11)etcd 將更新成功的事件發(fā)送給 APIServer,APIServer 也開始反映此 Pod 對象的調度結果。
(12)kubelet 是在 Node 上面運行的進程,它也通過 List-Watch 的方式監(jiān)聽(Watch,通過https的6443端口)APIServer 發(fā)送的 Pod 更新的事件。kubelet 會嘗試在當前節(jié)點上調用 Docker 啟動容器,并將 Pod 以及容器的結果狀態(tài)回送至 APIServer。
(13)APIServer 將 Pod 狀態(tài)信息存入 etcd 中。在 etcd 確認寫入操作成功完成后,APIServer將確認信息發(fā)送至相關的 kubelet,事件將通過它被接受。
#注意:在創(chuàng)建 Pod 的工作就已經完成了后,為什么 kubelet 還要一直監(jiān)聽呢?原因很簡單,假設這個時候 kubectl 發(fā)命令,要擴充 Pod 副本數量,那么上面的流程又會觸發(fā)一遍,kubelet 會根據最新的 Pod 的部署情況調整 Node 的資源。又或者 Pod 副本數量沒有發(fā)生變化,但是其中的鏡像文件升級了,kubelet 也會自動獲取最新的鏡像文件并且加載。
總:三個組件(contrllor manager、scheduler、kubelet)監(jiān)聽apiserver,通過端口,來看調度、擴容、縮容、升級等)
縮容、擴容、鏡像升級的話這些機制都得再來一遍
(2)List-Watch的工作機制圖示
3.調度的過程
(1)調度的任務
Scheduler 是 kubernetes 的調度器,主要的任務是把定義的 pod 分配到集群的節(jié)點上。其主要考慮的問題如下:
●公平:如何保證每個節(jié)點都能被分配資源
●資源高效利用:集群所有資源最大化被使用
●效率:調度的性能要好,能夠盡快地對大批量的 pod 完成調度工作
●靈活:允許用戶根據自己的需求控制調度的邏輯
(2)調度選擇pod節(jié)點
Sheduler 是作為單獨的程序運行的,啟動之后會一直監(jiān)聽 APIServer,獲取 spec.nodeName 為空的 pod,對每個 pod 都會創(chuàng)建一個 binding,表明該 pod 應該放到哪個節(jié)點上。
(3)調度的過程
調度分為幾個部分:首先是過濾掉不滿足條件的節(jié)點,這個過程稱為預算策略(predicate);然后對通過的節(jié)點按照優(yōu)先級排序,這個是優(yōu)選策略(priorities);最后從中選擇優(yōu)先級最高的節(jié)點。如果中間任何一步驟有錯誤,就直接返回錯誤。
(4)調度的算法
Predicate 有一系列的常見的算法可以使用:
●PodFitsResources:節(jié)點上剩余的資源是否大于 pod 請求的資源odeName,檢查節(jié)點名稱是否和 NodeName 匹配
●PodFitsHost:如果 pod 指定了 N
●PodFitsHostPorts:節(jié)點上已經使用的 port 是否和 pod 申請的 port 沖突。
●PodSelectorMatches:過濾掉和 pod 指定的 label 不匹配的節(jié)點。
●NoDiskConflict:已經 mount 的 volume 和 pod 指定的 volume 不沖突,除非它們都是只讀。
(5)調度的優(yōu)先級
如果在 predicate 過程中沒有合適的節(jié)點,pod 會一直在 pending 狀態(tài),不斷重試調度,直到有節(jié)點滿足條件。 經過這個步驟,如果有多個節(jié)點滿足條件,就繼續(xù) priorities 過程:按照優(yōu)先級大小對節(jié)點排序。
優(yōu)先級由一系列鍵值對組成,鍵是該優(yōu)先級項的名稱,值是它的權重(該項的重要性)。有一系列的常見的優(yōu)先級選項包括:
●LeastRequestedPriority:通過計算CPU和Memory的使用率來決定權重,使用率越低權重越高。也就是說,這個優(yōu)先級指標傾向于資源使用比例更低的節(jié)點。
●BalancedResourceAllocation:節(jié)點上 CPU 和 Memory 使用率越接近,權重越高。這個一般和上面的一起使用,不單獨使用。比如 node01 的 CPU 和 Memory 使用率 20:60,node02 的 CPU 和 Memory 使用率 50:50,雖然 node01 的總使用率比 node02 低,但 node02 的 CPU 和 Memory 使用率更接近,從而調度時會優(yōu)選 node02。
●ImageLocalityPriority:傾向于已經有要使用鏡像的節(jié)點,鏡像總大小值越大,權重越高。
通過算法對所有的優(yōu)先級項目和權重進行計算,得出最終的結果。
二.pod集群調度示例
1.指定調度節(jié)點示例
(1)pod.spec.nodeName 將 Pod 直接調度到指定的 Node 節(jié)點上,會跳過 Scheduler 的調度策略,該匹配規(guī)則是強制匹配
vim myapp.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: myapp
spec:replicas: 3selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:nodeName: node01containers:- name: myappimage: soscscs/myapp:v1ports:- containerPort: 80
注釋:
replicas: 3
指定了要創(chuàng)建的 Pod 副本數量為 3。selector
通過標簽選擇器指定了要管理的 Pod 集合,這里使用了app: myapp
標簽。template
定義了創(chuàng)建 Pod 的模板,在其中可以設置容器和其他配置。nodeName: node01
指定了 Pod 應該運行在名為node01
的節(jié)點上。containers
定義了要運行的容器的配置,包括容器名稱、鏡像和端口等信息。將在 Kubernetes 集群中創(chuàng)建 3 個副本的 Deployment,每個 Pod 將運行一個名為
myapp
的容器,并將這些 Pod 調度到名為node01
的節(jié)點上。
kubectl apply -f myapp.yaml
kubectl get pods -o wide
#查看詳細事件(發(fā)現未經過 scheduler 調度分配)
kubectl describe pod myapp-699655c7fd-m87pb
(2)pod.spec.nodeSelector:通過 kubernetes 的 label-selector 機制選擇節(jié)點,由調度器調度策略匹配 label,然后調度 Pod 到目標節(jié)點,該匹配規(guī)則屬于強制約束
#獲取標簽幫助
kubectl label --help
#需要獲取 node 上的 NAME 名稱
kubectl get node
#給對應的 node 設置標簽分別為 blue=a 和 blue=b
kubectl label nodes node01 blue=a
kubectl label nodes node02 blue=b
#查看標簽
kubectl get nodes --show-labels
2.通過節(jié)點標簽調度(nodeSelector)示例
#修改成nodeSelector調度方式
vim myapp1.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: myapp1
spec:replicas: 3selector:matchLabels:app: myapp1template:metadata:labels:app: myapp1spec:nodeSelector:blue: acontainers:- name: myapp1image: soscscs/myapp:v1ports:- containerPort: 80
注釋:
replicas: 3
指定了要創(chuàng)建的 Pod 副本數量為 3。selector
通過標簽選擇器指定了要管理的 Pod 集合,這里使用了app: myapp1
標簽。template
定義了創(chuàng)建 Pod 的模板,在其中可以設置容器和其他配置。nodeSelector
使用了blue: a
條件,表示只有具有標簽blue=a
的節(jié)點才能被選擇來調度 Pod。containers
定義了要運行的容器的配置,包括容器名稱、鏡像和端口等信息。這個部署腳本將在 Kubernetes 集群中創(chuàng)建 3 個副本的 Deployment,每個 Pod 將運行一個名為
myapp1
的容器,并將這些 Pod 調度到帶有標簽blue=a
的節(jié)點上。
kubectl apply -f myapp1.yaml
kubectl get pods -o wide
#查看詳細事件(通過事件可以發(fā)現要先經過 scheduler 調度分配)
kubectl describe pod myapp1-86c7cf9c8c-96w6t
注:如資源大小不足可能會會造成調度失敗
#查看標簽
kubectl get node --show-labels
#修改一個節(jié)點的 label 的值,需要加上 --overwrite 參數
kubectl label nodes node02 blue=a --overwrite
#刪除一個 label,只需在命令行最后指定 label 的 key 名并與一個減號相連即可:
kubectl label nodes node02 blue-
#指定標簽查詢 node 節(jié)點
kubectl get nodes -l blue=a
3.平均調度節(jié)點示例
注:資源大小不足可能會會造成調度失敗
平均放在node1、node2即可使用這個調度方法
#修改標簽,講node01、node02節(jié)點上的標簽都設置為一樣的值
kubectl label nodes node01 blue=a
kubectl label nodes node02 blue=a
kubectl get node --show-labels
#刪除之前創(chuàng)建的
kubectl delete -f myapp1.yamlvim myapp1.yaml apiVersion: apps/v1
kind: Deployment
metadata:name: myapp1
spec:replicas: 3selector:matchLabels:app: myapp1template:metadata:labels:app: myapp1spec:nodeSelector:blue: acontainers:- name: myapp1image: soscscs/myapp:v1ports:- containerPort: 80
#再次創(chuàng)建
kubectl apply -f myapp1.yaml
節(jié)點標簽未平均在node節(jié)點解決辦法
(1)查看剩余大小
free -h
#清緩存,來清除 Linux 系統(tǒng)緩存的操作,這個命令通常用于調優(yōu)系統(tǒng)性能或者在特定情況下需要釋放系統(tǒng)內存時使用。但需要注意的是,清除緩存可能導致一些文件系統(tǒng)的性能下降,因為在重新加載緩存時可能需要一些時間。
echo 3 > /proc/sys/vm/drop_caches
(2)查看節(jié)點是否存在污點
kubectl describe nodes | grep -B 3 Taints
(3)有可能是因為都在一個節(jié)點是節(jié)點的資源過多,此處使用相同的配置文件修改名字,再次創(chuàng)建
cp myapp1.yaml myapp2.yaml
kubectl apply -f myapp2.yaml
三.親和性(節(jié)點親和、pod親和)
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/
1.節(jié)點親和
(1)節(jié)點親和概念
節(jié)點親和:傾向于哪一個node節(jié)點,硬策略是必須是哪一個node節(jié)點,軟策略是最好是哪一個node節(jié)點,但是不是也可以接受。
pod.spec.nodeAffinity
●preferredDuringSchedulingIgnoredDuringExecution:軟策略
●requiredDuringSchedulingIgnoredDuringExecution:硬策略
(2)鍵值運算關系
●In:label 的值在某個列表中 pending————必須是
●NotIn:label 的值不在某個列表中————相反節(jié)點
●Gt:label 的值大于某個值
●Lt:label 的值小于某個值
●Exists:某個 label 存在
●DoesNotExist:某個 label 不存在
軟策略:配置NotIn使用較多
硬策略:in使用較多
(3)創(chuàng)建節(jié)點硬策略親和示例:
可以使用以下命令查看標簽下的選項:
kubectl explain pod.spec.aff1n1ty.nodeAffin1ty.requredDuring5chedulinglgnoredDuringExecut1on.nodeselectorTerms.
編輯文件中的標簽key值:
kubectl get nodes --show-labels
kubectl get nodes --show-labels
mkdir /opt/affinity
cd /opt/affinity
vim pod1.yamlapiVersion: v1
kind: Pod
metadata:name: affinitylabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostname #指定node的標簽operator: NotIn #設置Pod安裝到kubernetes.io/hostname的標簽值不在values列表中的node上values:- node02
注釋:
metadata
部分定義了 Pod 的元數據,包括名稱和標簽。
spec.containers
定義了要在 Pod 中運行的容器的配置,包括容器名稱和鏡像。affinity 定義了節(jié)點親和性配置。
nodeAffinity
指定了使用節(jié)點親和性。
requiredDuringSchedulingIgnoredDuringExecution
表示 Pod 必須滿足指定的節(jié)點親和性規(guī)則。nodeSelectorTerms 定義了要匹配的節(jié)點標簽條件。
matchExpressions 定義了節(jié)點選擇器的匹配表達式。
key
指定了要匹配的節(jié)點標簽鍵,這里使用了kubernetes.io/hostname
表示節(jié)點主機名。operator
定義了匹配操作符,這里使用了NotIn
表示節(jié)點主機名不在指定的列表中。values
定義了不滿足匹配條件的節(jié)點主機名列表,這里只有一個值node02
。因此,這個 Pod 定義了一個節(jié)點親和性規(guī)則,要求將其調度到除了主機名為
node02
的節(jié)點以外的其他節(jié)點上。
kubectl apply -f pod1.yaml
kubectl get pods -o wide
#如果硬策略不滿足條件,Pod 狀態(tài)一直會處于 Pending 狀態(tài)。
如果內存不夠可能也無法使pod狀態(tài)正常
(4)創(chuàng)建節(jié)點軟策略親和示例:
cp pod1.yaml pod2.yaml
vim pod2.yamlapiVersion: v1
kind: Pod
metadata:name: affinity-prlabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 1 #如果有多個軟策略選項的話,權重越大,優(yōu)先級越高preference:matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- node03 #沒有這個節(jié)點服務器會自動分配給存在的其他節(jié)點上
注釋:
metadata
部分定義了 Pod 的元數據,包括名稱和標簽。
spec.containers
定義了要在 Pod 中運行的容器的配置,包括容器名稱和鏡像。affinity 定義了節(jié)點親和性配置。
nodeAffinity
指定了使用節(jié)點親和性。preferredDuringSchedulingIgnoredDuringExecution
表示 Pod 首選滿足指定的節(jié)點親和性規(guī)則的節(jié)點,但不是必須的。
weight
定義了此規(guī)則的權重,在多個規(guī)則存在時,權重越大的規(guī)則優(yōu)先級越高。preference 定義了節(jié)點選擇器的匹配條件。
matchExpressions 定義了節(jié)點選擇器的匹配表達式。
key
指定了要匹配的節(jié)點標簽鍵,這里使用了kubernetes.io/hostname
表示節(jié)點主機名。operator
定義了匹配操作符,這里使用了In
表示節(jié)點主機名在指定的列表中。values
定義了滿足匹配條件的節(jié)點主機名列表,這里只有一個值node03
。因此,這個 Pod 定義了一個首選節(jié)點親和性規(guī)則,優(yōu)先調度到主機名為
node03
的節(jié)點上。如果不存在主機名為node03
的節(jié)點,則該 Pod 將被分配到其它節(jié)點上。
kubectl apply -f pod2.yaml
kubectl get pods -o wide
#把values:的值改成node02,則會優(yōu)先在node02上創(chuàng)建Pod
kubectl delete pod --all && kubectl apply -f pod2.yaml && kubectl get pods -o wide
(5)節(jié)點軟硬策略親和示例
如果把硬策略和軟策略合在一起使用,則要先滿足硬策略之后才會滿足軟策略
vim pod3.yamlapiVersion: v1
kind: Pod
metadata:name: affinity-prelabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution: #先滿足硬策略,排除有kubernetes.io/hostname=node02標簽的節(jié)點nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: NotInvalues:- node02preferredDuringSchedulingIgnoredDuringExecution: #再滿足軟策略,優(yōu)先選擇有blue=a標簽的節(jié)點- weight: 1preference:matchExpressions:- key: blueoperator: Invalues:- a
注釋:
metadata
部分定義了 Pod 的元數據,包括名稱和標簽。
spec.containers
定義了要在 Pod 中運行的容器的配置,包括容器名稱和鏡像。affinity 定義了節(jié)點親和性配置。
nodeAffinity
指定了使用節(jié)點親和性。requiredDuringSchedulingIgnoredDuringExecution 表示 Pod 必須滿足指定的節(jié)點親和性規(guī)則才能被調度到節(jié)點上。
nodeSelectorTerms 定義了節(jié)點選擇器的條件,這里只有一個匹配表達式。
matchExpressions 定義了節(jié)點選擇器的匹配表達式。
key
指定了要匹配的節(jié)點標簽鍵,這里使用了kubernetes.io/hostname
表示節(jié)點主機名。operator
定義了匹配操作符,這里使用了NotIn
表示排除匹配指定節(jié)點主機名的節(jié)點。values
定義了不滿足匹配條件的節(jié)點主機名列表,這里只有一個值node02
。preferredDuringSchedulingIgnoredDuringExecution 表示 Pod 首選滿足指定的節(jié)點親和性規(guī)則的節(jié)點,但不是必須的。
weight
定義了此規(guī)則的權重,在多個規(guī)則存在時,權重越大的規(guī)則優(yōu)先級越高。preference 定義了節(jié)點選擇器的匹配條件。
matchExpressions 定義了節(jié)點選擇器的匹配表達式。
key
指定了要匹配的節(jié)點標簽鍵,這里使用了blue
表示藍色標簽。operator
定義了匹配操作符,這里使用了In
表示節(jié)點標簽值在指定的列表中。values
定義了滿足匹配條件的藍色標簽值列表,這里只有一個值a
。因此,這個 Pod 定義了一個節(jié)點親和性規(guī)則,必須滿足不在
node02
節(jié)點上才能被調度。此外,它還定義了一個首選節(jié)點親和性規(guī)則,優(yōu)先調度到具有藍色標簽值為a
的節(jié)點上。如果不存在滿足這些條件的節(jié)點,則該 Pod 無法被調度。
kubectl apply -f pod3.yaml
kubectl get pod -owide
2.pod親和性與反親和性
pod親和:相同的等級,更傾向于哪一個,就是pod親和性,如果一定要和其中一個平等,就是硬策略;如果是想和一個平等并且最好的是軟策略,軟策略是不去也可以,硬策略則是不去就不行。
(1)Pod親和性與反親和性的調整策略
調度策略 | 匹配標簽 | 操作符 | 拓撲域支持 | 調度目標 |
---|---|---|---|---|
nodeAffinity | 主機 | In, NotIn, Exists,DoesNotExist, Gt, Lt | 否 | 指定主機 |
podAffinity | Pod | In, NotIn, Exists,DoesNotExist | 是 | Pod與指定Pod同一拓撲域 |
podAntiAffinity | Pod | In, NotIn, Exists,DoesNotExist | 是 | Pod與指定Pod不在同一拓撲域 |
(2)Pod親和性示例
kubectl label nodes node01 blue=a
kubectl label nodes node02 blue=a
#創(chuàng)建一個標簽為 app=myapp01 的 Pod
vim pod4.yamlapiVersion: v1
kind: Pod
metadata:name: myapp01labels:app: myapp01
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1
注釋:
apiVersion: v1
表示使用 Kubernetes API 的版本。kind: Pod
表示部署的資源類型是 Pod。metadata
定義了該資源的元數據信息,包括名稱和標簽等屬性。spec
定義了該 Pod 的具體配置信息,包括容器定義、存儲卷和網絡等相關配置。在該 YAML 文件中,Pod 中包含一個容器,容器名稱為
with-node-affinity
,它使用了鏡像soscscs/myapp:v1
,這個鏡像可能是開發(fā)者自己編寫的或從其他地方獲取的。
kubectl apply -f pod4.yaml
kubectl get pods --show-labels -o wide
#使用 Pod 親和性調度,創(chuàng)建多個 Pod 資源
vim pod5.yamlapiVersion: v1
kind: Pod
metadata:name: myapp02labels:app: myapp02
spec:containers:- name: myapp02image: soscscs/myapp:v1affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- myapp01topologyKey: blue
注釋:
文件定義了一個名為
myapp02
的 Pod,其中包含一個名為myapp02
的容器。此外,它還定義了 Pod 間的親和性規(guī)則。在這個規(guī)則中,
myapp02
Pod 要求與具有標簽app: myapp01
的其他 Pod 在拓撲域(topology domain)上保持親和。具體來說,它要求與拓撲域中具有相同blue
屬性的 Pod 保持親和。拓撲域是指一組共享相同資源或特征的節(jié)點。在這個例子中,通過指定
topologyKey
為blue
,myapp02
Pod 希望與擁有相同blue
屬性的其他 Pod 在同一個拓撲域內被調度。這種親和性規(guī)則可以用于將相關的 Pod 部署到相同的拓撲域中,以提高應用程序的性能和可靠性。
#僅當節(jié)點和至少一個已運行且有鍵為“app”且值為“myapp01”的標簽 的 Pod 處于同一拓撲域時,才可以將該 Pod 調度到節(jié)點上。 (更確切的說,如果節(jié)點 N 具有帶有鍵 kgc 和某個值 V 的標簽,則 Pod 有資格在節(jié)點 N 上運行,以便集群中至少有一個具有鍵 blue 和值為 V 的節(jié)點正在運行具有鍵“app”和值 “myapp01”的標簽的 pod。)
#topologyKey 是節(jié)點標簽的鍵。如果兩個節(jié)點使用此鍵標記并且具有相同的標簽值,則調度器會將這兩個節(jié)點視為處于同一拓撲域中。 調度器試圖在每個拓撲域中放置數量均衡的 Pod。
#如果 kgc 對應的值不一樣就是不同的拓撲域。比如 Pod1 在 kgc=a 的 Node 上,Pod2 在 kgc=b 的 Node 上,Pod3 在 blue=a 的 Node 上,則 Pod2 和 Pod1、Pod3 不在同一個拓撲域,而Pod1 和 Pod3在同一個拓撲域。
kubectl apply -f pod5.yaml
kubectl get pods --show-labels -o wide
(3)Pod 反親和性調度示例1
vim pod5f.yamlapiVersion: v1
kind: Pod
metadata:name: myapp10labels:app: myapp10
spec:containers:- name: myapp10image: soscscs/myapp:v1affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- myapp01topologyKey: kubernetes.io/hostname
注釋:
文件定義了一個 Pod 名為
myapp10
,其中包含一個名為myapp10
的容器。此外,它還定義了 Pod 間的反親和性規(guī)則。在本例中,myapp10
Pod 首選與具有標簽app: myapp01
的其他 Pod 在主機名(hostname)拓撲域上保持反親和。具體來說,它首選不與拓撲域中的具有相同主機名的 Pod 一起調度。這可以幫助將相關的 Pod 分散到不同的節(jié)點上。
#如果節(jié)點處于 Pod 所在的同一拓撲域且具有鍵“app”和值“myapp01”的標簽, 則該 pod 不應將其調度到該節(jié)點上。 (如果 topologyKey 為 kubernetes.io/hostname,則意味著當節(jié)點和具有鍵 “app”和值“myapp01”的 Pod 處于相同的拓撲域,Pod 不能被調度到該節(jié)點上。)
kubectl apply -f pod5f.yaml
kubectl get pods --show-labels -o wide
(4)Pod 反親和性調度示例2
vim pod6f.yamlapiVersion: v1
kind: Pod
metadata:name: myapp20labels:app: myapp20
spec:containers:- name: myapp20image: soscscs/myapp:v1affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- myapp01topologyKey: blue
注釋:
文件定義了一個 Pod 名為
myapp20
,其中包含一個名為myapp20
的容器。此外,它還定義了 Pod 間的反親和性規(guī)則。在本例中,myapp20
Pod 要求與具有標簽app: myapp01
的其他 Pod 在拓撲域上保持反親和。具體來說,它要求不與拓撲域中的具有相同blue
屬性的 Pod 一起調度。這可以幫助將相關的 Pod 分散到不同的拓撲域中。由于指定 Pod 所在的 node01 節(jié)點上具有帶有鍵 kgc 和標簽值 a 的標簽,node02 也有這個kgc=a的標簽,所以 node01 和 node02 是在一個拓撲域中,反親和要求新 Pod 與指定 Pod 不在同一拓撲域,所以新 Pod 沒有可用的 node 節(jié)點,即為 Pending 狀態(tài)。
kubectl apply -f pod6f.yaml
kubectl get pod --show-labels -owide
kubectl label nodes node02 blue=b --overwrite
kubectl get pod --show-labels -o wide
四.污點(Taint) 和 容忍(Tolerations)
1.污點(Taint)
(1)污點概念
節(jié)點親和性,是Pod的一種屬性(偏好或硬性要求),它使Pod被吸引到一類特定的節(jié)點。Taint 則相反,它使節(jié)點能夠排斥一類特定的 Pod。
Taint 和 Toleration 相互配合,可以用來避免 Pod 被分配到不合適的節(jié)點上。每個節(jié)點上都可以應用一個或多個 taint ,這表示對于那些不能容忍這些 taint 的 Pod,是不會被該節(jié)點接受的。如果將 toleration 應用于 Pod 上,則表示這些 Pod 可以(但不一定)被調度到具有匹配 taint 的節(jié)點上。
使用 kubectl taint 命令可以給某個 Node 節(jié)點設置污點,Node 被設置上污點之后就和 Pod 之間存在了一種相斥的關系,可以讓 Node 拒絕 Pod 的調度執(zhí)行,甚至將 Node 已經存在的 Pod 驅逐出去。
pod不會將服務部署到有污點的機器上
(2)污點的組成格式及污點的存在選項
key=value:effect
每個污點有一個 key 和 value 作為污點的標簽,其中 value 可以為空,effect 描述污點的作用。
當前 taint effect 支持如下三個選項:
●NoSchedule:表示 k8s 將不會將 Pod 調度到具有該污點的 Node 上
●PreferNoSchedule:表示 k8s 將盡量避免將 Pod 調度到具有該污點的 Node 上
●NoExecute:表示 k8s 將不會將 Pod 調度到具有該污點的 Node 上,同時會將 Node 上已經存在的 Pod 驅逐出去——更換節(jié)點使用
(3)查看節(jié)點污點
kubectl get nodes
#master 就是因為有 NoSchedule 污點,k8s 才不會將 Pod 調度到 master 節(jié)點上
kubectl describe node master
(4)節(jié)點污點示例
#設置污點
kubectl taint node node01 key1=value1:NoSchedule
#節(jié)點說明中,查找 Taints 字段
kubectl describe node node01
vim pod6w.yamlapiVersion: v1
kind: Pod
metadata:name: pod6wlabels:app: node-affinity-pod
spec:containers:- name: pod6wimage: soscscs/myapp:v1affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: NotInvalues:- node01
注釋:
文件定義了一個 Pod 名為
pod6w
,其中包含一個名為pod6w
的容器。此外,它還定義了節(jié)點親和性規(guī)則。在本例中,pod6w
Pod 要求不被調度到具有標簽kubernetes.io/hostname: node01
的節(jié)點上。這將限制 Pod 的調度范圍,使其不運行在指定的節(jié)點上。
kubectl apply -f pod6w.yaml
kubectl get pod -o wide
#去除污點
kubectl taint node node01 key1:NoSchedule-
kubectl get pods -o wide
kubectl taint node node02 check=mycheck:NoExecute
#查看 Pod 狀態(tài),會發(fā)現 node02 上的 Pod 已經被全部驅逐(注:如果是 Deployment 或者 StatefulSet 資源類型,為了維持副本數量則會在別的 Node 上再創(chuàng)建新的 Pod)
kubectl get pods -o wide
注:取消設置的node02污點
kubectl taint node node02 check=mycheck:NoExecute-
2.容忍(Tolerations)
(1)容忍(Tolerations)概念
設置了污點的 Node 將根據 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之間產生互斥的關系,Pod 將在一定程度上不會被調度到 Node 上。但我們可以在 Pod 上設置容忍(Tolerations),意思是設置了容忍的 Pod 將可以容忍污點的存在,可以被調度到存在污點的 Node 上。
(2)節(jié)點容忍示例
使用場景:如是為了測試后設置了污點秒數,在測試結束后,達到秒數之后會自動驅除,資源很多的情況下不建議做節(jié)點驅除
#設置節(jié)點容忍驅除
kubectl taint node node01 check=summer:NoExecute
#查看節(jié)點容忍設置
kubectl describe nodes node01 | grep -i taint
vim demo01.yamlapiVersion: v1
kind: Pod
metadata:name: myapp01labels:app: myapp01
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1restartPolicy: AlwaysnodeSelector:kubernetes.io/hostname: node01tolerations:- key: "check"operator: "Equal"value: "summer"effect: "NoExecute"tolerationSeconds: 60 #設置60秒之后自動驅除節(jié)點
注釋:
metadata
: 定義了 Pod 的元數據,包括名稱和標簽。spec
: 定義了 Pod 的規(guī)格,包括容器、重啟策略、節(jié)點選擇和容忍策略。在這個配置中:
containers
: 定義了 Pod 中的容器,這里包含一個名為with-node-affinity
的容器,使用soscscs/myapp:v1
鏡像。restartPolicy
: 設置了容器的重啟策略為Always
,表示發(fā)生故障時會自動重啟容器。nodeSelector
: 定義了節(jié)點選擇器,指定了 Pod 要運行在具有標簽kubernetes.io/hostname: node01
的節(jié)點上。這將限制 Pod 的調度范圍,使其只能運行在具有該標簽的節(jié)點上。tolerations
: 定義了容忍策略,即 Pod 對于節(jié)點上的特定條件的容忍程度。在這個例子中,Pod 標記了一個鍵值對check=summer
,并設置容忍效果為NoExecute
,表示 Pod 允許在節(jié)點上執(zhí)行非關鍵的系統(tǒng)任務。tolerationSeconds
設置為 60,表示容忍持續(xù)的時間為 60 秒。通過節(jié)點選擇器和容忍策略,可以對 Pod 進行更加具體的調度和限制,以滿足特定的需求。
kubectl apply -f demo01.yaml
kubectl get pod -o wide
kubectl get pod -w -o wide
#在兩個 Node 上都設置了污點后,會創(chuàng)建在master01上,此時 Pod 將無法創(chuàng)建成功,如果再將master01也設置污點則無法創(chuàng)建pod為Pending狀態(tài)
kubectl taint node node02 check=summer:NoExecute
kubectl describe node node01
kubectl describe node node02kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 0/1 Pending 0 17s <none> <none> <none> <none>
#其中的 key、vaule、effect 都要與 Node 上設置的 taint 保持一致
#operator 的值為 Exists 將會忽略 value 值,即存在即可
#tolerationSeconds 用于描述當 Pod 需要被驅逐時可以在 Node 上繼續(xù)保留運行的時間
(3)污點注意事項
- 當不指定 key 值時,表示容忍所有的污點 key
tolerations:
- operator: "Exists"
- 當不指定 effect 值時,表示容忍所有的污點作用
tolerations:
- key: "key""Exists"operator:
- 有多個 Master 存在時,防止資源浪費,可以如下設置
kubect1 taint node Master-Name node role,kubernetes.io/master-;PreferNoSchedule
- 如果某個 Node 事新升級系統(tǒng)組件,為了防止業(yè)務長時間中斷,可以先在該 Node 設置 NOExecule 污點,把該Node 上的 Pod 都驅逐出去
kubect1 taint node node01 check=ycheck:NoExecute
- 比時如果別的 Node資源不夠用,可臨時給 Master設置PreferNoSchedule污點,讓pod可在 Master上臨時創(chuàng)建
kubectI taint node master node-role,kubernetes,io/master=:PreferNoSchedule
-
待所有 node 的更新操作都完成后,再去除污點
kubectl taint node node01 check=mycheck:NoExecute-
五.維護操作
1.cordon調度器
(1)對節(jié)點執(zhí)行維護操作
#查看節(jié)點的狀態(tài)
kubectl get nodes
(2)cordon調度器
使用場景:使需要維護的node節(jié)點機器不可以進行資源創(chuàng)建,在取消調度器創(chuàng)建的資源會正常,注:開啟調度器之前的資源是正常的
①格式
#將 Node 標記為不可調度的狀態(tài),這樣就不會讓新創(chuàng)建的 Pod 在此 Node 上運行
#該node將會變?yōu)镾chedulingDisabled狀態(tài)
kubectl cordon <NODE NAME>
#將 Node 標記為可調度的狀態(tài)
kubectl uncordon <NODE_NAME>
②示例
#查看節(jié)點正常狀態(tài)
kubectl get nodes
#查看是否設置了污點
kubectl describe nodes node01|grep -i taint
kubectl describe nodes node02|grep -i taint
#設置了取消污點
kubectl taint node node01 check=summer:NoExecute-
kubectl taint node node02 check=summer:NoExecute-
kubectl cordon node02
kubectl get nodes
vim demo02.yaml apiVersion: v1
kind: Pod
metadata:name: myapp01labels:app: myapp01
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1restartPolicy: AlwaysnodeSelector:kubernetes.io/hostname: node02
kubectl apply -f demo02.yaml
kubectl get pod
#關閉調度器
kubectl uncordon node02
#查看狀態(tài)
kubectl get pod -owide
2.drain命令
①格式
#kubectl drain 可以讓: Node 節(jié)點開始釋放所有,并且不接收新的 pod 進程。drain本意排水,意思是將出問題的 Node 下的 Pod 轉移到其它 Node 下運行
kubectl drain <NODE NAME> --ignore-daemonsets --delete-local-data --force
注釋:
–iqnore-daemonsets:無視 DaemonSet 管理下的 Pode
–delete-local-data:如果有mount local volume 的 pod,會強制殺掉該 pod
–force:強制釋放不是控制器管理的 Pod,例如 kube-proxy
執(zhí)行 drain 命令,會自動做了兩件事情:
- 設定此 node 為不可調度狀態(tài) (cordon)
- evict (驅逐)了 Pod
②示例
kubectl get pod -owide
kubectl drain node01 --ignore-daemonsets --delete-local-data --force
kubectl get pod -owide
–ignore-daemonsets:在排空節(jié)點時忽略DaemonSet類型的Pod。
–delete-local-data:刪除節(jié)點上的本地數據。包括PV、Volume等。
–force:強制執(zhí)行排空操作,不進行確認提示。
–grace-period=:設置節(jié)點上的Pod被遷移前的優(yōu)雅停機時間,默認情況下為30秒。
–pod-selector=:指定要排空的Pod的標簽選擇器,只有匹配選擇器的Pod才會被遷移。
–ignore-errors:繼續(xù)排空操作,即使在遷移Pod時發(fā)生錯誤。
–timeout=:設置排空操作的超時時間,默認情況下為0,表示無限等待,直到所有Pod被遷移完成
注:
使用kubectl drain命令需要具備集群管理員權限或特權賬號。
在執(zhí)行排空操作之前,請確保已經做好備份和驗證。
排空操作會將Pod遷移至其他可用節(jié)點,因此可能會導致一段時間內的業(yè)務中斷,請謹慎操作。
#取消drain命令使用結果
kubectl uncordon node01
六.Pod啟動階段(相位 phase)
1.pod啟動過程
Pod 創(chuàng)建完之后,一直到持久運行起來,中間有很多步驟,也就有很多出錯的可能,因此會有很多不同的狀態(tài)。
一般來說,pod 這個過程包含以下幾個步驟:
(1)調度到某臺 node 上。kubernetes 根據一定的優(yōu)先級算法選擇一臺 node 節(jié)點將其作為 Pod 運行的 node
(2)拉取鏡像
(3)掛載存儲配置等
(4)運行起來。如果有健康檢查,會根據檢查的結果來設置其狀態(tài)。
2.phase 的可能狀態(tài)
(1)Pending:表示APIServer創(chuàng)建了Pod資源對象并已經存入了etcd中,但是它并未被調度完成(比如還沒有調度到某臺node上),或者仍然處于從倉庫下載鏡像的過程中。
(2)Running:Pod已經被調度到某節(jié)點之上,并且Pod中所有容器都已經被kubelet創(chuàng)建。至少有一個容器正在運行,或者正處于啟動或者重啟狀態(tài)(也就是說Running狀態(tài)下的Pod不一定能被正常訪問)。
(3)Succeeded:有些pod不是長久運行的,比如job、cronjob,一段時間后Pod中的所有容器都被成功終止,并且不會再重啟。需要反饋任務執(zhí)行的結果。
(4)Failed:Pod中的所有容器都已終止了,并且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態(tài)退出或者被系統(tǒng)終止,比如 command 寫的有問題。
(5)Unknown:表示無法讀取 Pod 狀態(tài),通常是 kube-controller-manager 無法與 Pod 通信。
3.故障排除步驟
(1)查看Pod事件
kubectl describe TYPE NAME_PREFIX
(2)查看Pod日志(Failed狀態(tài)下)
kubectl logs <POD_NAME> [-c Container_NAME]
(3)進入Pod(狀態(tài)為running,但是服務沒有提供)
kubectl exec –it <POD_NAME> bash
(4)查看集群信息
kubectl get nodes
(5)發(fā)現集群狀態(tài)正常
kubectl cluster-info
(6)查看kubelet日志發(fā)現
journalctl -xefu kubelet
總:
1.list-watch
controller-manager,scheduler,kubelet監(jiān)聽apiserver 發(fā)出的事件,apiserver 監(jiān)聽 etcd 發(fā)出的事件,
2.scheduler
預選策略:通過調度算法過濾掉不滿足的節(jié)點
優(yōu)選策略:通過優(yōu)先級選項給滿足調度條件的節(jié)點進行優(yōu)先級和權重排序,選擇優(yōu)先級最高的節(jié)點
3.pod 調度到指定節(jié)點的方法
配置文件中指定nodename
nodeSelector
4.節(jié)點親和性和反親和性
節(jié)點親和性 | 硬策略 (必要條件) | 軟策略(優(yōu)先級) |
---|---|---|
pod親和性 | 和滿足標簽的條件的pod | 在同一個拓步域 |
pod反親和性 | 和滿足標簽的條件的pod | 不在同一個拓步域 |
5.相關標簽命令
kubectl get <資源類型> <資源名稱> --show-labels
kubectl get <資源類型> -l <標簽 key> [=<標簽 value>]
kubectl label <資源類型> <資源名稱> key-value
kubectl label <資源類型> <資源名稱> key=vaule --overrwite
kubect1 label <資源光型> <資源名稱> key-
6.污點和容忍
(1)設置和取消
kubectl taint node <節(jié)點名稱> key=value:effect
effect:NoSchedule PeferNoSchedule Noexecute
kubectl taint node <節(jié)點名稱> key:effect-
(2)調度
kubectl cordon <節(jié)點名稱>不可調度
kubectl drain <節(jié)點名稱> 不可調度+驅逐
7.Pod啟動階段(相位) 5個狀態(tài)
(1)pendding:pod已創(chuàng)建且寫入etcd,但是未完成調度或者仍處于鏡像拉取過程中
(2)running:正常狀態(tài)
(3)Succeeded:短期 (非長久運行的) Pod的正常退出
(4)failed:短期 (非長久運行的) pod 異常退出
(5)unkown:controller-manager 無法與pod 正常通信
8.排除故障方法
(1)kubectl describe
(2)kubectl logs
(3)kubectI exec -it
(4)kubectl cluster-info
(5)journalctl -u 服務進程名 (比如kubelet)