

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# EKS 資料平面
<a name="data-plane"></a>

若要操作高可用性和彈性應用程式，您需要高可用性和彈性的資料平面。彈性資料平面可確保 Kubernetes 可以自動擴展和修復您的應用程式。彈性資料平面由兩個或多個工作者節點組成，可以隨著工作負載成長和縮減，並從故障中自動復原。

對於具有 EKS 的工作者節點，您有多種選擇：[EKS Auto Mode 受管節點](https://docs.aws.amazon.com/eks/latest/userguide/automode.html)、[EC2 執行個體](https://docs.aws.amazon.com/eks/latest/userguide/worker.html)和 [Fargate](https://docs.aws.amazon.com/eks/latest/userguide/fargate.html)。

EKS Auto Mode 提供彈性資料平面的最簡單路徑。Auto Mode 會將 Kubernetes 叢集的 AWS 管理延伸到叢集本身之外，讓 AWS 也可以設定和管理基礎設施，讓工作負載能夠順暢地運作。自動模式會在 Kubernetes 擴展 Pod 時自動擴展或縮減資料平面，並持續確保叢集中的節點大小適合目前執行中的工作負載，且符合成本效益。

如果您選擇 EC2 執行個體，您可以自行管理工作者節點，或使用 [EKS 受管節點群組](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)。您可以擁有混合自動模式、受管、自我管理的工作者節點和 Fargate 的叢集。

Fargate 會在隔離的運算環境中執行每個 Pod。在 Fargate 上執行的每個 Pod 都會取得自己的工作者節點。Fargate 會在 Kubernetes 擴展 Pod 時自動擴展資料平面。您可以使用[水平 Pod 自動擴展器來擴展](https://docs.aws.amazon.com/eks/latest/userguide/horizontal-pod-autoscaler.html)資料平面和工作負載。

擴展 EC2 工作者節點 （如果未使用 AWS 自動執行的 EKS Auto 模式） 的偏好方法是使用 [Karpenter](https://karpenter.sh/)、[Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) 或 [EC2 Auto Scaling 群組](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html)。

## 建議
<a name="_recommendations"></a>

### 將工作者節點和工作負載分散到多個可用AZs
<a name="_spread_worker_nodes_and_workloads_across_multiple_azs"></a>

您可以在多個 AZ 中執行工作者節點和 Pod，以保護工作負載免於個別 AZs 中的故障。您可以使用您建立節點的子網路，控制在 中建立工作者節點的 AZ。

跨 AZs 分散 Pod 的建議方法是使用 [Pod 的拓撲分散限制](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods)條件。EKS Auto Mode 和 Karpenter 等自動擴展功能知道拓撲分散限制條件，並會自動在正確的 AZs 中啟動節點，以滿足您的限制條件。

下列部署會盡可能將 Pod 分散到 AZs，如果沒有的話，讓這些 Pod 執行：

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          whenUnsatisfiable: ScheduleAnyway
          topologyKey: topology.kubernetes.io/zone
          labelSelector:
            matchLabels:
              app: web-server
      containers:
      - name: web-app
        image: nginx
        resources:
          requests:
            cpu: 1
```

**注意**  
 `kube-scheduler` 只會透過與這些標籤一起存在的節點來了解拓撲網域。如果上述部署僅部署到單一區域中具有節點的叢集，則所有 Pod 都會在這些節點上排程，因為 `kube-scheduler` 不知道其他區域。若要讓此拓撲與排程器如預期般運作，節點必須已存在於所有區域中。拓撲分散限制條件的 `minDomains` 屬性用於通知排程器合格網域的數量，即使其中有節點執行以避免此問題。

**警告**  
如果無法滿足拓撲分散限制條件，`whenUnsatisfiable``DoNotSchedule`將導致 Pod 無法排程。只有在 Pod 不執行而不是違反拓撲分散限制條件時，才應該設定它。

在舊版 Kubernetes 上，您可以使用 Pod 反親和性規則來跨多個 AZs 排程 Pod。下列資訊清單會通知 Kubernetes 排程器*偏好*在不同的AZs排程 Pod。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
  labels:
    app: web-server
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web-server
              topologyKey: failure-domain.beta.kubernetes.io/zone
            weight: 100
      containers:
      - name: web-app
        image: nginx
```

**警告**  
不需要在不同的 AZs 之間排程 Pod，否則部署中的 Pod 數目永遠不會超過 AZs 數目。

### 使用 EBS 磁碟區時，確保能夠在每個 AZ 中啟動節點
<a name="_ensure_ability_to_launch_nodes_in_each_az_when_using_ebs_volumes"></a>

如果您使用 Amazon EBS 提供持久性磁碟區，則需要確保 Pod 和相關聯的 EBS 磁碟區位於相同的可用區域中。Pod 無法存取位於不同 AZ 的 EBS 支援的持久性磁碟區。Kubernetes [排程器會從節點上的標籤知道工作者節點位於哪個 AZ](https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#topologykubernetesiozone)，並且一律會排程 Pod，該 Pod 需要與磁碟區位於相同 AZ 中的 EBS 磁碟區。不過，如果磁碟區所在的 AZ 中沒有可用的工作者節點，則無法排程 Pod。

如果使用 EKS Auto Mode 或 Karpenter，您將需要確保 NodeClass 在每個可用區域中選取子網路。如果使用受管節點群組，您需要確保在每個 AZ 中有一個節點群組。

EBS 儲存功能內建於 EKS Auto 模式，但如果使用 Karpenter 或受管節點群組，則還需要安裝 [EBS CSI](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)。

### 使用 EKS Auto 模式管理工作者節點
<a name="_use_eks_auto_mode_to_manage_worker_nodes"></a>

EKS Auto Mode 透過為生產就緒的叢集提供最低的操作負荷，簡化 EKS 管理。自動模式負責根據叢集中執行的 Pod 向上或向下擴展節點數量。節點會與軟體修補程式保持最新狀態，並自動修正，並根據設定的 [NodePool](https://docs.aws.amazon.com/eks/latest/userguide/create-node-pool.html#_disruption) 中斷設定和 Pod 中斷預算執行更新。

### 執行節點監控代理程式
<a name="_run_the_node_monitoring_agent"></a>

[節點監控代理](https://docs.aws.amazon.com/eks/latest/userguide/node-health.html)程式會透過發佈 Kubernetes 事件並更新節點上的狀態條件，來監控節點運作狀態問題並做出反應。節點監控代理程式隨附於 EKS 自動模式節點，可安裝為非自動模式管理之節點的 EKS 附加元件。

EKS Auto Mode、受管節點群組和 Karpenter 全都能夠偵測節點監控代理程式回報的嚴重節點條件，並在這些條件發生時自動修復這些節點。

### 實作 QoS
<a name="_implement_qos"></a>

對於關鍵應用程式，請考慮為 Pod 中的容器定義 `requests`=`limits`。這將確保在另一個 Pod 請求資源時不會終止容器。

最佳實務是為所有容器實作 CPU 和記憶體限制，因為它可防止容器無意中耗用系統資源，進而影響其他共置程序的可用性。

### 設定和調整所有工作負載的資源請求/限制
<a name="_configure_and_size_resource_requestslimits_for_all_workloads"></a>

某些一般指引可以套用到調整工作負載的資源請求和限制大小：
+ 請勿在 CPU 上指定資源限制。如果沒有限制，請求會做為[容器取得多少相對 CPU 時間](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#how-pods-with-resource-limits-are-run)的權重。這可讓您的工作負載使用完整的 CPU，而不需要人工限制或匱乏。
+ 對於非 CPU 資源，設定 `requests`=`limits` 提供最可預測的行為。如果 `requests`！=`limits`，容器也會將其 [QOS](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes) 從保證縮減為爆量，使其在[節點壓力](https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/)的情況下更有可能被移出。
+ 對於非 CPU 資源，請勿指定遠大於請求的限制。相對於 ，`limits`設定較大的節點`requests`越有可能過度承諾，導致工作負載中斷的機率很高。
+ 正確大小的請求在使用 [Karpenter](https://aws.github.io/aws-eks-best-practices/karpenter/) 或 [Cluster AutoScaler](https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/) 等節點自動擴展解決方案時特別重要。這些工具會查看您的工作負載請求，以決定要佈建的節點數量和大小。如果您的請求太小，且限制較大，您可能會發現工作負載在節點上封裝緊密時遭到移出或 OOM 終止。

判斷資源請求可能很困難，但 [Vertical Pod Autoscaler ](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler)等工具可以透過在執行時間觀察容器資源用量來協助您「正確大小」請求。其他可能有助於判斷請求大小的工具包括：
+  [金絲雀](https://github.com/FairwindsOps/goldilocks) 
+  [Parca](https://www.parca.dev/) 
+  [Prodfiler](https://prodfiler.com/) 
+  [rsg](https://mhausenblas.info/right-size-guide/) 

### 設定命名空間的資源配額
<a name="_configure_resource_quotas_for_namespaces"></a>

命名空間主要使用於有許多使用者分散於多個團隊或專案的環境中。它們提供名稱的範圍，並且是在多個團隊、專案、工作負載之間劃分叢集資源的一種方式。您可以限制命名空間中的彙總資源耗用。[https://kubernetes.io/docs/concepts/policy/resource-quotas/](https://kubernetes.io/docs/concepts/policy/resource-quotas/) 物件可以依類型限制可在命名空間中建立的物件數量，以及該專案中資源可能耗用的運算資源總量。您可以限制可在指定命名空間中請求的儲存和/或運算 (CPU 和記憶體） 資源總和。

如果為 CPU 和記憶體等運算資源的命名空間啟用資源配額，使用者必須為該命名空間中的每個容器指定請求或限制。

考慮為每個命名空間設定配額。考慮使用 `LimitRanges` 自動將預先設定的限制套用至命名空間內的容器。

### 限制命名空間中的容器資源用量
<a name="_limit_container_resource_usage_within_a_namespace"></a>

Resource Quotas 有助於限制命名空間可以使用的資源量。[`LimitRange` 物件](https://kubernetes.io/docs/concepts/policy/limit-range/)可協助您實作容器可請求的最小和最大資源。`LimitRange` 您可以使用 設定容器的預設請求和限制，如果設定運算資源限制不是組織中的標準實務，這很有幫助。顧名思義， `LimitRange`可以強制執行命名空間中每個 Pod 或容器的運算資源用量下限和上限。此外，在命名空間中強制執行每個 PersistentVolumeClaim 的儲存請求下限和上限。

考慮將 `LimitRange` 與 搭配使用，`ResourceQuota`以在容器和命名空間層級強制執行限制。設定這些限制可確保容器或命名空間不會影響叢集中其他租用戶使用的資源。

### 使用 NodeLocal DNSCache
<a name="_use_nodelocal_dnscache"></a>

您可以執行 [NodeLocal DNSCache 來改善叢集 DNS](https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/) 效能。此功能會在叢集節點上執行 DNS 快取代理程式，做為 DaemonSet。所有 Pod 都會使用節點上執行的 DNS 快取代理程式進行名稱解析，而不是使用 `kube-dns` Service。此功能會自動包含在 EKS Auto 模式中。

### 設定自動調整規模的 CoreDNS
<a name="_configure_auto_scaling_coredns"></a>

改善叢集 DNS 效能的另一個方法是啟用 [ CoreDNS Pod 的內建自動擴展](https://docs.aws.amazon.com/eks/latest/userguide/coredns-autoscaling.html)。

此功能會持續監控叢集狀態，包括節點和 CPU 核心的數量。根據該資訊，控制器會動態調整 EKS 叢集中 CoreDNS 部署的複本數量。