通常情況下,Pod分配到哪些Node是不需要管理員操心的,這個過程會由scheduler自動實現。但有時,我們需要指定一些調度的限制,例如某些應用應該跑在具有SSD存儲的節點上,有些應用應該跑在同一個節點上等等。
截止到Kubernetes 1.11版本,節點親和性的特性還是Beta階段。
nodeSelector
首先我們爲Node規劃標籤,然後在創建部署的時候,通過使用nodeSelector
標籤來指定Pod運行在哪些節點上。
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: docker.io/nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd
nodeSelector 將會在後續的版本中廢除,還是建議大家使用使用親和性策略。
親和與反親和 Affinity and anti-affinity
nodeSelector的調度方式略顯簡單,通過親和和反親和配置,能夠爲調度提供更靈活的策略,主要有以下幾點增強:
- 更多的表達式支持,不僅僅是ADD和精確匹配了
- 可以設置soft/preference的調度策略,而不是剛性的要求
- 可以通過Pod的標籤進行調度約束,不僅僅是Node的標籤
親和性特性包含兩種方式
節點親和性 Node affinity
Node affinity 是 Kubernetes 1.2版本後引入的新特性,類似於nodeSelector,允許我們指定一些Pod在Node間調度的約束。支持兩種形式:requiredDuringSchedulingIgnoredDuringExecution
和preferredDuringSchedulingIgnoredDuringExecution
,可以認爲前一種是必須滿足,如果不滿足則不進行調度,後一種是傾向滿足,不滿足的情況下會調度的不符合條件的Node上。IgnoreDuringExecution
表示如果在Pod運行期間Node的標籤發生變化,導致親和性策略不能滿足,則繼續運行當前的Pod。
apiVersion: v1 kind: Pod metadata: name: nginx spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 //取值範圍1-100 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: nginx image: docker.io/nginx
標籤判斷的操作符除了使用In
之外,還可以使用NotIn
、Exists
、DoesNotExist
、Gt
、Lt
。如果指定多個nodeSelectorTerms
,則只要滿足其中一個條件,就會被調度到相應的節點上。如果指定多個matchExpressions
,則所有的條件都必須滿足纔會調度到對應的節點。
Pod間的親和性與反親和性 inter-pod affinity/anti-affinity
這個特性是Kubernetes 1.4後增加的,允許用戶通過已經運行的Pod上的標籤來決定調度策略,用文字描述就是“如果Node X上運行了一個或多個滿足Y條件的Pod,那麼這個Pod在Node應該運行在Pod X”,因爲Node沒有命名空間,Pod有命名空間,這樣就允許管理員在配置的時候指定這個親和性策略適用於哪個命名空間,可以通過topologyKey
來指定。topology是一個範圍的概念,可以是一個Node、一個機櫃、一個機房或者是一個區域(如北美、亞洲)等,實際上對應的還是Node上的標籤。
有兩種類型
- requiredDuringSchedulingIgnoredDuringExecution,剛性要求,必須精確匹配
- preferredDuringSchedulingIgnoredDuringExecution,軟性要求
apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: failure-domain.beta.kubernetes.io/zone podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: security operator: In values: - S2 topologyKey: kubernetes.io/hostname containers: - name: with-pod-affinity image: k8s.gcr.io/pause:2.0
標籤的判斷操作支持In
、NotIn
、Exists
、DoesNotExist
。
原則上topologyKey
可以是節點的合法標籤,但是有一些約束:
- 對於親和性以及RequiredDuringScheduling的反親和性,topologyKey需要指定
- 對於RequiredDuringScheduling的反親和性,LimitPodHardAntiAffinityTopology的准入控制限制topologyKey爲kubernetes.io/hostname,可以通過修改或者disable解除該約束
- 對於PreferredDuringScheduling的反親和性,空的topologyKey表示kubernetes.io/hostname, failure-domain.beta.kubernetes.io/zone and failure-domain.beta.kubernetes.io/region的組合.
- topologyKey在遵循其他約束的基礎上可以設置成其他的key.
本文來自 阿僕來耶 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/jettery/article/details/79003562?utm_source=copy
Pod間的親和性策略要求可觀的計算量可能顯著降低集羣的性能,不建議在超過100臺節點的範圍內使用。 Pod間的反親和策略要求所有的Node都有一致的標籤,例如集羣中所有節點都應有匹配topologyKey的標籤,如果一些節點缺失這些標籤可能導致異常行爲。
常用場景
apiVersion: apps/v1 kind: Deployment metadata: name: redis-cache spec: selector: matchLabels: app: store replicas: 3 template: metadata: labels: app: store spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: "kubernetes.io/hostname" containers: - name: redis-server image: redis:3.2-alpine
上面的例子中,創建了一個具有三個實例的部署,採用了Pod間的反親和策略,限制創建的實例的時候,如果節點上已經存在具有相同標籤的實例,則不進行部署,避免了一個節點上部署多個相同的實例。
apiVersion: apps/v1 kind: Deployment metadata: name: web-server spec: selector: matchLabels: app: web-store replicas: 3 template: metadata: labels: app: web-store spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - web-store topologyKey: "kubernetes.io/hostname" podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: "kubernetes.io/hostname" containers: - name: web-app image: nginx:1.12-alpine
再創建3個Web服務的實例,同上面Redis的配置,首先確保兩個Web不會部署到相同的節點,然後在應用Pod間親和策略,優先在有Redis服務的節點上部署Web。