Kubernetes控制節(jié)點的部署
標簽和nodeSelector
標簽(Label)是附加到 Kubernetes 對象上的鍵值對,如果用 json 表示附加到 metadata 的 label:
"metadata": { "labels": { "key1" : "value1", "key2" : "value2" } }
yaml:
metadata: labels: key1: "value1" key2: "value2"
標簽主要是用于表示對用戶有意義的對象的屬性標識。
可以給節(jié)點設(shè)定一些 Label,例如在 kube-system 命名空間中,運行著 Kubernetes 的核心組件,我們可以查看此命名空間中所有組件的 Label。
kubectl get nodes --namespace=kube-system --show-labels
beta.kubernetes.io/arch=amd64, beta.kubernetes.io/os=linux, kubernetes.io/arch=amd64, ... ...
我們也可以手動給一個 Node 添加標簽。
kubectl label nodes <node-name> <label-key>=<label-value>
例如我們給節(jié)點設(shè)置一個 disksize
,表示節(jié)點的硬盤是否夠大。
kubectl label nginx disksize=big
然后我們在編寫 yaml 文件時,希望這個 pod 在容量大的 Node 上運行,可以這樣寫:
nodeSelector: disksize=big
順便聊一下官方的一個例子,設(shè)置 Node 的 Label,表示硬盤是 ssd。
kubectl label nodes kubernetes-foo-node-1.c.a-robinson.internal disktype=ssd
在 yaml 文件的節(jié)點選擇器中,添加選擇。
spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd
Label 可以在多個地方使用,例如在 Node 上添加 Label,標識此 Node;而在 NodeSelector 里使用,可以選擇合適的 Node 運行 Pod;在 metadata
中使用,可以對元數(shù)據(jù)加以描述。
在 metadata 中添加的 Label,可以在命令查詢時做篩選。
查詢 pod 的 Label:
kubectl get pods --show-labels
查找符合條件的 pod(參考 LABELS 字段,可以根據(jù)里面的標簽選擇):
kubectl get pods -l app=nginx
標簽選擇
在前面,我們學(xué)習(xí)了 nodeSelector ,可以幫助我們選擇合適的 Node 運行 Pod,實際上 Kubernets 的標簽選擇是豐富多樣的,例如:
nodeSelector: disktype: ssd disksize: big
則表示節(jié)點選擇器是等值選擇,表達式是 disktype=ssd && disksize=big
。
標簽選擇有等值和集合兩種,其中等值選擇有 =
、==
、!=
三種,=
和 ==
無區(qū)別。在多個需求(多個label)的情況下,相對于使用 &&
運算符,但是選擇器不存在 ||
這種邏輯或運算符。
yaml 只支持 {key}:{value}
這種形式,而我們使用命令形式時,則可使用以上三種運算符。
kubectl get nodes -l disktype=ssd,disksize!=big # 多個條件使用 逗號","" 隔開,而不是 "&&"。
對于集合選擇方式,支持三種操作符:in
、notin
和 exists
。不過別理解成是從集合中選擇,下面舉個例子。
假如有三個 Node,其 disksize 有 big、medium、small,我們要部署一個 pod,在 big、medium 中都可以運行,則:
... -l disksize in (big,medium)
... -l disksize notin (small) # 不在 small 中運行
而 exists 則跟 !=
類似,但是 exists 表示只要存在這個 label 即可,而不論其設(shè)置了是什么值。
-l disksize # 等同 -l disksize in (big,medium,small)
我們也可以使用 ''
把選擇表達式包起來。
kubectl get pods -l 'app=nginx'
前面已經(jīng)提到了 yaml 的 nodeSelector 和 命令式的選擇,這里我們介紹 yaml 的 selector。
前面我們提到在 Deployment 的 metadata 中加上 Label,即 pod 加上 Label,我們也在 kubectl get pods
中使用 Label 選擇過濾 pod。同樣,當我們創(chuàng)建 Service 或者使用 ReplicationController 時,也可以使用標簽選擇合適的 pod。
假如我們已經(jīng)部署了 nginx,那么查詢 kubectl get pods --show-labels
時,其 pod 的 LABELS 會有 app=nginx
,那么我們可以這樣選擇:
selector: app: nginx
完整版本:
apiVersion: v1 kind: Service metadata: name: my-service spec: type: LoadBalancer selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 6666 status: loadBalancer: ingress: - ip: 192.0.2.127
selector 還支持以下選擇方式 matchLabels
、matchExpressions
:
matchLabels
是由 {key,value}
對組成的映射。 matchLabels
映射中的單個 {key,value }
等同于 matchExpressions
的元素, 其 key
字段為 "key",operator
為 "In",而 values
數(shù)組僅包含 "value"。
matchExpressions
是 Pod 選擇算符需求的列表。 有效的運算符包括 In
、NotIn
、Exists
和 DoesNotExist
。 在 In
和 NotIn
的情況下,設(shè)置的值必須是非空的。 來自 matchLabels
和 matchExpressions
的所有要求都按邏輯與的關(guān)系組合到一起 -- 它們必須都滿足才能匹配。
示例如下:
selector: matchLabels: component: redis matchExpressions: - {key: tier, operator: In, values: [cache]} - {key: environment, operator: NotIn, values: [dev]}
這里就不在詳細說這些選擇規(guī)則了,前面提到的已經(jīng)夠用了,讀者可以查閱官方文檔學(xué)習(xí)更多復(fù)雜的操作:https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/labels/
親和性和反親和性
前面我們學(xué)習(xí)了 nodeSelector
,使用 nodeSelector
選擇合適的 Label,可以表達我們約束的類型。
親和性則類似于 nodeSelector,可以根據(jù)節(jié)點上的標簽約束 pod 可以調(diào)度到哪些節(jié)點。
pod 親和性有兩種別為:
requiredDuringSchedulingIgnoredDuringExecution
硬需求,將 pod 調(diào)度到一個節(jié)點必須滿足的規(guī)則。
preferredDuringSchedulingIgnoredDuringExecution
。嘗試執(zhí)行但是不能保證偏好。
這是官方的一個例子:
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: k8s.gcr.io/pause:2.0
親和性的約束相對于:
... ... -l kubernetes.io/e2e-az-name in (e2e-az1,e2e-az2)
affinity 設(shè)置親密關(guān)系,nodeAffinity 設(shè)置節(jié)點親密關(guān)系,最后才到 親和性,它們表示必須滿足和盡量滿足。
如果我們設(shè)置了多個 nodeSelectorTerms :
requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: ... nodeSelectorTerms:
則只需要滿足其中一種即可調(diào)度 pod 到 node 上。
如果你同時指定了 nodeSelector
和 nodeAffinity
,兩者必須都要滿足, 才能將 Pod 調(diào)度到候選節(jié)點上。
節(jié)點親和性語法支持下面的操作符: In
,NotIn
,Exists
,DoesNotExist
,Gt
,Lt
。
Pod 親和性與反親和性的合法操作符有 In
,NotIn
,Exists
,DoesNotExist
。
通過 -Affinity
可以設(shè)置親和性,例如節(jié)點親和性 nodeAffinity
,而且設(shè)置反親和性使用 -AntiAffinity
,例如 nodeAntiAffinity
。
反親和性跟親和性一樣,都有 requiredDuringSchedulingIgnoredDuringExecution
硬限制和 preferredDuringSchedulingIgnoredDuringExecution
軟限制,只是反親和性是相反的表示,如果符合條件則不能調(diào)度。
關(guān)于親和性和反親和性的說明就到這里,著兩者的配置比較多和復(fù)雜,讀者可以參考官方文檔,這里不在贅述。
污點和容忍度
前面提到親和性和反親和性,我們加以通過 pod 選擇合適的 node,或者 service 選擇合適的 pod,這些擁有 Label 的對象都是被選擇的。
這里,我們介紹污點和容忍度,它們可以排斥 “被選擇” 的命運。
節(jié)點污點(taint) 可以排斥一類特定的 pod,而 容忍度(Tolerations)則表示能夠容忍這個對象的污點。
當節(jié)點添加一個污點后,除非 pod 聲明能夠容忍這個污點,否則 pod 不會被調(diào)度到這個 節(jié)點上。
系統(tǒng)會 盡量 避免將 Pod 調(diào)度到存在其不能容忍污點的節(jié)點上, 但這不是強制的。Kubernetes 處理多個污點和容忍度的過程就像一個過濾器:從一個節(jié)點的所有污點開始遍歷, 過濾掉那些 Pod 中存在與之相匹配的容忍度的污點。
但是如果你只有一個 worker,那么設(shè)置了污點,那 pod 也只能選擇在這個節(jié)點上運行。
添加污點格式:
kubectl taint node [node] key=value:[effect]
更新污點或覆蓋:
kubectl taint node [node] key=value:[effect] --overwrite=true
使用 kubectl taint
給節(jié)點增加一個污點。
kubectl taint nodes node1 key1=value1:NoSchedule
移除污點:
kubectl taint nodes node1 key1=value1:NoSchedule-
其中,污點需要設(shè)置 label ,并設(shè)置這個 label 的效果為 NoSchedule。
污點的效果稱為 effect ,節(jié)點的污點可以設(shè)置為以下三種效果:
NoSchedule
:不能容忍此污點的 Pod 不會被調(diào)度到節(jié)點上;不會影響已存在的 pod。PreferNoSchedule
:Kubernetes 會避免將不能容忍此污點的 Pod 安排到節(jié)點上。NoExecute
:如果 Pod 已在節(jié)點上運行,則會將該 Pod 從節(jié)點中逐出;如果尚未在節(jié)點上運行,則不會將其安排到節(jié)點上。
但是某些系統(tǒng)創(chuàng)建的 Pod 可以容忍所有 NoExecute
和 NoSchedule
污點,因此不會被逐出,例如 master 節(jié)點是不能被部署 pod 的,但是 kube-system
命名空間卻有很多系統(tǒng) pod。當然通過修改污點,可以讓 戶 pod 部署到 master 節(jié)點中。
查詢節(jié)點的污點:
kubectl describe nodes | grep Taints
Taints: node-role.kubernetes.io/master:NoSchedule Taints: key1=value1:NoSchedule
系統(tǒng)默認污點
我們?nèi)コ?master 的污點:
kubectl taint node instance-1 node-role.kubernetes.io/master:NoSchedule-
然后部署 nginx pod。
kubectl create deployment nginxtaint --image=nginx:latest --replicas=3
查看 pod:
kubectl get pods -o wide
結(jié)果筆者查到三個副本都在 master 節(jié)點上。
為了保證集群安全,我們需要恢復(fù) master 的污點。
kubectl taint node instance-1 node-role.kubernetes.io/master:NoSchedule
當某種條件為真時,節(jié)點控制器會自動給節(jié)點添加一個污點。當前內(nèi)置的污點包括:
node.kubernetes.io/not-ready
:節(jié)點未準備好。這相當于節(jié)點狀態(tài)Ready
的值為 "False
"。node.kubernetes.io/unreachable
:節(jié)點控制器訪問不到節(jié)點. 這相當于節(jié)點狀態(tài)Ready
的值為 "Unknown
"。node.kubernetes.io/out-of-disk
:節(jié)點磁盤耗盡。node.kubernetes.io/memory-pressure
:節(jié)點存在內(nèi)存壓力。node.kubernetes.io/disk-pressure
:節(jié)點存在磁盤壓力。node.kubernetes.io/network-unavailable
:節(jié)點網(wǎng)絡(luò)不可用。node.kubernetes.io/unschedulable
: 節(jié)點不可調(diào)度。node.cloudprovider.kubernetes.io/uninitialized
:如果 kubelet 啟動時指定了一個 "外部" 云平臺驅(qū)動, 它將給當前節(jié)點添加一個污點將其標志為不可用。在 cloud-controller-manager 的一個控制器初始化這個節(jié)點后,kubelet 將刪除這個污點。
容忍度
一個 node 可以設(shè)置污點,排斥 pod,但是 pod 也可以設(shè)置 容忍度,容忍 node 的污點。
tolerations: - key: "key1" operator: "Exists" effect: "NoSchedule"
也可以設(shè)置 value。
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule"
operator
的默認值是 Equal
。
一個容忍度和一個污點相“匹配”是指它們有一樣的鍵名和效果,并且:
如果
operator
是Exists
此時容忍度不能指定
value
,如果存在 key 為 key1 的 label,且污點效果為NoSchedule
,則容忍。如果
operator
是Equal
,則它們的value
應(yīng)該相等
如果 effect
留空,則表示只要是 label 為 key1
的節(jié)點,都可以容忍。
如果:
tolerations: operator: "Exists"
則表示此 pod 能夠容忍任意的污點,無論 node 怎么設(shè)置 key
、value
、effect
,此 pod 都不會介意。
如果要在 master 上也能部署 pod,則可以修改 pod 的容忍度:
spec: tolerations: # this toleration is to have the daemonset runnable on master nodes # remove it if your masters can't run pods - key: node-role.kubernetes.io/master effect: NoSchedule
DaemonSet
在 Kubernetes 中,有三個 -Set
,分別是 ReplicaSet、DaemonSet、StatefulSets。而 負載類型有 Deployments、ReplicaSet、DaemonSet、StatefulSets等(或者說有這幾個控制器)。
前面已經(jīng)介紹過 Deployments ,而 kind: ReplicaSet
一般是沒必要的,可以在 kind: Deployment
加上 replicas:
。
而 kind: DaemonSet
需要使用一個 yaml 來描述,但是整體跟 Deployment 一樣。
DaemonSet 可以確保一個節(jié)點只運行一個 Pod 副本,假如有個 nginx 的 pod,當新的 Node 加入集群時,會自動在這個 Node 上部署一個 pod;當節(jié)點從集群中移開時,這個 Node 上的 Pod 會被回收;如果 DaemontSet 配置被刪除,則也會刪除所有由它創(chuàng)建的 Pod。
DaemonSet 的一些典型用法:
- 在每個節(jié)點上運行集群守護進程
- 在每個節(jié)點上運行日志收集守護進程
- 在每個節(jié)點上運行監(jiān)控守護進程
在 yaml 中,要配置 Daemont,可以使用 tolerations
,配置示例:
kind: DaemontSet ... ...
其它地方跟 Deployment 一致。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Kubernetes中Deployment的升級與回滾
- 了解Kubernetes中的Service和Endpoint
- Kubernetes部署實例并配置Deployment、網(wǎng)絡(luò)映射、副本集
- Kubernetes關(guān)鍵組件與結(jié)構(gòu)組成介紹
- 配置Kubernetes外網(wǎng)訪問集群
- 使用kubeadm命令行工具創(chuàng)建kubernetes集群
- Minikube搭建Kubernetes集群
- kubernetes中的namespace、node、pod介紹
- Kubernetes集群的組成介紹
- Dashboard管理Kubernetes集群與API訪問配置
相關(guān)文章
kubernetes中的namespace、node、pod介紹
這篇文章介紹了kubernetes中的namespace、node、pod,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03Kubernetes Visitor設(shè)計模式及發(fā)送pod創(chuàng)建請求解析
這篇文章主要為大家介紹了Kubernetes Visitor設(shè)計模式及發(fā)送pod創(chuàng)建請求解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11Kubernetes Informer數(shù)據(jù)存儲Index與Pod分配流程解析
這篇文章主要為大家介紹了Kubernetes Informer數(shù)據(jù)存儲Index與Pod分配流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11kubernetes數(shù)據(jù)持久化PV?PVC深入分析詳解
這篇文章主要為大家介紹了kubernetes數(shù)據(jù)持久化PV?PVC分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11KubeSphere接入外部Elasticsearch實戰(zhàn)示例
這篇文章主要為大家介紹了KubeSphere接入外部Elasticsearch實戰(zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12