使用 CI/CD 管道在 Amazon EKS 中自动部署 Node Termination Handler - AWS Prescriptive Guidance

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

使用 CI/CD 管道在 Amazon EKS 中自动部署 Node Termination Handler

由 Sandip Gangapadhyay (AWS)、John Vargas (AWS)、Pragtideep Singh (AWS)、Sandeep Gawande (AWS) 和 Viyoma Sachdeva (AWS) 编写

代码存储库:将 NTH 部署到 EKS

环境:生产

技术:容器和微服务; DevOps

AWS 服务:AWS CodePipeline;Amazon EKS;AWS CodeBuild

Summary

在 Amazon Web Services (AWS) 云上,您可以使用 AWS Node Termination Handler(一个开源项目)来正常地处理 Kubernetes 内的 Amazon Elastic Compute Cloud (Amazon EC2) 实例关闭。Node Termination Handler 有助于确保 Kubernetes 控制面板对可能导致 EC2 实例不可用的事件做出适当的响应。这些事件包括:

如果未处理事件,您的应用程序代码可能无法正常停止。恢复完全可用性也可能需要更长的时间,或者可能会意外地将工作安排到正在关闭的节点上。aws-node-termination-handler(NTH)可以在两种不同的模式下运行:实例元数据服务(IMDS)或队列处理器。有关这两种模式的更多信息,请参阅自述文件

此模式通过持续集成和持续交付(CI/CD)管道使用队列处理器自动部署 NTH。

注意:如果您使用的是 EKS 托管节点组,则不需要 aws-node-termination-handler

先决条件和限制

先决条件

  • 一个有效的 Amazon Web Services account。

  • 支持与 AWS 管理控制台 配合使用的 Web 浏览器。参阅支持的浏览器列表

  • AWS Cloud Development Kit (AWS CDK) 已安装

  • kubectl,Kubernetes 命令行工具,已安装

  • eksctl安装了适用于 Amazon Elastic Kubernetes Service (Amazon EKS) 的 AWS 命令行界面(AWS CLI)。

  • 运行的 EKS 集群,版本 1.20 或以上。

  • 连接至 EKS 集群的自托管式节点组。运行以下命令创建具有自托管式节点组的Amazon EKS集群。

    eksctl create cluster --managed=false --region <region> --name <cluster_name>

    有关 eksctl 的更多信息,请参阅 eksctl 文档

  • 适用于您的集群的 AWS Identity and Access Management (IAM) OpenID Connect (OIDC) 提供程序。有关更多信息,请参阅为您的集群创建 IAM OIDC 提供程序

限制

  • 您必须使用支持 Amazon EKS 服务的 AWS 区域。

产品版本

  • Kubernetes 版本 1.20 或更高版本

  • eksctl 版本 0.107.0 或更高版本

  • AWS CDK 版本 2.27.0 或更高版本

架构

目标技术堆栈

  • 虚拟私有云(VPC)

  • EKS 集群

  • Amazon Simple Queue Service(Amazon SQS)

  • IAM

  • Kubernetes

目标架构

下图显示了节点终止开始时 end-to-end 步骤的高级视图。

一个带有 Auto Scaling 组的 VPC、一个带有节点终止处理程序的 EKS 集群和 SQS 队列。

图中显示的工作流包含以下概要步骤:

  1. 自动扩缩 EC2 实例终止事件发送到 SQS 队列。

  2. NTH 容器组(pod)监控 SQS 队列中的新消息。

  3. NTH 容器组(pod)收到新消息并执行以下操作:

    • 封锁节点,这样新的容器组(pod)就不会在该节点上运行。

    • 排空节点,以便撤出现有容器组(pod)

    • 向自动扩缩组发送生命周期挂钩信号,以便可以终止该节点。

自动化和扩缩

工具

Amazon Web Services

  • AWS Cloud Development Kit (AWS CDK) 是一个软件开发框架,可帮助您在代码中定义和预调配 Amazon Web Services Cloud 基础设施。

  • AWS CodeBuild 是一项完全托管的构建服务,可帮助您编译源代码、运行单元测试和生成可随时部署的项目。

  • AWS CodeCommit 是一项版本控制服务,可帮助您私下存储和管理 Git 存储库,而无需管理自己的源代码控制系统。

  • AWS CodePipeline 可帮助您快速建模和配置软件发布的不同阶段,并自动执行持续发布软件变更所需的步骤。

  • Amazon Elastic Kubernetes Service (Amazon EKS) 可帮助您在 AWS 上运行 Kubernetes,而无需安装或维护您自己的 Kubernetes 控制面板或节点。

  • Amazon EC2 Auto Scaling 可帮助您保持应用程序的可用性,并允许您根据自己定义的条件自动添加或删除 Amazon EC2 实例。

  • Amazon Simple Queue Service (Amazon SQS) 提供了一个安全、持久且可用的托管队列,它可帮助您集成和分离分布式软件系统与组件。

其他工具

  • kubectl 是针对 Kubernetes 集群运行命令的Kubernetes命令行工具。您可使用 kubectl 部署应用程序、检查和管理集群资源以及查看日志。

代码

此模式的代码可在 GitHub .com 的deploy-nth-to-eks存储库中找到。代码库包含以下文件和文件夹。

  • nth folder— Helm 图表、值文件以及用于扫描和部署节点终止处理程序的 AWS CloudFormation 模板的脚本。

  • config/config.json — 应用程序的配置参数文件。此文件包含部署 CDK 所需所有参数。

  • cdk — AWS CDK 源代码。

  • setup.sh — 用于部署 AWS CDK 应用程序以创建所需 CI/CD 管道和其他所需资源的脚本。

  • uninstall.sh — 用于清理资源的脚本。

要使用示例代码,请按照操作说明部分中的说明执行操作。

最佳实践

有关自动化 AWS Node Termination Handler 的最佳实践,请参见以下内容:

操作说明

任务描述所需技能

克隆存储库。

要使用 SSH(Secure Shell)克隆存储库,请运行以下命令。

git clone git@github.com:aws-samples/deploy-nth-to-eks.git

要使用HTTPS克隆存储库,请运行以下命令。

git clone https://github.com/aws-samples/deploy-nth-to-eks.git

克隆存储库会创建一个名为 deploy-nth-to-eks 的文件夹。

切换到该目录。

cd deploy-nth-to-eks
应用程序开发人员、AWS DevOps、 DevOps 工程师

设置 kubeconfig 文件。

在您的终端设置您的 AWS 凭证,并确认您有权担任集群角色。您可使用以下示例代码。

aws eks update-kubeconfig --name <Cluster_Name> --region <region>--role-arn <Role_ARN>
AWS DevOps, DevOps 工程师,应用程序开发人员
任务描述所需技能

设置参数。

config/config.json 文件中,设置以下必需参数。

  • pipelineName:要由 AWS CDK 创建的 CI/CD 管道的名称(例如 deploy-nth-to-eks-pipeline)。AWS CodePipeline 将创建一个具有此名称的管道。

  • repositoryName:要创建的 CodeCommit AWS 存储库(例如,deploy-nth-to-eks-repo)。AWS CDK 将创建此存储库并将其设置为 CI/CD 管道来源。

    注意:此解决方案将创建此 CodeCommit 存储库和分支(在以下 branch 参数中提供)。

  • branch:存储库中的分支名称(例如 main)。对该分支的提交将启动 CI/CD 管道。

  • cfn_scan_script:将用于扫描 AWS CloudFormation 模板以获取 NTH (scan.sh) 的脚本路径。此脚本存在于将成为 AWS CodeCommit 存储库一部分的nth文件夹中。

  • cfn_deploy_script: 将用于部署 NTH 的 AWS CloudFormation 模板的脚本路径 (installApp.sh)。

  • stackName:要部署的 CloudFormation 堆栈的名称。

  • eksClusterName –现有 EKS 集群的名称。

  • eksClusterRole:用于访问所有 Kubernetes API 调用的 EKS 集群的 IAM 角色(例如 clusteradmin)。通常,此角色在 aws-auth ConfigMap 中添加。

  • create_cluster_role:若要创建 eksClusterRole IAM 角色,请输入。如果要在 eksClusterRole 参数中提供现有的集群角色,请输入

  • create_iam_oidc_provider: 要为集群创建 IAM OIDC 提供程序,请输入。如果 IAM OIDC 提供程序已经存在,请输入。有关更多信息,请参阅为您的集群创建 IAM OIDC 提供程序

  • AsgGroupName:属于 EKS 集群的自动扩缩组名称的逗号分隔列表(例如 ASG_Group_1,ASG_Group_2)。

  • region:集群所在的 AWS 区域的名称(例如 us-east-2)。

  • install_cdk:如果计算机上当前未安装 AWS CDK,请输入。运行 cdk --version 命令检查安装的 AWS CDK 版本是否为 2.27.0 或更高版本。在这种情况下,请输入

    如果您输入,setup.sh 脚本将运行在计算机上安装 AWS CDK sudo npm install -g cdk@2.27.0 命令。该脚本需要 sudo 权限,因此请在出现提示时提供账户密码。

应用程序开发人员、AWS DevOps、 DevOps 工程师

创建 CI/CD 管道,以部署 NTH。

运行setup.sh脚本。

./setup.sh

该脚本将部署 AWS CDK 应用程序,该应用程序将根据文件中的config/config.json用户输入参数使用示例代码、管道和 CodeBuild 项目创建 CodeCommit 存储库。

该脚本在使用 sudo 命令安装 npm 软件包时将要求输入密码。

应用程序开发人员、AWS DevOps、 DevOps 工程师

查看 CI/CD 管道。

打开 AWS 管理控制台,查看在堆栈中创建的以下资源。

  • CodeCommit 包含文件夹内容的 repo nth

  • AWS CodeBuild 项目cfn-scan,它将扫描 CloudFormation 模板中是否存在漏洞。

  • CodeBuild 项目Nth-Deploy,它将通过 AWS CodePipeline 管道部署 AWS CloudFormation 模板和相应的 NTH Helm 图表。

  • 用于部署 NTH 的 CodePipeline 管道。

管道成功运行后,Helm 版本 aws-node-termination-handler 将安装在 EKS 集群中。此外,名为 aws-node-termination-handler 的容器组(pod)正在集群的 kube-system 命名空间中运行。

应用程序开发人员、AWS DevOps、 DevOps 工程师
任务描述所需技能

模拟自动扩缩组横向缩减事件。

要模拟自动扩缩横向缩减事件,请执行以下操作:

  1. 在 Amazon Web Services Console 上,打开 EC2 控制台,然后选择自动扩缩组

  2. 选择与 config/config.json 中提供的组同名的自动扩缩组,然后选择编辑

  3. 所需容量和最小容量减少 1。

  4. 选择更新

查看日志。

在横向缩减事件期间,NTH 容器组(pod)将封锁并耗尽相应的 Worker 节点(作为缩容事件的一部分终止横向缩减的 EC2 实例)。要查看日志,请使用其他信息部分中的代码。

应用程序开发人员、AWS DevOps、 DevOps 工程师
任务描述所需技能

清理全部 AWS 资源。

锐欧要清理此模式创建的资源,请运行以下命令。

./uninstall.sh

这将通过删除 CloudFormation 堆栈来清理在此模式中创建的所有资源。

DevOps 工程师

故障排除

问题解决方案

npm 注册表设置不正确。

在此解决方案的安装过程中,脚本会安装 npm install 以下载所有必需的软件包。如果在安装过程中看到找不到模块的消息,则可能无法正确设置 npm 注册表。要查看当前的注册表设置,请运行以下命令。

npm config get registry

运行以下命令以设置 https://registry.npmjs.org/ 注册表。

npm config set registry https://registry.npmjs.org

延迟 SQS 消息传送。

作为故障排除的一部分,如果您想延迟向 NTH 容器组(pod)传送 SQS 消息,可以调整 SQS 传送延迟参数。有关更多信息,请参阅 Amazon SQS 延迟队列

相关资源

其他信息

1. 找到 NTH 容器组(pod)的名字。

kubectl get pods -n kube-system |grep aws-node-termination-handler aws-node-termination-handler-65445555-kbqc7 1/1 Running 0 26m kubectl get pods -n kube-system |grep aws-node-termination-handler aws-node-termination-handler-65445555-kbqc7 1/1 Running 0 26m

2. 检查日志。日志示例如下所示。它表明在发送自动扩缩组生命周期挂钩完成信号之前,该节点已被封锁并耗尽。

kubectl -n kube-system logs aws-node-termination-handler-65445555-kbqc7 022/07/17 20:20:43 INF Adding new event to the event store event={"AutoScalingGroupName":"eksctl-my-cluster-target-nodegroup-ng-10d99c89-NodeGroup-ZME36IGAP7O1","Description":"ASG Lifecycle Termination event received. Instance will be interrupted at 2022-07-17 20:20:42.702 +0000 UTC \n","EndTime":"0001-01-01T00:00:00Z","EventID":"asg-lifecycle-term-33383831316538382d353564362d343332362d613931352d383430666165636334333564","InProgress":false,"InstanceID":"i-0409f2a9d3085b80e","IsManaged":true,"Kind":"SQS_TERMINATE","NodeLabels":null,"NodeName":"ip-192-168-75-60.us-east-2.compute.internal","NodeProcessed":false,"Pods":null,"ProviderID":"aws:///us-east-2c/i-0409f2a9d3085b80e","StartTime":"2022-07-17T20:20:42.702Z","State":""} 2022/07/17 20:20:44 INF Requesting instance drain event-id=asg-lifecycle-term-33383831316538382d353564362d343332362d613931352d383430666165636334333564 instance-id=i-0409f2a9d3085b80e kind=SQS_TERMINATE node-name=ip-192-168-75-60.us-east-2.compute.internal provider-id=aws:///us-east-2c/i-0409f2a9d3085b80e 2022/07/17 20:20:44 INF Pods on node node_name=ip-192-168-75-60.us-east-2.compute.internal pod_names=["aws-node-qchsw","aws-node-termination-handler-65445555-kbqc7","kube-proxy-mz5x5"] 2022/07/17 20:20:44 INF Draining the node 2022/07/17 20:20:44 ??? WARNING: ignoring DaemonSet-managed Pods: kube-system/aws-node-qchsw, kube-system/kube-proxy-mz5x5 2022/07/17 20:20:44 INF Node successfully cordoned and drained node_name=ip-192-168-75-60.us-east-2.compute.internal reason="ASG Lifecycle Termination event received. Instance will be interrupted at 2022-07-17 20:20:42.702 +0000 UTC \n" 2022/07/17 20:20:44 INF Completed ASG Lifecycle Hook (NTH-K8S-TERM-HOOK) for instance i-0409f2a9d3085b80e