将应用程序迁移到新的节点组 - Amazon EKS

帮助改进此页面

想为本用户指南做出贡献? 滚动到页面底部,然后选择在 GitHub 上编辑此页面。您的贡献有助于我们的用户指南为每个人提供更充分的参考。

将应用程序迁移到新的节点组

本主题介绍如何创建新的节点组,将您的现有应用程序自然地迁移到新组,然后从您的集群中删除旧的节点组。您可以使用 eksctl 或 AWS Management Console 迁移到新的节点组。

eksctl
使用 eksctl 将您的应用程序迁移到新的节点组

有关使用 eksctl 进行迁移的更多信息,请参阅 eksctl 文档中的非托管节点组

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

eksctl version

有关安装或升级 eksctl 的说明,请参阅 eksctl 文档中的 Installation

注意

此过程仅适用于使用 eksctl 创建的集群和节点组。

  1. 检索您现有节点组的名称,同时将 my-cluster 替换为您的集群名称。

    eksctl get nodegroups --cluster=my-cluster

    示例输出如下。

    CLUSTER NODEGROUP CREATED MIN SIZE MAX SIZE DESIRED CAPACITY INSTANCE TYPE IMAGE ID default standard-nodes 2019-05-01T22:26:58Z 1 4 3 t3.medium ami-05a71d034119ffc12
  2. eksctl 和下面的命令启动新节点组。将命令中的所有 example value 替换为您自己的值。版本号不能高于控制面板的 Kubernetes 版本。此外,它不能比控制面板的 Kubernetes 版本低两个以上的次要版本。我们建议您使用与控制面板相同的版本。

    如果满足以下条件,我们建议阻止 Pod 访问 IMDS:

    • 您计划将 IAM 角色分配到所有 Kubernetes 服务账户,以便 Pods 只具有所需的最低权限。

    • 集群中没有任何 Pods 需要出于其他原因(例如检索当前 AWS 区域)访问 Amazon EC2 实例元数据服务(IMDS)。

    有关更多信息,请参阅限制对分配给工作节点的实例配置文件的访问

    要阻止 Pod 对 IMDS 的访问,请将 --disable-pod-imds 选项添加到以下命令。

    注意

    有关更多可用标志及其说明,请参阅 https://eksctl.io/

    eksctl create nodegroup \ --cluster my-cluster \ --version 1.31 \ --name standard-nodes-new \ --node-type t3.medium \ --nodes 3 \ --nodes-min 1 \ --nodes-max 4 \ --managed=false
  3. 当上一个命令完成时,使用以下命令验证您的所有节点是否已达到 Ready 状态:

    kubectl get nodes
  4. 使用以下命令删除原始节点组。在命令中,将每个 example value 替换为集群和节点组名称:

    eksctl delete nodegroup --cluster my-cluster --name standard-nodes-old
AWS Management Console and AWS CLI
使用 AWS Management Console 和 AWS CLI 将您的应用程序迁移到新的节点组。
  1. 执行 创建自行管理的 Amazon Linux 节点 中概述的步骤,启动新的节点组。

  2. 完成创建堆栈后,在控制台中选中它,然后选择 Outputs(输出)

  3. 记录已创建的节点组的 NodeInstanceRole。您需要它来将新的 Amazon EKS 节点添加到集群。

    注意

    如果您已将任何其他 IAM policy 附加到旧节点组 IAM 角色,则应将这些相同的策略附加到新节点组 IAM 角色以在新组上保持该功能。这适用于为 Kubernetes Cluster Autoscaler 添加权限的情况。

  4. 同时更新两个节点组的安全组,以便它们可以相互通信。有关更多信息,请参阅 查看集群的 Amazon EKS 安全组要求

    1. 记下两个节点组的安全组 ID。这在 AWS CloudFormation 堆栈输出中显示为 NodeSecurityGroup 值。

      您可以使用以下 AWS CLI 命令从堆栈名称中获取安全组 ID。在这些命令中,oldNodes 是您的较旧节点堆栈的 AWS CloudFormation 堆栈名称,newNodes 是要迁移到的堆栈的名称。将每个 example value 替换为您自己的值。

      oldNodes="old_node_CFN_stack_name" newNodes="new_node_CFN_stack_name" oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text) newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text)
    2. 向每个节点安全组添加入口规则,以便它们接受彼此的流量。

      以下 AWS CLI 命令向每个安全组添加入站规则,以允许来自另一个安全组的所有协议上的所有流量。通过此配置,在您将工作负载迁移到新组时,每个节点组中的 Pods 都可以相互通信。

      aws ec2 authorize-security-group-ingress --group-id $oldSecGroup \ --source-group $newSecGroup --protocol -1 aws ec2 authorize-security-group-ingress --group-id $newSecGroup \ --source-group $oldSecGroup --protocol -1
  5. 编辑 aws-auth configmap 以在 RBAC 中映射新的节点实例角色。

    kubectl edit configmap -n kube-system aws-auth

    为新的节点组添加新的 mapRoles 条目。如果您的集群位于 AWS GovCloud(美国东部)或 AWS GovCloud(美国西部)AWS 区域,则将 arn:aws: 替换为 arn:aws-us-gov:

    apiVersion: v1 data: mapRoles: | - rolearn: ARN of instance role (not instance profile) username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes> - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-U11V27W93CX5 username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes

    ARN of instance role (not instance profile) 代码段替换为您在上一步中记录的 NodeInstanceRole 值,然后保存该文件。保存并关闭该文件以应用更新后的 configmap。

  6. 查看节点的状态并等待新节点加入您的集群并达到 Ready 状态。

    kubectl get nodes --watch
  7. (可选)如果使用 Kubernetes Cluster Autoscaler,请将部署缩减到 0 个副本以避免相互冲突的扩缩操作。

    kubectl scale deployments/cluster-autoscaler --replicas=0 -n kube-system
  8. 使用以下命令,对要使用 NoSchedule 删除的每个节点执行 Taint 操作。这样不会在要替换的节点上安排或重新安排新 Pods。有关更多信息,请参阅 Kubernetes 文档中的污点和容忍度

    kubectl taint nodes node_name key=value:NoSchedule

    如果您要将节点升级到新的 Kubernetes 版本,则可以使用以下代码段标识特定 Kubernetes 版本(此示例中为 1.29)的所有节点并对其执行污点操作。版本号不能高于控制面板的 Kubernetes 版本。此外,它不能比控制面板的 Kubernetes 版本低两个以上的次要版本。我们建议您使用与控制面板相同的版本。

    K8S_VERSION=1.29 nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}") for node in ${nodes[@]} do echo "Tainting $node" kubectl taint nodes $node key=value:NoSchedule done
  9. 确定集群的 DNS 提供商。

    kubectl get deployments -l k8s-app=kube-dns -n kube-system

    示例输出如下。此集群使用 CoreDNS 解析 DNS,但您的集群可能会返回 kube-dns):

    NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE coredns 1 1 1 1 31m
  10. 如果您的当前部署所运行的副本少于 2 个,请将部署扩展到 2 个副本。如果您的上一个命令输出返回了该项,请将 coredns 替换为 kubedns

    kubectl scale deployments/coredns --replicas=2 -n kube-system
  11. 使用以下命令耗尽要从集群中删除的每个节点:

    kubectl drain node_name --ignore-daemonsets --delete-local-data

    如果您要将节点升级到新的 Kubernetes 版本,则使用以下代码段标识并耗尽特定 Kubernetes 版本(此示例中为 1.29)的所有节点。

    K8S_VERSION=1.29 nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}") for node in ${nodes[@]} do echo "Draining $node" kubectl drain $node --ignore-daemonsets --delete-local-data done
  12. 在旧节点耗尽后,请撤销您之前授权的安全组入口规则。然后删除 AWS CloudFormation 堆栈以终止实例。

    注意

    如果您已将任何其他 IAM policy 附加到旧节点组 IAM 角色(例如,为 Kubernetes Cluster Autoscaler 添加权限),请先将这些附加策略与该角色分离,然后才能删除 AWS CloudFormation 堆栈。

    1. 撤销您之前为节点安全组创建的入站规则。在这些命令中,oldNodes 是您的较旧节点堆栈的 AWS CloudFormation 堆栈名称,newNodes 是要迁移到的堆栈的名称。

      oldNodes="old_node_CFN_stack_name" newNodes="new_node_CFN_stack_name" oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text) newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text) aws ec2 revoke-security-group-ingress --group-id $oldSecGroup \ --source-group $newSecGroup --protocol -1 aws ec2 revoke-security-group-ingress --group-id $newSecGroup \ --source-group $oldSecGroup --protocol -1
    2. 打开 AWS CloudFormation 控制台,地址:https://console.aws.amazon.com/cloudformation

    3. 选择您的旧节点堆栈。

    4. 选择删除

    5. Delete stack(删除堆栈)确认对话框中,请选择 Delete stack(删除堆栈)。

  13. 编辑 aws-auth configmap 以从 RBAC 中删除旧节点实例角色。

    kubectl edit configmap -n kube-system aws-auth

    删除旧节点组的 mapRoles 条目。如果您的集群位于 AWS GovCloud(美国东部)或 AWS GovCloud(美国西部)AWS 区域,则将 arn:aws: 替换为 arn:aws-us-gov:

    apiVersion: v1 data: mapRoles: | - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-W70725MZQFF8 username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes - rolearn: arn:aws:iam::111122223333:role/nodes-1-15-NodeInstanceRole-U11V27W93CX5 username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes>

    保存并关闭该文件以应用更新后的 configmap。

  14. (可选)如果您使用的是 Kubernetes Cluster Autoscaler,请将部署缩减为 1 个副本。

    注意

    您还必须适当地标记新的弹性缩放组(例如,k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster)并将您的 Cluster Autoscaler 部署命令更新为指向新标记的 Auto Scaling 组。有关更多信息,请参阅 AWS 上的 Cluster Autoscaler

    kubectl scale deployments/cluster-autoscaler --replicas=1 -n kube-system
  15. (可选)确认您使用的是最新版本的 Kubernetes 的 Amazon VPC CNI 插件。您可能需要更新 CNI 版本以使用最新的受支持实例类型。有关更多信息,请参阅 使用 Amazon VPC CNI 将 IP 分配给 Pods

  16. 如果您的集群使用适用于 DNS 解析的 kube-dns(请参阅上一步),请将 kube-dns 部署缩减为 1 个副本。

    kubectl scale deployments/kube-dns --replicas=1 -n kube-system