當叢集裡有很多node及pod時,如果想把相同或是相關的服務部屬到同一個node上時該怎麼做呢?
在這裡Pod元件提供了親和性(Affinity)屬性,當然對Deployment也適用,可將服務部屬到有相關標籤的服務所在node上,當然也提供了反親和性(Anti-Affinity),可以避免將把相同的服務部屬到同一個node上,那麼就讓我們來看看要如何實做吧!
※Pod 環境必需(完全)滿足 Pod 相依/互斥配置才可進行派送,否則將創建失敗
※podAffinity 設定為參考 Pod 部署,則 podAntiAffinity 禁止與參考 Pod 部署
mysql.yaml
kubectl apply -f mysql.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-1
  labels:
    app: mysql
spec:
  containers:
  - image: mysql:5.6
    name: mysql
    env:
    # Use secret in real usage
    - name: MYSQL_ROOT_PASSWORD
      value: password
kubectl get pod -o wide

kubectl get node --show-labels

※Pod affinity 擁有 Node domain (Label) 的分別,需指定 topologyKey (domain)
※參考 kubectl get node --show-labels 的資料
撰寫 相依於 mysql & mongodb 的兩個服務 yaml 檔案nginx-mysql.yaml&nginx-mongodb.yaml
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-mysql
   labels:
     app: nginx
 spec:
   affinity:
     podAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - labelSelector:
           matchExpressions:
           - key: app
             operator: In
             values:
             - mysql
         topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-mongodb
   labels:
     app: nginx
 spec:
   affinity:
     podAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - labelSelector:
           matchExpressions:
           - key: app
             operator: In
             values:
             - mongodb
         topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
※附註說明
部屬相依於 mysql & mongodb 的兩個服務 yaml 檔案nginx-mysql.yaml&nginx-mongodb.yaml
kubectl apply -f nginx-mysql.yaml
kubectl apply -f nginx-mongodb.yaml
kubectl get pod -o wide


因無法找到 Pod affinity 參考 Pod 的服務 Labels,Pod 無法進行派送與啟動
nginx-anti-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-anti
  labels:
    app: nginx
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - mysql
        topologyKey: name
  containers:
  - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80
      hostPort: 80
kubectl apply -f nginx-anti-affinity.yaml
kubectl get pod -o wide

※Pod 參考需求環境派送,若無法匹配則尋找最低負載 Node 部屬 Pod
※podAffinity 設定為參考 Pod 部署,則 podAntiAffinity 禁止與參考 Pod 部署
mysql.yaml
kubectl apply -f mysql.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-1
  labels:
    app: mysql
spec:
  containers:
  - image: mysql:5.6
    name: mysql
    env:
    # Use secret in real usage
    - name: MYSQL_ROOT_PASSWORD
      value: password
kubectl get pod -o wide

kubectl get node --show-labels

撰寫 相依於 mysql & mongodb 的兩個服務 yaml 檔案nginx-mysql-soft.yaml&nginx-mongodb-soft.yaml
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-mysql-soft
   labels:
     app: nginx
 spec:
   affinity:
     podAffinity:
       preferredDuringSchedulingIgnoredDuringExecution:
       - weight: 1
         podAffinityTerm:
           labelSelector:
             matchExpressions:
             - key: app
               operator: In
               values:
               - mysql
           topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-mongodb-soft
   labels:
     app: nginx
 spec:
   affinity:
     podAffinity:
       preferredDuringSchedulingIgnoredDuringExecution:
       - weight: 1
         podAffinityTerm:
           labelSelector:
             matchExpressions:
             - key: app
               operator: In
               values:
               - mongodb
           topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
※附註說明
派送服務 yaml 檔
kubectl apply -f nginx-mysql-soft.yaml
kubectl apply -f nginx-mongodb-soft.yaml
kubectl get pod -o wide

※若參考 Pod 的服務 Labels 無法對應,則尋找負載較低的 Node 進行派送與啟動
mysql-deployment.yaml
kubectl apply -f mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
kubectl get deploy -o wide
kubectl get pod -o wide
kubectl get rs

撰寫一個服務 yaml 檔nginx-anti-affinity-soft.yaml
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-anti-soft
   labels:
     app: nginx
 spec:
   affinity:
     podAntiAffinity:
       preferredDuringSchedulingIgnoredDuringExecution:
       - weight: 1
         podAffinityTerm:
           labelSelector:
             matchExpressions:
             - key: app
               operator: In
               values:
               - mysql
           topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
派送服務互斥 mysql 服務
kubectl apply -f nginx-anti-affinity-soft.yaml
kubectl get pod -o wide

所有 Node 皆有 mysql Pod 服務,則尋找負載較低的 Node 進行派送與啟動
※測試方案 : 將node Affinity 的 hardMode和pod Affinity 的 hardMode同時配置並執行派送
kubectl get node --show-labels

kubectl get pod -o wide

nginx-mysql-node-pod-affinity-hard.yaml&nginx-mongodb-node-pod-affinity-hard.yaml
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-mysql-node-pod-affinity-hard
   labels:
     app: nginx
 spec:
   affinity:
     nodeAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
         nodeSelectorTerms:
         - matchExpressions:
           - key: disktype
             operator: In
             values:
             - hdd
     podAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - labelSelector:
          matchExpressions:
           - key: app
             operator: In
             values:
             - mysql
         topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
 apiVersion: v1
 kind: Pod
 metadata:
   name: nginx-mongodb-node-pod-affinity-hard
   labels:
     app: nginx
 spec:
   affinity:
     nodeAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
         nodeSelectorTerms:
         - matchExpressions:
           - key: disktype
             operator: In
             values:
             - hdd
     podAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - labelSelector:
          matchExpressions:
           - key: app
             operator: In
             values:
             - mongodb
         topologyKey: name
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80
       hostPort: 80
kubectl apply -f nginx-mysql-node-pod-affinity-hard.yaml
kubectl apply -f nginx-mongodb-node-pod-affinity-hard.yaml
kubectl get pod -o wide

成功派送 Pod 至符合規定配置的 Node
因無法找到匹配的需求設置,Pod 無法進行派送與啟動