更新集群 - Amazon EKS
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

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

更新集群

您可以将现有群集更新为新的 Kubernetes 版本,也可以为群集启用信封加密。

更新 Amazon EKS 群集 Kubernetes 版本

当 Amazon EKS 中有新的 Kubernetes 版本可用时,您可以将集群更新到最新版本。

重要

我们建议您在更新到新的 Kubernetes 版本之前,可以查看Amazon EKS KS Kubernetes 版本中的信息和本主题中的更新步骤。

新的 Kubernetes 版本已经引入了重大的变化。因此,我们建议您先针对新的 Kubernetes 版本测试您的应用程序的行为,然后再更新生产集群。您可以通过构建持续集成工作流来测试您的应用程序行为,然后再移至新的 Kubernetes 版本来实现上述目的。

更新过程包含 Amazon EKS 使用更新后的 Kubernetes 版本启动新的 API 服务器节点来替换现有节点。Amazon EKS 会针对这些新节点上的网络流量执行标准基础设施和就绪运行状况检查,以确认它们是否按照预期工作。如果任意一项检查失败,Amazon EKS 将恢复基础设施部署,且您的集群保留为先前的 Kubernetes 版本。正在运行的应用程序不受影响,并且您的集群绝不会留在非确定性或不可恢复状态。Amazon EKS 定期备份托管集群,并且有机制来在必要时恢复集群。我们不断地评估和改进我们的 Kubernetes 基础设施管理流程。

要更新集群,Amazon EKS 需要来自您在创建集群时提供的子网中的两到三个空闲 IP 地址。如果这些子网没有可用的 IP 地址,则更新可能会失败。此外,如果在集群创建过程中提供的任何子网或安全组已被删除,则集群更新过程可能会失败。

注意

尽管 Amazon EKS 运行高度可用的控制层面,但您可能在更新期间遇到次要服务中断。例如,如果您尝试在 API 服务器终止并由运行新版 Kubernetes 的新 API 服务器替换前后连接到 API 服务器,则可能遇到 API 调用错误或连接问题。如果出现这种情况,请重试您的 API 操作直至成功。

要更新 Amazon EKS 集群的 Kubernetes 版本,请执行以下步骤:

更新集群的 Kubernetes 版本。

更新集群的 Kubernetes 版本

  1. 将群集控制平面的 Kubernetes 版本与节点的 Kubernetes 版本进行比较。

    • 使用以下命令获取集群控制层面的 Kubernetes 版本。

      kubectl version --short
    • 使用以下命令获取您节点的 Kubernetes 版本。此命令返回所有自我管理和托管的 Amazon EC2 和 Fargate 节点。每个 Fargate 容器都作为其自己的节点列出。

      kubectl get nodes

    群集中的托管节点和 Fargate 节点的 Kubernetes 次要版本必须与控制平面的当前版本的版本相同,然后才能将控制平面更新为新 Kubernetes 版本。例如,如果您的控制平面运行版本 1.19,并且您的任何节点运行版本 1.18,则在将控制平面的 Kubernetes 版本更新为 1.20 之前,请将节点更新为版本 1.19。我们还建议您在更新控制平面之前将自我管理节点更新为与控制平面相同的版本。有关更多信息,请参阅 更新托管节点组自行管理的节点更新。要更新 Fargate 节点的版本,请删除由节点表示的容器,然后在更新控制平面后重新部署容器。

  2. Amazon EKS 集群上默认启用 Pod 安全策略准入控制器。在更新集群之前,请确保在更新之前已制定适当的 Pod 安全策略,以避免出现任何问题。您可以使用以下命令检查默认策略:

    kubectl get psp eks.privileged

    如果您收到以下错误,请参阅默认 Pod 安全策略然后继续。

    Error from server (NotFound): podsecuritypolicies.extensions "eks.privileged" not found
  3. 如果您最初在 Kubernetes 上部署了集群1.17或更早版本,那么您可能需要从您的 CoreDNS 清单中删除已停产的条款。

    1. 检查您的 CoreDNS 清单是否有一行仅包含upstream

      kubectl get configmap coredns -n kube-system -o jsonpath='{$.data.Corefile}' | grep upstream

      如果没有返回输出,则清单没有行,您可以跳到下一步以更新您的集群。如果单词upstream,那么你需要删除该行。

    2. 编辑配置映射,删除文件顶部附近的行,该行仅包含upstream。不要更改文件中的任何其他内容。删除该行后,保存更改。

      kubectl edit configmap coredns -n kube-system -o yaml
  4. 使用更新您的集群eksctl,Amazon Web Services Management Console,或Amazon CLI。

    重要
    • 由于 Amazon EKS 运行高度可用的控制层面,因此,您可以一次只更新一个次要版本。请参阅 Kubernetes 版本和版本倾斜支持政策以了解此要求背后的原理。因此,如果您的当前版本为 1.18,并且您想要更新到 1.20,则必须先将集群更新到 1.19,然后再将其从 1.19 更新到 1.20。

    • 确保已运行kubelet在您更新之前,您的托管节点和 Fargate 节点的 Kubernetes 版本与您的控制平面相同。我们还建议您的自我管理节点与控制平面处于相同的版本,尽管它们最多可以落后于控制平面的当前版本。

    • 将集群从 1.16 更新到 1.17 将失败,如果您有AmazonFargate 豆荚具有kubelet较早于 1.16 的次要版本。在将集群从 1.16 更新到 1.17 之前,您需要回收您的 Fargate 窗格,以便它们的kubelet为 1.16,然后尝试将群集更新为 1.17。

    • 您可能需要更新某些已部署的资源,然后才能更新到 1.16。有关更多信息,请参阅 Kubernetes 1.16 更新先决条件

    • 将集群更新到较新版本可能会覆盖自定义配置。

    eksctl

    此过程需要 eksctl 版本 0.54.0 或更高版本。可以使用以下命令来查看您的 版本:

    eksctl version

    有关安装或更新的更多信息eksctl,请参阅安装或升级 eksctl

    使用以下命令将您的 Amazon EKS 控制层面的 Kubernetes 版本更新为比当前版本高的一个次要版本。Replace<my-cluster>(包括<>),并使用您的集群名称。

    eksctl upgrade cluster --name <my-cluster> --approve

    更新需要几分钟时间才能完成。

    Amazon Web Services Management Console
    1. 从打开 Amazon EKS 控制台https://console.aws.amazon.com/eks/home#/clusters

    2. 选择要更新的集群的名称,然后选择 Update cluster version (更新集群版本)

    3. 对于 Kubernetes version (Kubernetes 版本),选择您的集群要更新到的版本并选择 Update (更新)

    4. 对于 Cluster name (集群名称),键入您的集群的名称并选择 Confirm (确认)

      更新需要几分钟时间才能完成。

    Amazon CLI
    1. 使用以下 Amazon CLI 命令更新集群。将替换为<example-values>(包括<>) 与您自己的值。

      aws eks update-cluster-version \ --region <region-code> \ --name <my-cluster> \ --kubernetes-version <1.20>

      输出:

      { "update": { "id": "<b5f0ba18-9a87-4450-b5a0-825e6e84496f>", "status": "InProgress", "type": "VersionUpdate", "params": [ { "type": "Version", "value": "1.20" }, { "type": "PlatformVersion", "value": "eks.1" } ], ... "errors": [] } }
    2. 使用以下命令监控集群更新的状态。使用上一命令返回的集群名称和更新 ID。当状态显示为 Successful 时,您的更新将完成。更新需要几分钟时间才能完成。

      aws eks describe-update \ --region <region-code> \ --name <my-cluster> \ --update-id <b5f0ba18-9a87-4450-b5a0-825e6e84496f>

      输出:

      { "update": { "id": "b5f0ba18-9a87-4450-b5a0-825e6e84496f", "status": "Successful", "type": "VersionUpdate", "params": [ { "type": "Version", "value": "1.20" }, { "type": "PlatformVersion", "value": "eks.1" } ], ... "errors": [] } }
  5. 更新 VPC CNI、CoreDNS 和kube-proxy附加组件。

  6. (可选)如果您在更新集群之前将 Kubernetes Cluster Autoscaler 部署到集群,请将 Cluster Autoscaler 更新为与您更新到的 Kubernetes 主版本和次版本匹配的最新版本。

    1. 在 Web 浏览器中打开 Cluster Autoscaler 版本页面,找到与您集群的 Kubernetes 主版本和次要版本相匹配的 Cluster Autoscaler。例如,如果您集群的 Kubernetes 版本是 1.20,则查找以 1.20 开头的最新 Cluster Autoscaler 版本。记录语义版本号 (<1.20.n>),以在下一步中使用。

    2. 使用以下命令,将 Cluster Autoscaler 映像标签设置为您在上一步中记录的版本。如有必要,将1.20n使用您自己的值。

      kubectl -n kube-system set image deployment.apps/cluster-autoscaler cluster-autoscaler=public.ecr.aws/bitnami/cluster-autoscaler:v1.20.n
  7. (仅限于具有 GPU 节点的集群)如果您的集群具有带 GPU 支持的节点组(例如,p3.2xlarge),您必须更新适用于 Kubernetes 的 NVIDIA 设备插件使用以下命令在集群上进行 DaemonSet 护程序集。

    kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.8.0/nvidia-device-plugin.yml
  8. 集群更新完成后,将节点更新到已更新集群的同一 Kubernetes 版本。有关更多信息,请参阅 自行管理的节点更新更新托管节点组。Fargate 上推出的任何新舱都将有一个kubelet版本匹配您的集群版本。现有的 Fargate 舱不会更改。

Kubernetes 1.16 更新先决条件

正如Kubernetes 1.15 更改日志1.16 中删除过时的 API:以下是您需要了解的内容文档中,如果您有现有的集群,则在将集群更新到 1.16 之前,需要对以下已部署的资源进行 API 更改。

警告

如果在更新到 1.16 之前未更改这些 API,则在更新完成后,工作负载将失败。

  • NetworkPolicy 资源将不再从版本 1.16 的 extensions/v1beta1 中提供。迁移到使用 networking.k8s.io/v1 API,从版本 1.8 开始提供。可以通过 networking.k8s.io/v1 API 检索现有的持久数据。

  • PodSecurityPolicy 资源将不再从版本 1.16 的 extensions/v1beta1 中提供。迁移到 policy/v1beta1 API,从版本 1.10 开始提供。可以通过 policy/v1beta1 API 检索现有的持久数据。

  • DaemonSet、Deployment、StatefulSet 和 ReplicaSet 资源将不再从版本 1.16 中的 extensions/v1beta1apps/v1beta1apps/v1beta2 提供。迁移到 apps/v1 API,从版本 1.9 开始提供。可以通过 apps/v1 API 检索现有的持久数据。例如,要转换当前使用 apps/v1beta1 的 Deployment,请输入以下命令。

    kubectl convert -f ./<my-deployment.yaml> --output-version apps/v1
    注意

    上一个命令使用的默认值可能与当前清单文件中设置的值不同。要了解有关特定资源的更多信息,请参阅 Kubernetes API 参考

如果您最初使用 Kubernetes 版本 1.11 或更早版本创建了 Amazon EKS 集群,但尚未删除--resource-container标志kube-proxyDaemonSet,然后更新到 Kubernetes 1.16 将导致kube-proxy失败。Kubernetes 1.16 不再支持此标志。有关更多信息,请参阅 。kube-proxyKubernetes 1.16 弃用和删除。在更新到 Kubernetes 1.16 之前,您必须删除此标志。

更新到 1.16 之前需要执行的操作

  • 更改您的 YAML 文件以引用新的 API。

  • 更新自定义集成和控制器以调用新的 API。

  • 确保您使用任何第三方工具的更新版本,例如入口控制器、持续交付系统以及调用新 API 的其他工具。

    要轻松检查集群中已停用的 API 使用情况,请确保将audit 控制层面日志处于启用状态,然后指定v1beta作为事件的过滤器。所有替换 API 都位于高于 1.10 的 Kubernetes 版本中。Amazon EKS 任何受支持版本的 Amazon EKS 上的应用程序现在都可以开始使用更新的 API。

  • 删除--resource-container=""标志从您的kube-proxyDaemonSet 群,如果您的集群最初是使用 Kubernetes 1.11 或更早版本部署的,或使用 kube-proxy 配置文件(推荐)。若要确定您的当前版本kube-proxy具有标记,请输入以下命令。

    kubectl get daemonset kube-proxy --namespace kube-system -o yaml | grep 'resource-container='

    如果您没有收到输出,则无需删除任何内容。如果您收到类似于--resource-container="",那么你需要删除标志。输入以下命令来编辑当前kube-proxy配置。

    kubectl edit daemonset kube-proxy --namespace kube-system

    打开编辑器后,删除--resource-container=""行,然后保存文件。我们建议您改为开始使用 kube-proxy 配置文件。为此,请下载以下清单。

    curl -o kube-proxy-daemonset.yaml https://s3.cn-north-1.amazonaws.com.cn/amazon-eks/cloudformation/2020-06-10/kube-proxy-daemonset.yaml

    使用以下命令确定集群的终端节点。

    aws eks describe-cluster \ --name <cluster-name> \ --region <region-code> \ --query 'cluster.endpoint' \ --output text

    您可以在一个 (扩展) 代码行中执行所有这些操作:

    https://<A89DBB2140C8AC0C2F920A36CCC6E18C>.sk1.<region-code>.eks.amazonaws.com

    编辑 kube-proxy-daemonset.yaml文件。在编辑器中,将<MASTER_ENDPOINT>(包括<>)与上一个命令的输出一起。Replace<REGION>与您的集群区域一起使用。在同一行上,如有必要,将版本替换为集群版本。使用以下命令应用文件。

    kubectl apply -f kube-proxy-daemonset.yaml

在现有群集上启用信封加密

如果启用密钥加密,Kubernetes 密钥将使用Amazon Key Management Service您选择的客户主密钥 (CMK)。CMK 必须对称,在与集群相同的区域中创建,如果在不同的账户中创建了 CMK,则用户必须具有对 CMK 的访问权限。有关更多信息,请参阅 。允许其他账户中的用户使用 CMK中的Amazon Key Management Service开发人员指南。Kubernetes 版本支持在现有群集上启用信封加密1.13或更高版本.

警告

启用信封加密后,无法禁用信封加密。这一行动是不可逆的。

eksctl

可以通过下列两种方式启用加密:

  • 使用单个命令将加密添加到您的集群中。

    要自动重新加密密码,请执行以下操作:

    eksctl utils enable-secrets-encryption / --cluster <my-cluster> / --key-arn arn:aws-cn:kms:<Region-code>:<account>:key/<key>

    要选择退出自动重新加密密码,请执行以下操作:

    eksctl utils enable-secrets-encryption --cluster <my-cluster> / --key-arn arn:aws-cn:kms:<Region-code>:<account>:key/<key> / --encrypt-existing-secrets=false
  • 使用 .yaml 文件向集群添加加密。

    # cluster.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: <my-cluster> region: <Region-code> secretsEncryption: keyARN: arn:aws-cn:kms:<Region-code>:<account>:key/<key>

    要自动重新加密密码,请执行以下操作:

    eksctl utils enable-secrets-encryption -f kms-cluster.yaml

    要选择退出自动重新加密密码,请执行以下操作:

    eksctl utils enable-secrets-encryption -f kms-cluster.yaml --encrypt-existing-secrets=false
Amazon Web Services Management Console
  1. 从打开 Amazon EKS 控制台https://console.aws.amazon.com/eks/home#/clusters

  2. 选择要向其添加 KMS 加密的集群。

  3. 单击配置选项卡。

  4. 向下滚动到密钥加密部分,然后单击Enable (启用 Gem)按钮。

  5. 从下拉菜单中选择一个键,然后单击Enable (启用 Gem)按钮。如果未列出任何密钥,则必须先创建一个密钥。有关更多信息,请参阅 。创建密钥

  6. 单击确认按钮以使用选定的键。

Amazon CLI
  1. 使用以下方法将信封加密配置与您的集群关联Amazon CLI命令。将替换为<example-values>(包括<>) 与您自己的值。

    aws eks associate-encryption-config \ --cluster-name <my-cluster> \ --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws-cn:kms:<Region-code>:<account>:key/<key>"}}]'

    输出:

    {   "update": {     "id": "<3141b835-8103-423a-8e68-12c2521ffa4d>",     "status": "InProgress",     "type": "AssociateEncryptionConfig",     "params": [       {         "type": "EncryptionConfig",         "value": "[{\"resources\":[\"secrets\"],\"provider\":{\"keyArn\":\"arn:aws-cn:kms:<Region-code>:<account>:key/<key>\"}}]"       }     ],     "createdAt": <1613754188.734>,     "errors": []   } }
  2. 可使用以下命令监控您的加密更新的状态。使用cluster nameupdate ID中返回的输出上面的步骤。当状态显示为 Successful 时,您的更新将完成。

    aws eks describe-update \ --region <Region-code> \ --name <my-cluster> \ --update-id <3141b835-8103-423a-8e68-12c2521ffa4d>

    输出:

    {   "update": {     "id": "<3141b835-8103-423a-8e68-12c2521ffa4d>",     "status": "Successful",     "type": "AssociateEncryptionConfig",     "params": [       {         "type": "EncryptionConfig",         "value": "[{\"resources\":[\"secrets\"],\"provider\":{\"keyArn\":\"arn:aws-cn:kms:<region-code>:<account>:key/<key>\"}}]"       }     ],     "createdAt": <1613754188.734>,     "errors": []   } }
  3. 要验证您的集群中是否启用了加密,请运行describe-cluster命令。响应将包含EncryptionConfig

    aws eks describe-cluster --region <Region-code> --name <my-cluster>

在群集上启用加密后,您需要使用新密钥加密所有现有密钥:

注意

eksctl用户不需要运行以下命令,除非他们选择不自动重新加密其密码。

kubectl get secrets --all-namespaces -o json | kubectl annotate --overwrite -f - kms-encryption-timestamp="<time value>"
警告

如果您为现有集群启用信封加密,并且您使用的密钥会被删除,则无法恢复集群。删除 CMK 会将集群永久性置于降级状态。

注意

默认情况下,create-key 命令会创建一个具有密钥策略的对称密钥,该密钥策略向账户的根用户管理员授予对 Amazon KMS 操作和资源的访问权限。如果要缩小权限的范围,请确保允许对将调用 create-cluster API 的委托人的密钥策略执行 kms:DescribeKeykms:CreateGrant 操作。

Amazon EKS 不支持密钥策略条件kms:GrantIsForAWSResource。如果此操作位于密钥策略语句中,则将无法创建集群。