

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

# EKS 控制面板
<a name="control-plane"></a>

**提示**  
 [通过亚马逊 EKS 研讨会探索](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)最佳实践。

亚马逊弹性Kubernetes服务 (EKS) 是一项托管的Kubernetes服务，使您可以轻松地在AWS上运行Kubernetes，而无需安装、操作和维护自己的Kubernetes控制平面或工作节点。它在上游 Kubernetes 上游运行，并经认证符合 Kubernetes 标准。这种一致性确保了 EKS 支持 Kubernetes API，就像您可以在 EC2 或本地安装的开源社区版本一样。在上游 Kubernetes 上运行的现有应用程序与亚马逊 EKS 兼容。

EKS 自动管理 Kubernetes 控制平面节点的可用性和可扩展性，并自动替换不健康的控制平面节点。

## EKS 架构
<a name="reliability_cpeks_architecture"></a>

EKS 架构旨在消除任何可能损害 Kubernetes 控制平面的可用性和耐久性的单点故障。

由 EKS 管理的 Kubernetes 控制平面在 EKS 管理的 VPC 内运行。EKS 控制平面由 Kubernetes API 服务器节点、etcd 集群组成。Kubernetes API 服务器节点运行 API 服务器、调度器等组件，并在自动扩展组中`kube-controller-manager`运行。EKS 在 AWS 区域内的不同可用区 (AZ) 中至少运行两个 API 服务器节点。同样，为了耐久性，etcd 服务器节点也在跨越三个可用区的自动扩展组中运行。EKS 在每个 AZ 中运行 NAT 网关，而 API 服务器和 etcd 服务器在私有子网中运行。这种架构可确保单个可用区中的事件不会影响 EKS 集群的可用性。

当您创建新集群时，Amazon EKS 会为托管 Kubernetes API 服务器创建一个高可用终端节点，用于与集群通信（使用诸如此类的工具）。`kubectl`托管端点使用 NLB 对 Kubernetes API 服务器进行负载平衡。EK [ S 还在不同的可用区中预置两个 ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html) ENI，以促进与工作节点的通信。

EKS 数据平面网络连接

![连接](http://docs.aws.amazon.com/zh_cn/eks/latest/best-practices/images/reliability/eks-data-plane-connectivity.jpeg)


您可以[配置](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html)是可通过公共互联网（使用公共终端节点）还是通过您的 VPC（使用 EKS-managed ENI）访问您的 Kubernetes 集群的 API 服务器，或两者兼而有之。

无论用户和工作节点使用公共端点还是 EKS-managed ENI 连接到 API 服务器，都有冗余的连接路径。

## 建议
<a name="cp-recs"></a>

查看以下建议。

## 监控控制平面指标
<a name="reliability_cpmonitor_control_plane_metrics"></a>

监控 Kubernetes API 指标可以让你深入了解控制平面性能并识别问题。不健康的控制平面可能会危及集群内运行的工作负载的可用性。例如，编写不当的控制器会使 API 服务器过载，从而影响应用程序的可用性。

Kubernetes 在端点公开了控制平面指标。`/metrics`

您可以使用以下方式查看暴露的指标`kubectl`：

```
kubectl get --raw /metrics
```

这些指标以 [ Prometheus 文本格式表示。](https://github.com/prometheus/docs/blob/main/docs/instrumenting/exposition_formats.md)

你可以使用 Prometheus 来收集和存储这些指标。2020 年 5 月，在 Container Insights 中CloudWatch 增加了对监控 Prometheus 指标的 CloudWatch支持。因此，您也可以使用亚马逊 CloudWatch 来监视EKS控制平面。您可以使用添加新 Prometheus Scrape Target [ 教程：Prometheus KPI 服务器指标](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights-Prometheus-Setup-configure.html#ContainerInsights-Prometheus-Setup-new-exporters)来收集指标并创建 CloudWatch 仪表板来监控集群的控制平面。

你可以在这里找到 Kubernetes API 服务器指标。[https://github.com/kubernetes/apiserver/blob/master/pkg/endpoints/metrics/metrics.go](https://github.com/kubernetes/apiserver/blob/master/pkg/endpoints/metrics/metrics.go)例如，`apiserver_request_duration_seconds`可以指示 API 请求需要多长时间才能运行。

考虑监控以下控制平面指标：

### API 服务器
<a name="reliability_cpapi_server"></a>


| 指标 | 说明 | 
| --- | --- | 
|  `apiserver_request_total`  | 对于每个动词、试运行值、组、版本、资源、范围、组件和 HTTP 响应代码划分的 apiserver 请求的计数器。 | 
|  `apiserver_request_duration_seconds*`  | 每个动词、试运行值、组、版本、资源、子资源、子资源、范围和组件的响应延迟直方图（以秒为单位）。 | 
|  `apiserver_admission_controller_admission_duration_seconds*`  | 准入控制器延迟直方图（以秒为单位），由名称标识，并按每项操作和 API 资源和类型（验证或准许）进行细分。 | 
|  `apiserver_admission_webhook_rejection_count`  | 准入 webhook 被拒绝的次数。按名称、操作、拒绝码、类型（验证或承认）、错误类型（calling\_webhook\_error、apiserver\_internal\_error、no\_error、no\_error）识别 | 
|  `rest_client_request_duration_seconds*`  | 请求延迟直方图（以秒为单位）。按动词和 URL 细分。 | 
|  `rest_client_requests_total`  | HTTP 请求数，按状态码、方法和主机分区。 | 
+ 直方图指标包括 \_bucket、\_sum 和 \_count 后缀。

### etcd
<a name="reliability_cpetcd"></a>


| 指标 | 说明 | 
| --- | --- | 
|  `etcd_request_duration_seconds*`  | 每种操作和对象类型的 Etcd 请求延迟直方图（以秒为单位）。 | 
|  `apiserver_storage_db_total_size_in_bytes`或`apiserver_storage_size_bytes`（从 EKS v1.28 开始） | etcd 数据库大小。 | 
+ 直方图指标包括 \_bucket、\_sum 和 \_count 后缀。

考虑使用 [ Kubernetes 监控概览仪表板](https://grafana.com/grafana/dashboards/14623)来可视化和监控 Kubernetes API 服务器请求和延迟以及 etcd 延迟指标。

**重要**  
当超过数据库大小限制时，etcd 会发出空间不足警报并停止接收进一步的写入请求。换句话说，集群变为只读状态，所有更改对象的请求，例如创建新 pod、扩展部署等，都将被集群的 API 服务器拒绝。

## 集群身份验证
<a name="reliability_cpcluster_authentication"></a>

EKS 目前支持两种类型的身份验证：[bearer/service账户令牌](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)和使用 [ webhook 令牌身份验证的 IAM 身份验证](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication)。当用户调用 Kubernetes API 时，网络挂钩会将请求中包含的身份验证令牌传递给 IAM。该令牌是一个基于 64 位的签名网址，由 AWS 命令行接口 (A [ WS CLI](https://aws.amazon.com/cli/)) 生成。

创建 EKS 集群的 IAM 用户或角色自动获得对集群的完全访问权限。您可以通过编辑 [ aws-auth 配置映射来管理对 EKS 集群的访问权限。](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html)

如果您错误配置了 `aws-auth` configmap 并失去了对集群的访问权限，您仍然可以使用集群创建者的用户或角色来访问您的 EKS 集群。

万一您无法在 AWS 区域使用 IAM 服务，这种情况极少发生，您也可以使用 Kubernetes 服务账户的持有者代币来管理集群。

创建一个允许在集群中执行所有操作的`super-admin`账户：

```
kubectl -n kube-system create serviceaccount super-admin
```

创建角色绑定以提供超级管理员集群管理员角色：

```
kubectl create clusterrolebinding super-admin-rb --clusterrole=cluster-admin --serviceaccount=kube-system:super-admin
```

获取服务账号的密钥：

```
SECRET_NAME=`kubectl -n kube-system get serviceaccount/super-admin -o jsonpath='{.secrets[0].name}'`
```

获取与该机密相关的代币：

```
TOKEN=`kubectl -n kube-system get secret $SECRET_NAME -o jsonpath='{.data.token}'| base64 --decode`
```

将服务帐号和令牌添加到`kubeconfig`：

```
kubectl config set-credentials super-admin --token=$TOKEN
```

将当前上下文设置`kubeconfig`为使用超级管理员帐户：

```
kubectl config set-context --current --user=super-admin
```

决赛`kubeconfig`应该是这样的：

```
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data:<REDACTED>
    server: https://<CLUSTER>.gr7.us-west-2.eks.amazonaws.com
  name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
contexts:
- context:
    cluster: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
    user: super-admin
  name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
current-context: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
kind: Config
preferences: {}
users:
#- name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
#  user:
#    exec:
#      apiVersion: client.authentication.k8s.io/v1beta1
#      args:
#      - --region
#      - us-west-2
#      - eks
#      - get-token
#      - --cluster-name
#      - <<cluster name>>
#      command: aws
#      env: null
- name: super-admin
  user:
    token: <<super-admin sa's secret>>
```

## 入学网络挂钩
<a name="reliability_cpadmission_webhooks"></a>

Kubernetes 有两种类型的准入网络挂钩：[验证准入网络挂钩和变异准入网络挂钩。](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers)这些允许用户扩展 kubernetes API 并在 API 接受对象之前对其进行验证或变异。这些 Webhook 的配置不当会阻塞集群的关键操作，从而破坏 EKS 控制平面的稳定。

为了避免影响集群的关键操作，要么避免设置如下所示的 “包罗万象” 网络挂钩：

```
- name: "pod-policy.example.com"
  rules:
  - apiGroups:   ["*"]
    apiVersions: ["*"]
    operations:  ["*"]
    resources:   ["*"]
    scope: "*"
```

或者确保 webhook 的失效开放策略，超时时间小于 30 秒，以确保在 webhook 不可用时不会损害集群的关键工作负载。

### 使用不安全 s `ysctl 屏蔽 Pod`
<a name="reliability_cpblock_pods_with_unsafe_sysctls"></a>

 `Sysctl`是一个 Linux 实用程序，允许用户在运行时修改内核参数。这些内核参数控制操作系统行为的各个方面，例如网络、文件系统、虚拟内存和进程管理。

Kubernetes 允许为 Pod 分配`sysctl`配置文件。Kubernetes 分`systcls`为安全和不安全。Saf `sysctls` e 的命名空间位于容器或 Pod 中，设置它们不会影响节点上的其他 Pod 或节点本身。相比之下，不安全的 sysctl 在默认情况下处于禁用状态，因为它们可能会中断其他 Pod 或使节点不稳定。

由于 unsafe 在默认情况下`sysctls`处于禁用状态，因此 kubelet 不会使用不安全的`sysctl`配置文件创建 Pod。如果你创建这样的 Pod，调度器会反复将这样的 Pod 分配给节点，而节点无法启动它。这种无限循环最终会拉紧集群控制平面，使集群不稳定。

考虑使用 [ OPA Gatekeeper ](https://github.com/open-policy-agent/gatekeeper-library/blob/377cb915dba2db10702c25ef1ee374b4aa8d347a/src/pod-security-policy/forbidden-sysctls/constraint.tmpl) 或 [ Kyverno ](https://kyverno.io/policies/pod-security/baseline/restrict-sysctls/restrict-sysctls/) 来拒绝不安全的 Pod。`sysctls`

## 处理集群升级
<a name="reliability_cphandling_cluster_upgrades"></a>

自2021年4月以来，Kubernetes的发布周期已从每年四次（每季度一次）更改为每年发布三次。一个新的次要版本（比如 1.**21 ** 或 1。**22**) 大约[每十五周发布一次](https://kubernetes.io/blog/2021/07/20/new-kubernetes-release-cadence/#what-s-changing-and-when)。从 Kubernetes 1.19 开始，每个次要版本在首次发布后的大约十二个月内受到支持。随着 Kubernetes v1.28 的问世，控制平面和工作节点之间的兼容性偏差已从 n-2 扩展到 n-3 次要版本。要了解更多信息，请参阅集群升级[最佳实践](cluster-upgrades.md)。

## 集群终端节点连接
<a name="reliability_cpcluster_endpoint_connectivity"></a>

使用亚马逊 EKS（弹性 Kubernetes 服务）时，在 Kubernetes 控制平面扩展或修补等事件期间，你可能会遇到连接超时或错误。这些事件可能导致 kube-apiserver 实例被替换，从而可能导致在解析 FQDN 时返回不同的 IP 地址。本文档概述了 Kubernetes API 使用者保持可靠连接的最佳实践。

**注意**  
实施这些最佳实践可能需要更新客户端配置或脚本，以有效处理新的 DNS 重新解析和重试策略。

主要问题源于 DNS 客户端缓存以及 EKS 端点（公共端点或 X-ENI 私有端点的*公共 NLB）的 IP 地址可能过时。*替换 kube-apiserver 实例时，完全限定域名 (FQDN) 可能会解析为新的 IP 地址。但是，由于 DNS 生存时间 (TTL) 设置（在 AWS 托管的 Route 53 区域中设置为 60 秒），客户端可能会在短时间内继续使用过时的 IP 地址。

为了缓解这些问题，Kubernetes API 使用者（例如 kubectl、 CI/CD 管道和自定义应用程序）应实施以下最佳实践：
+ 实施 DNS 重新解析
+ 使用 Backoff 和 Jitter 实现重试。例如，请参阅[这篇标题为 “失败发生” 的文章 ](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/) 
+ 实现客户端超时。设置适当的超时时间，以防止长时间运行的请求阻塞您的应用程序。请注意，某些 Kubernetes 客户端库，尤其是那些由 OpenAPI 生成器生成的客户端库，可能不允许轻松设置自定义超时。
  + 使用 kubectl 的示例 1：

  ```
    kubectl get pods --request-timeout 10s # default: no timeout
  ```
  + 使用 Python 的示例 2：[Kubernetes 客户端提供了 \_request\_timeout 参数 ](https://github.com/kubernetes-client/python/blob/release-30.0/kubernetes/client/api_client.py#L120) 

通过实施这些最佳实践，您可以显著提高应用程序在与 Kubernetes API 交互时的可靠性和弹性。请记住要对这些实现进行全面测试，尤其是在模拟故障条件下，以确保它们在实际扩展或修补事件中按预期运行。

## 运行大型集群
<a name="reliability_cprunning_large_clusters"></a>

EKS 主动监控控制平面实例的负载并自动扩展它们以确保高性能。但是，在运行大型集群时，您应该考虑 Kubernetes 中潜在的性能问题和限制以及 AWS 服务的配额。
+ 根据 ProjectCalico 团队进行的[测试，拥有超过 1000 个服务的集群`kube-proxy`在使用 in `iptables` 模式时可能会遇到网络延迟](https://www.projectcalico.org/comparing-kube-proxy-modes-iptables-or-ipvs/)。解决方案是切换到`kube-proxy`在`ipvs`模式下[运行](ipvs.md)。
+ [如果 CNI 需要为 Pod 请求 IP 地址，或者您需要经常创建新的 ](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/throttling.html) EC2 实例，您也可能会遇到 EC2 API 请求限制。您可以通过将 CNI 配置为缓存 IP 地址来减少 EC2 API 的调用。您可以使用更大的 EC2 实例类型来减少 EC2 扩展事件。

## 其他资源：
<a name="reliability_cpadditional_resources"></a>
+  [De-mystifying亚马逊 EKS 工作节点的集群网络 ](https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/) 
+  [亚马逊 EKS 集群终端节点访问控制 ](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) 
+  [AWS re: Invent 2019：亚马逊 EKS 的幕后黑幕 () CON421-R1 ](https://www.youtube.com/watch?v=7vxDWDD2YnM) 