

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

# 使用 CI/CD 管道在 Amazon EKS 中自动部署节点终止处理程序
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline"></a>

*Sandip Gangapadhyay、Sandeep Gawande、Viyoma Sachdeva、Pragtideep Singh 和 John Vargas，Amazon Web Services*

## Summary
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-summary"></a>

**注意**： CodeCommit AWS 不再向新客户开放。AWS 的现有客户 CodeCommit 可以继续照常使用该服务。[了解详情](https://aws.amazon.com/blogs/devops/how-to-migrate-your-aws-codecommit-repository-to-another-git-provider/)

在亚马逊网络服务 (AWS) 云上，您可以使用开源项目 [AWS 节点终止处理程序](https://github.com/aws/aws-node-termination-handler)来优雅地处理 Kubernetes 中的亚马逊弹性计算云 (Amazon EC2) 实例关闭。AWS 节点终止处理程序有助于确保 Kubernetes 控制平面对可能导致您的 EC2 实例不可用的事件做出适当的响应。这些事件包括：
+ [EC2 实例定期维护](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html)
+ [Amazon EC2 竞价型实例中断](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-interruptions.html)
+ [自动扩缩组横向缩减](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroupLifecycle.html#as-lifecycle-scale-in)
+ [自动扩缩组在可用区域间再平衡](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-benefits.html#AutoScalingBehavior.InstanceUsage)
+ EC2 通过 API 或 AWS 管理控制台终止实例

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

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

**注意**  
如果您使用的是 [EKS 托管节点组](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)，则不需要 `aws-node-termination-handler`。

## 先决条件和限制
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-prereqs"></a>

**先决条件**
+ 一个活跃的 AWS 账户。
+ 支持与 AWS 管理控制台 配合使用的 Web 浏览器。参阅[支持的浏览器列表](https://aws.amazon.com/premiumsupport/knowledge-center/browsers-management-console/)。
+ AWS Cloud Development Kit (AWS CDK) [已安装](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install)。
+ `kubectl`，Kubernetes 命令行工具，[已安装](https://kubernetes.io/docs/tasks/tools/)。
+ `eksctl`，[安装了](https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html)适用于 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 文档](https://eksctl.io/usage/creating-and-managing-clusters/)。
+ 适用于您的集群的 AWS Identity and Access Management (IAM) OpenID Connect (OIDC) 提供程序。有关更多信息，请参阅[为您的集群创建 IAM OIDC 提供程序](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html)。

**限制**
+ 您必须使用支持 Amazon EKS 服务的 AWS 区域。

**产品版本**
+ Kubernetes 版本 1.20 或更高版本
+ `eksctl` 版本 0.107.0 或更高版本
+ AWS CDK 版本 2.27.0 或更高版本

## 架构
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-architecture"></a>

**目标技术堆栈**
+ 虚拟私有云（VPC）
+ EKS 集群
+ Amazon Simple Queue Service(Amazon SQS)
+ IAM
+ Kubernetes

**目标架构**** **

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

![具有自动扩缩组的 VPC、具有节点终止处理程序的 EKS 集群以及 SQS 队列。](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/images/pattern-img/970dfb73-9526-4942-a974-e8eef6416596/images/9e0125ae-d55b-49dd-ae70-ccaedf03832a.png)


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

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

1. NTH 容器组（pod）监控 SQS 队列中的新消息。

1. NTH 容器组（pod）收到新消息并执行以下操作：
   + 封锁节点，这样新的容器组（pod）就不会在该节点上运行。
   + 排空节点，以便撤出现有容器组（pod）
   + 向自动扩缩组发送生命周期挂钩信号，以便可以终止该节点。

**自动化和扩缩**
+ 代码由 AWS CDK 管理和部署，由 AWS CloudFormation 嵌套堆栈提供支持。
+ [Amazon EKS 控制面板](https://docs.aws.amazon.com/eks/latest/userguide/disaster-recovery-resiliency.html)跨多个可用区运行以确保高可用性。
+ 为了实现[自动扩缩](https://docs.aws.amazon.com/eks/latest/userguide/autoscaling.html)，Amazon EKS 支持 Kubernetes [集群自动扩缩程序](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)和 [Karpenter](https://karpenter.sh/)。

## 工具
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-tools"></a>

**Amazon Web Services**
+ [AWS Cloud Development Kit（AWS CDK）](https://docs.aws.amazon.com/cdk/latest/guide/home.html) 是一个软件开发框架，可帮助您在代码中定义并预调配 AWS 云基础设施。
+ [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html) 是一项完全托管的构建服务，可帮助您编译源代码、运行单元测试和生成可随时部署的项目。
+ [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) 是一项版本控制服务，可帮助您私下存储和管理 Git 存储库，而无需管理自己的源代码控制系统。
+ [AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html) 可帮助您快速建模和配置软件发布的不同阶段，并自动执行持续发布软件变更所需的步骤。
+ [Amazon Elastic Kubernetes Service (Amazon EKS)](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html) 可帮助您在 AWS 上运行 Kubernetes，而无需安装或维护您自己的 Kubernetes 控制面板或节点。
+ [Amazon A EC2 uto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html) 可帮助您保持应用程序的可用性，并允许您根据自己定义的条件自动添加或删除亚马逊 EC2 实例。
+ [Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) 提供了一个安全、持久且可用的托管队列，它可帮助您集成和分离分布式软件系统与组件。

**其他工具**
+ [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) 是针对 Kubernetes 集群运行命令的Kubernetes命令行工具。您可使用 kubectl 部署应用程序、检查和管理集群资源以及查看日志。

**代码**

此模式的代码可在 GitHub .com 的[deploy-nth-to-eks](https://github.com/aws-samples/deploy-nth-to-eks)存储库中找到。代码库包含以下文件和文件夹。
+ `nth folder`— Helm 图表、值文件以及用于扫描和部署节点终止处理程序的 AWS CloudFormation 模板的脚本。
+ `config/config.json` — 应用程序的配置参数文件。此文件包含部署 CDK 所需所有参数。
+ `cdk` — AWS CDK 源代码。
+ `setup.sh`— 用于部署 AWS CDK 应用程序以创建所需 CI/CD 管道和其他所需资源的脚本。
+ `uninstall.sh` — 用于清理资源的脚本。

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

## 最佳实践
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-best-practices"></a>

有关自动化 AWS Node Termination Handler 的最佳实践，请参见以下内容：
+ [EKS 最佳实践指南](https://aws.github.io/aws-eks-best-practices/)
+ [Node Termination Handler - 配置](https://github.com/aws/aws-node-termination-handler/tree/main/config/helm/aws-node-termination-handler)

## 操作说明
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-epics"></a>

### 设置您的环境
<a name="set-up-your-environment"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 克隆存储库。 | 要使用 SSH（Secure Shell）克隆存储库，请运行以下命令。<pre>git clone git@github.com:aws-samples/deploy-nth-to-eks.git</pre><br />要使用HTTPS克隆存储库，请运行以下命令。<pre>git clone https://github.com/aws-samples/deploy-nth-to-eks.git</pre><br />克隆存储库会创建一个名为 `deploy-nth-to-eks` 的文件夹。<br />切换到该目录。<pre>cd deploy-nth-to-eks</pre> | 应用程序开发人员、AWS DevOps、 DevOps 工程师 | 
| 设置 kubeconfig 文件。 | 在您的终端设置您的 AWS 凭证，并确认您有权担任集群角色。您可使用以下示例代码。<pre>aws eks update-kubeconfig --name <Cluster_Name> --region <region>--role-arn <Role_ARN></pre> | AWS DevOps， DevOps 工程师，应用程序开发人员 | 

### 部署 CI/CD 管道
<a name="deploy-the-ci-cd-pipeline"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 设置参数。 | 在 `config/config.json` 文件中，设置以下必需参数。[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline.html) | 应用程序开发人员、AWS DevOps、 DevOps 工程师 | 
| 创建用于部署 NTH 的 CI/CD 管道。 | 运行setup.sh脚本。<pre>./setup.sh</pre><br />该脚本将部署 AWS CDK 应用程序，该应用程序将根据文件中的`config/config.json`用户输入参数使用示例代码、管道和 CodeBuild 项目创建 CodeCommit 存储库。<br />该脚本在使用 sudo 命令安装 npm 软件包时将要求输入密码。 | 应用程序开发人员、AWS DevOps、 DevOps 工程师 | 
| 查看 CI/CD 管道。 | 打开 AWS 管理控制台，查看在堆栈中创建的以下资源。[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline.html)<br />管道成功运行后，Helm 版本 `aws-node-termination-handler` 将安装在 EKS 集群中。此外，名为 `aws-node-termination-handler` 的容器组（pod）正在集群的 `kube-system` 命名空间中运行。 | 应用程序开发人员、AWS DevOps、 DevOps 工程师 | 

### 测试NTH部署
<a name="test-nth-deployment"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 模拟自动扩缩组横向缩减事件。 | 要模拟自动扩缩横向缩减事件，请执行以下操作：[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline.html) |  | 
| 查看日志。 | 在缩容事件期间，第 N 个 Pod 将封锁并耗尽相应的工作节点（作为缩容事件的一部分终止的 EC2 实例）。要查看日志，请使用*其他信息*部分中的代码。 | 应用程序开发人员、AWS DevOps、 DevOps 工程师 | 

### 清理
<a name="clean-up"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 清理全部 AWS 资源。 | 锐欧要清理此模式创建的资源，请运行以下命令。<pre>./uninstall.sh</pre><br />这将通过删除 CloudFormation 堆栈来清理在此模式中创建的所有资源。 | DevOps 工程师 | 

## 问题排查
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-troubleshooting"></a>


| 问题 | 解决方案 | 
| --- | --- | 
| npm 注册表设置不正确。 | 在此解决方案的安装过程中，脚本会安装 npm install 以下载所有必需的软件包。如果在安装过程中看到找不到模块的消息，则可能无法正确设置 npm 注册表。要查看当前的注册表设置，请运行以下命令。<pre>npm config get registry</pre><br />运行以下命令以设置 `https://registry.npmjs.org/` 注册表。<pre>npm config set registry https://registry.npmjs.org</pre> | 
| 延迟 SQS 消息传送。 | 作为故障排除的一部分，如果您想延迟向 NTH 容器组（pod）传送 SQS 消息，可以调整 SQS 传送延迟参数。有关更多信息，请参阅 [Amazon SQS 延迟队列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-delay-queues.html)。 | 

## 相关资源
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-resources"></a>
+ [AWS Node Termination Handler 源代码](https://github.com/aws/aws-node-termination-handler)
+ [EC2 工作坊](https://ec2spotworkshops.com/using_ec2_spot_instances_with_eks/070_selfmanagednodegroupswithspot/deployhandler.html)
+ [AWS CodePipeline](https://aws.amazon.com/codepipeline/)
+ [Amazon Elastic Kubernetes Service(Amazon EKS)](https://aws.amazon.com/eks/)
+ [AWS Cloud Development Kit](https://aws.amazon.com/cdk/)
+ [AWS CloudFormation](https://aws.amazon.com/cloudformation/)

## 附加信息
<a name="automate-deployment-of-node-termination-handler-in-amazon-eks-by-using-a-ci-cd-pipeline-additional"></a>

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
```