從service的externalTrafficPolicy到podAntiAffinity

externalTrafficPolicy 簡介

若是服務須要將外部流量路由到 本地節點或者集羣級別的端點,即service type 爲LoadBalancer或NodePort,那麼須要指明該參數。存在兩種選項:」Cluster」(默認)和 「Local」。 「Cluster」 隱藏源 IP 地址,可能會致使第二跳(second hop)到其餘節點,可是全局負載效果較好。」Local」 保留客戶端源 IP 地址,避免 LoadBalancer 和 NodePort 類型服務的第二跳,可是可能會致使負載不平衡。node

在實際的業務中,諸多業務是須要保留客戶端源 IP,因此須要經過將服務的配置文件中的 externalTrafficPolicy 參數設置爲 「Local」 來激活這個特性。api

{
      "kind": "Service",
      "apiVersion": "v1",
      "metadata": {
        "name": "example-service",
      },
      "spec": {
        "ports": [{
          "port": 8765,
          "targetPort": 9376
        }],
        "selector": {
          "app": "example"
        },
        "type": "LoadBalancer",
        "externalTrafficPolicy": "Local"
      }
    }

使用保留源 IP 的警告和限制

新功能中,外部的流量不會按照 pod 平均分配,而是在節點(node)層面平均分配(由於 GCE/AWS 和其餘外部負載均衡實現沒有能力作節點權重, 而是平均地分配給全部目標節點,忽略每一個節點上所擁有的 pod 數量)。app

然而,在 pod 數量(NumServicePods) « 節點數(NumNodes)或者 pod 數量(NumServicePods) » 節點數(NumNodes)的狀況下,即便沒有權重策略,咱們也能夠看到很是接近公平分發的場景。負載均衡

內部 pod 對 pod 的流量應該與 ClusterIP 服務相似,流量對於全部 pod 是均分的。運維

ps

設置了externalTrafficPolicy:Local之後svc死活都不能訪問,後來通過一系列排查iptables和kube-proxy終於發現瞭解決辦法。
在kube-proxy啓動參數裏面須要設置--hostname-override:frontend

- --hostname-override=$(NODE_NAME)
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: spec.nodeName

經過podAntiAffinity 避免pod 流量不均衡

居然外部的流量不會按照 pod 平均分配,而是在節點(node)層面平均分配 ,那麼咱們能作的只有保證同一業務的pod調度到不一樣的node節點上。ide

podAntiAffinity使用場景:ui

  • 將一個服務的POD分散在不一樣的主機或者拓撲域中,提升服務自己的穩定性。
  • 給POD對於一個節點的獨佔訪問權限來保證資源隔離,保證不會有其它pod來分享節點資源。
  • 把可能會相互影響的服務的POD分散在不一樣的主機上

對於親和性和反親和性,每種都有三種規則能夠設置:google

  • RequiredDuringSchedulingRequiredDuringExecution :在調度期間要求知足親和性或者反親和性規則,若是不能知足規則,則POD不能被調度到對應的主機上。在以後的運行過程當中,若是由於某些緣由(好比修改label)致使規則不能知足,系統會嘗試把POD從主機上刪除(如今版本還不支持)。
  • RequiredDuringSchedulingIgnoredDuringExecution :在調度期間要求知足親和性或者反親和性規則,若是不能知足規則,則POD不能被調度到對應的主機上。在以後的運行過程當中,系統不會再檢查這些規則是否知足。
  • PreferredDuringSchedulingIgnoredDuringExecution :在調度期間儘可能知足親和性或者反親和性規則,若是不能知足規則,POD也有可能被調度到對應的主機上。在以後的運行過程當中,系統不會再檢查這些規則是否知足。

那咱們的使用場景只能使用RequiredDuringSchedulingIgnoredDuringExecution,要嚴格保證同一業務pod調度到不一樣的主機。固然這樣可能出現一種問題:不知足條件的pod,會pending。這個時候咱們運維會接受到通知,去增長node節點或是驅趕業務不重要的pod。code

示例解讀

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: name
              operator: In
              values:
              - frontend
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0

使用kubernetes.io/hostname做爲拓撲域,查看匹配規則,即同一打有一樣標籤name=frontend的pod會調度到不一樣的節點。

親和性/反親和性調度策略比較

調度策略 匹配標籤 操做符 拓撲域支持 調度目標
nodeAffinity 主機 In, NotIn, Exists, DoesNotExist, Gt, Lt pod到指定主機
podAffinity Pod In, NotIn, Exists, DoesNotExist pod與指定pod同一拓撲域
PodAntiAffinity Pod In, NotIn, Exists, DoesNotExist pod與指定pod非同一拓撲域
相關文章
相關標籤/搜索