更新集群 - Amazon EKS

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

更新集群

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

更新 Amazon EKS 群集 Kubernetes 版本

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

重要

我们建议您在更新到新的 Kubernetes 版本之前,可以查看Amazon EKS 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,AWS Management Console,或AWSCLI。

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

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

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

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

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

    eksctl

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

    eksctl version

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

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

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

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

    AWS 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 (确认)

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

    AWS CLI
    1. 使用以下操作更新集群AWSCLI 命令。将替换为<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附加组件。如果您将集群更新为 1.17 或更早版本,请参阅手动更新亚马逊 VPC CNI 加载项手动更新 CoreDNS 附加组件, 和更新kube-proxy手动加载更新您的亚马逊 VPC CNI、CoreDNS 和kube-proxy附加组件。如果您将集群更新为 1.18,则可以添加 Amazon EKS 加载项。有关更多信息,请参阅 。添加 Amazon VPC 实体 CNI Amazon VPC 附加组件添加已核准的 Amazon EKS 附加组件,或者添加kube-proxyAmazon EKS 附加组件。要了解有关 Amazon EKS 附加组件的更多信息,请参阅Amazon EKS 附加组件。如果您已更新到 1.19 或更高版本,并且正在使用亚马逊 EKS 加载项,请在亚马逊 EKS 控制台中选择集群,然后在左窗格中选择要更新的集群的名称。通知显示在控制台中,通知您有一个新版本可用于每个具有可用更新的插件。要更新附加组件,您可以选择立即更新,选择可用版本,然后选择更新。或者,您也可以选择配置选项卡,然后选择附加项选项卡。如果附加组件有可用更新,则可选择立即更新,选择可用版本,然后选择更新。您也可以使用AWSCLI 更新VPC CNICoreDNS, 和kube-proxyAmazon EKS 附加组件。

  6. (可选)如果您在更新集群之前将 Kubernetes 集群 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=k8s.gcr.io/autoscaling/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 上的应用程序现在都可以开始使用更新的 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://amazon-eks.s3-us-west-2.amazonaws.com/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

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

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

警告

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

eksctl

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

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

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

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

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

    eksctl utils enable-secrets-encryption --cluster <my-cluster> / --key-arn arn:aws: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: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
AWS Management Console
  1. 从打开 Amazon EKS 控制台https://console.aws.amazon.com/eks/home#/clusters

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

  3. 单击配置选项卡。

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

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

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

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

    aws eks associate-encryption-config \ --cluster-name <my-cluster> \ --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws: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: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: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 命令会创建一个具有密钥策略的对称密钥,该密钥策略向账户的根用户管理员授予对 AWS KMS 操作和资源的访问权限。如果要缩小权限的范围,请确保允许对将调用 create-cluster API 的委托人的密钥策略执行 kms:DescribeKeykms:CreateGrant 操作。

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