迁移到新的节点组 - Amazon EKS
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

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

迁移到新的节点组

本主题可帮助您创建新节点组,将现有应用程序正常地迁移到新组,然后从集群中删除旧节点组。您可以使用 eksctlAWS 管理控制台 迁移到新的节点组。

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

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

eksctl version

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

注意

此过程仅适用于使用 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 values>(包括 <>)替换为您自己的值。版本号不能高于控制层面的 Kubernetes 版本,并且不能比控制层面的 Kubernetes 版本早两个以上的次要版本,不过我们建议您使用与控制层面相同的版本。如果您计划将 IAM 角色分配给所有 Kubernetes 服务账户,以便 Pod 只拥有所需的最低权限,并且集群中没有 Pod 出于其他原因(例如,检索当前区域)需要访问 Amazon EC2 实例元数据服务 (IMDS),那么我们建议阻止 Pod 访问 IMDS。有关更多信息,请参阅 服务账户的 IAM 角色限制对 IMDS 和 Amazon EC2 实例配置文件凭证的访问。如果要阻止 Pod 对 IMDS 的访问,请将 --disable-pod-imds 选项添加到以下命令。

    注意

    有关更多可用的标签及其对应描述,请参阅 https://eksctl.io/

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

    kubectl get nodes
  4. 使用以下命令删除原始节点组,同时将 <example values>(包括 <>)替换为您的集群和节点组名称:

    eksctl delete nodegroup --cluster <my-cluster> --name <standard-nodes>

使用 AWS 管理控制台 和 AWS CLI 将应用程序迁移到新节点组

  1. 按照启动自管理 Amazon Linux 节点中概述的步骤启动新的节点组。

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

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

    注意

    如果您已将任何其他 IAM 策略附加到旧节点组 IAM 角色(例如为 Kubernetes Cluster Autoscaler 添加权限),则应将这些相同的策略附加到新节点组 IAM 角色以在新组上维护该功能。

  4. 更新两个节点组的安全组,以便它们可以相互通信。有关更多信息,请参阅 Amazon EKS 安全组注意事项.

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

      您可以使用以下 AWS CLI 命令从堆栈名称中获取安全组 ID。在这些命令中,oldNodes 是您的较早节点堆栈的 AWS CloudFormation 堆栈名称,newNodes 是您要迁移到的堆栈的名称。将 <example values>(包括 <>)替换为您自己的值。

      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 命令向每个安全组添加入口规则,以允许来自另一个安全组的所有协议上的所有流量。此配置允许每个节点组中的 Pod 在您将工作负载迁移到新组时相互通信。

      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 配置映射以在 RBAC 中映射新的节点实例角色。

    kubectl edit configmap -n kube-system aws-auth

    为新的节点组添加新的 mapRoles 条目。

    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 操作,以便在要替换的节点上不计划或重新计划新的 Pod:

    kubectl taint nodes <node_name> key=value:NoSchedule

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

    K8S_VERSION=<1.16> 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

    输出(此集群使用的是适用于 DNS 解析的 kube-dns,但您的集群可能会改为返回 coredns

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

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

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

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

    K8S_VERSION=<1.16> 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 策略附加到旧节点组 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. https://console.amazonaws.cn/cloudformation 打开 AWS CloudFormation 控制台。

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

    4. 选择 Actions (操作),然后选择 Delete stack (删除堆栈).

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

    kubectl edit configmap -n kube-system aws-auth

    删除旧节点组的 mapRoles 条目。

    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,请将部署缩减为一个副本。

    注意

    您还必须适当地标记新的 Auto Scaling 组(例如,k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<YOUR CLUSTER NAME>)并将您的 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适用于 Kubernetes 的 CNI 插件升级.

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

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