Pod Affinity
通過《K8S調度之節點親和性》,我們知道怎么在調度的時候讓pod靈活的選擇node,但有些時候我們希望調度能夠考慮pod之間的關系,而不只是pod與node的關系。於是在kubernetes 1.4的時候引入了pod affinity。
為什么有這樣的需求呢?舉個例子,我們系統服務 A 和服務 B 盡量部署在同個主機、機房、城市,因為它們網絡溝通比較多;再比如,我們系統數據服務 C 和數據服務 D 盡量分開,因為如果它們分配到一起,然后主機或者機房出了問題,會導致應用完全不可用,如果它們是分開的,應用雖然有影響,但還是可用的。
pod affinity 可以這樣理解:調度的時候選擇(或者不選擇)這樣的節點 N ,這些節點上已經運行了滿足條件 X。條件 X 是一組 label 選擇器,它必須指明作用的 namespace(也可以作用於所有的 namespace),因為 pod 是運行在某個 namespace 中的。
這里的X指的是集群中的節點、機架、區域等概念,通過kubernetes內置節點標簽中的key來進行聲明。這個key的名字為topologyKey,意為表達節點所屬的topology范圍:
- kubernetes.io/hostname
- failure-domain.beta.kubernetes.io/zone
- failure-domain.beta.kubernetes.io/region
和 node affinity 相似,pod affinity 也有 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,意義也和之前一樣。如果有使用親和性,在 affinity 下面添加 podAffinity 字段,如果要使用互斥性,在 affinity 下面添加 podAntiAffinity 字段。
先定義一個參照目標pod:
apiVersion: v1
kind: Pod
metadata:
name: pod-flag
labels:
security: "S1"
app: "nginx"
spec:
containers:
- name: nginx
image: nginx
Pod親和性調度
下面是一個親和性調度的示例
apiVersion: v1
kind: Pod
metadata:
name: pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: gcr.io/google_containers/pause:2.0
創建后可以看到這個pod與上面那個參照的pod位於同一個node上,另外,如果將這個node上的kubernetes.io/hostname標簽干掉,將會發現pod會一直處於pending狀態,這是因為找不到滿足條件的node了。
pod互斥性調度
下面是一個互斥性調度的示例:
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: gcr.io/google_containers/pause:2.0
這個例子要求這個新pod與security=S1的pod為同一個zone,但是不與security=S2的pod為同一個node。
原則上,topologyKey可以使用任何合法的標簽Key賦值,但是出於性能和安全方面的考慮,對topologyKey有如下限制:
- 在pod親和性和RequiredDuringScheduling的pod互斥性的定義中,不允許使用空的topologyKey
- 如果admission controller包含了LimitPodHardAntiAffinityTopology,那么針對RequiredDuringScheduling的pod互斥性定義就被限制為kubernetes.io/hostname,要使用自定義的topologyKey,就要改寫或禁用該控制器
- 在PerferredDuringScheduling類型的Pod互斥性定義中,空的topologyKey會被解釋為kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone及failure-domain.beta.kubernetes.io/region的組合
podAffinity規則設置的注意事項:
- 在labelSelector和topologyKey同級,還可以定義namespaces列表,表示匹配哪些namespace里面的pod,默認情況下,會匹配定義的pod所在的namespace,如果定義了這個字段,但是它的值為空,則匹配所有的namespaces。
- 所有關聯requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都滿足之后,系統才能將pod調度到某個node上。