

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# EKS 数据平面
<a name="data-plane"></a>

要运行高可用性和弹性的应用程序，您需要一个高可用性和弹性的数据平面。弹性数据平面可确保 Kubernetes 可以自动扩展和修复您的应用程序。弹性数据平面由两个或更多工作节点组成，可以随着工作负载的变化而增长和缩小，并自动从故障中恢复。

使用 EKS 的工作节点有多种选择：EKS [自动模式托管节点](https://docs.aws.amazon.com/eks/latest/userguide/automode.html)、[EC2 实例](https://docs.aws.amazon.com/eks/latest/userguide/worker.html)和 [Fargat](https://docs.aws.amazon.com/eks/latest/userguide/fargate.html) e。

EKS 自动模式提供了通往弹性数据平面的最简单途径。自动模式将 AWS 对 Kubernetes 集群的管理扩展到集群本身之外，让 AWS 还可以设置和管理基础设施，使您的工作负载能够顺利运行。当 Kubernetes 扩展 Pod 时，自动模式会自动向上或向下扩展数据平面，并不断确保集群中的节点大小适当、经济实惠，以适应当前正在运行的工作负载。

如果您选择 EC2 实例，则可以自己管理工作节点或使用 [EKS 托管节点组](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)。你可以拥有一个混合了自动模式、托管、自我管理的工作节点和 Fargate 的集群。

Fargate 在隔离的计算环境中运行每个 Pod。在 Fargate 上运行的每个 Pod 都有自己的工作节点。当 Kubernetes 缩放 pod 时，Fargate 会自动缩放数据平面。您可以使用[水平容器自动扩缩器来扩展](https://docs.aws.amazon.com/eks/latest/userguide/horizontal-pod-autoscaler.html)数据平面和工作负载。

[扩展 EC2 工作节点的首选方法（如果不使用由 AWS 自动执行的 EKS 自动模式）是使用 K [arpenter](https://karpenter.sh/)、[Kubernetes 集群自动扩缩器或 EC2 Aut](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) o Scaling 组。](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html)

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

### 将工作节点和工作负载分布到多个可用区
<a name="_spread_worker_nodes_and_workloads_across_multiple_azs"></a>

您可以通过在多个可用区中运行工作节点和 Pod 来保护您的工作负载免受单个可用区故障的影响。您可以使用在其中创建节点的子网来控制创建工作节点的可用区。

跨可用区分配 Pod 的推荐方法是对 Po [d 使用拓扑分布约束](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods)。 Auto-scaling 诸如 EKS Auto Mode 和 Karpenter 之类的功能知道拓扑分布限制，并且会自动在正确的可用区中启动节点以满足您的限制。

如果可能的话，下面的部署将 pod 分布在 AZ 中，如果没有，则让这些 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。下面的清单告知 Kubernetes 调度器*更喜欢*在不同的可用区中调度 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
```

**警告**  
不要要求在不同的可用区之间调度 Pod，否则，部署中的 Pod 数量将永远不会超过可用区的数量。

### 使用 EBS 卷时，确保能够在每个可用区中启动节点
<a name="_ensure_ability_to_launch_nodes_in_each_az_when_using_ebs_volumes"></a>

如果您使用 Amazon EBS 提供永久卷，则需要确保 Pod 和关联的 EBS 卷位于同一个可用区中。Pod 无法访问位于不同可用区的 EBS-backed 永久卷。Kubernetes [调度器通过节点上的标签知道工作节点位于哪个可用区](https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#topologykubernetesiozone)，并且将始终调度需要与卷位于同一可用区的 EBS 卷的 Pod。但是，如果卷所在的可用区中没有工作节点可用，则无法调度 Pod。

如果使用 EKS 自动模式或 Karpenter，则需要确保在每个可用区 NodeClass 中选择子网。如果使用托管节点组，则需要确保在每个可用区中都有一个节点组。

EBS 存储功能内置于 EKS 自动模式中，但如果使用 Karpenter 或托管节点组，则还需要[安装 EBS CSI](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)。

### 使用 EKS 自动模式管理工作节点
<a name="_use_eks_auto_mode_to_manage_worker_nodes"></a>

EKS Auto Mode 通过为生产就绪型集群提供操作开销最小的操作开销来简化 EKS 的管理。自动模式负责根据集群中运行的 Pod 向上或向下扩展 Node 的数量。节点会自动更新软件补丁和修复，更新将根据配置的中[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 自动模式、托管节点组和 Karpenter 都能够检测节点监控代理报告的致命节点状况，并在出现这些情况时自动修复这些节点。

### 实施 QoS
<a name="_implement_qos"></a>

对于关键应用程序，可以考虑为 Pod 中的容器定义 `requests` = `limits`。这将确保在另一个 Pod 请求资源时容器不会被杀死。

最佳做法是对所有容器实施 CPU 和内存限制，因为这样可以防止容器无意中消耗系统资源，从而影响其他共置进程的可用性。

### 为所有工作负载配置和调整资源 Requests/Limits 规模
<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) 也从 “保证” 降低到 Burstable，因此在节点压力下它更有可能被驱逐。](https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/)
+ 对于非 CPU 资源，请勿指定比请求大得多的限制。相对于的配置越大 `limits``requests`，节点被过度使用的可能性就越大，从而导致工作负载中断的可能性很大。
+ [在使用 [Karpen](https://aws.github.io/aws-eks-best-practices/karpenter/) ter 或 Cluster 等节点自动缩放解决方案时，正确调整请求大小尤为重要。AutoScaler](https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/)这些工具会查看您的工作负载请求，以确定要配置的节点的数量和大小。如果你的请求太小，限制更大，那么如果你的工作负载被紧密地挤在节点上，你可能会发现工作负载被驱逐或 OOM 终止。

确定资源请求可能很困难，但是像 Vertic [al Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) 这样的工具可以通过在运行时观察容器资源使用情况来帮助你 “调整请求的大小”。可能对确定请求大小有用的其他工具包括：
+  [Goldilocks](https://github.com/FairwindsOps/goldilocks) 
+  [帕尔卡](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/)对象可以按类型限制可以在命名空间中创建的对象的数量，以及该项目中资源可能消耗的计算资源总量。您可以限制在给定命名空间中可以请求的存储 and/or 计算（CPU 和内存）资源的总和。

如果为计算资源（如 CPU 和内存）启用了命名空间的资源配额，则用户必须为该命名空间中的每个容器指定请求或限制。

考虑为每个命名空间配置配额。考虑使用自动`LimitRanges`将预配置的限制应用于命名空间内的容器。

### 限制命名空间内的容器资源使用量
<a name="_limit_container_resource_usage_within_a_namespace"></a>

资源配额有助于限制命名空间可以使用的资源量。该[`LimitRange`对象](https://kubernetes.io/docs/concepts/policy/limit-range/)可以帮助您实现容器可以请求的最小和最大资源。使用`LimitRange`可以为容器设置默认请求和限制，如果设置计算资源限制不是组织中的标准做法，这会很有用。顾名思义，`LimitRange`可以强制命名空间中每个 Pod 或容器的最低和最大计算资源使用量。并且，在命名空间 PersistentVolumeClaim 中强制执行每个存储请求的最小和最大值。

考虑与结合使用 `LimitRange``ResourceQuota`，在容器和命名空间级别强制执行限制。设置这些限制将确保容器或命名空间不会影响集群中其他租户使用的资源。

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

您可以通过运行 [NodeLocaldnsCache 来提高集群 DN](https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/) S 的性能。此功能在群集节点上运行 DNS 缓存代理DaemonSet。所有 pod 都使用节点上运行的 DNS 缓存代理进行名称解析，而不是使用 S `kube-dns` ervice。此功能自动包含在 EKS 自动模式中。

### 配置自动缩放 CoreDNS
<a name="_configure_auto_scaling_coredns"></a>

提高集群 DNS 性能的另一种方法是启用 CoreDNS P [od 的内置自动缩放功能。](https://docs.aws.amazon.com/eks/latest/userguide/coredns-autoscaling.html)

此功能持续监控集群状态，包括节点数量和 CPU 内核。控制器会根据这些信息，动态调整 EKS 集群中 CoreDNS 部署的副本数量。