通常情況下,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。