以更低的成本运行 Kubernetes 使用 Amazon Elastic Kubernetes Service 和 Spot 实例

Amazon Elastic Kubernetes Service (Amazon EKS) 是一项全托管的 Kubernetes 服务,并且经认证符合 Kubernetes 规范,因此您可以利用社区开源工具的所有优势。您无需重构代码即可将任何标准 Kubernetes 应用程序轻松迁移到 EKS。

Amazon EC2 Spot 实例让您能够充分利用 AWS 云中未使用的 EC2 容量。与按需型实例的价格相比,Spot 实例的价格更加经济实惠。

Spot 实例非常适用于在 Kubernetes 集群上运行的 无状态容器化工作负载,因为容器和 Spot 实例采用的方法类似,其一大特征是短暂使用并可自动扩缩的容量。这意味着您可以在遵守 SLA 的同时对其进行添加和移除,而不会影响应用程序的性能或可用性。

Amazon EKS 托管节点组可自动执行 Amazon EKS Kubernetes 集群节点(Amazon EC2 实例)的预配和生命周期管理。

借助 Amazon EKS 托管节点组,您无需单独预配或注册 Amazon EC2 实例来提供运行 Kubernetes 应用程序所需的计算容量。只需单次操作,即可创建、自动更新或终止集群的节点。节点在运行时会使用您 AWS 账户中经过 Amazon EKS 优化的最新 AMI。在终止或更新期间,Amazon EKS 会使用 Kubernetes API 自动驱逐节点。

Amazon EKS Spot 托管节点组遵循 Spot 实例最佳实践,运用容量优化型分配策略,可以从最深的 Spot 实例池中预配 Spot 实例。Amazon EKS Spot 托管节点组通过容量再平衡功能,以确保当 Spot 节点的中断风险上升时,Amazon EKS 可以自动地适当驱逐并重新平衡您的 Spot 节点。

在本教程中,您将学习如何使用 Spot 托管节点组将 Spot 实例添加到 EKS 集群。您还将运行一个示例 Kubernetes 部署,并使用 Kubernetes Cluster Autoscaler 在 Spot 实例节点上对其进行自动扩缩。

关于本教程
时间 30 分钟
费用 不到 5 美元
使用场景 容器、计算
产品 Elastic Kubernetes Service、EC2 Spot 实例
级别 300
上次更新时间 2021 年 5 月 13 日

已经拥有账户?登录您的账户

步骤 1:设置权限(若使用 Cloud9)

如果您已经拥有使用 eksctl 启动的 EKS 集群,请跳到步骤 4,在现有集群中添加 Spot 实例。

1.1 — 登录 AWS 管理控制台。依次点击 IAM、Roles(角色)和 Create Role(创建角色)。

1.2 — 选择 AWS service(AWS 服务),接下来在 Common use cases(常见使用场景)下方选择 EC2,然后点击 Next: Permission(下一步:权限)。

1.3 — 选择 AdministratorAccess(管理员访问权限),然后点击 Next: Tags(下一步:标签)。

1.4 — 点击 Next: Review(下一步:查看)。

1.5 — 在 Role name(角色名称)文本框中输入 eks-tutorial-admin,然后点击 Create Role(创建角色)。

1.6 — 选择 Cloud9 服务,选择 Cloud9 实例,然后点击 Open IDE(打开 IDE)。点击右上角的灰色圆圈按钮,然后选择 Manage EC2 Instance(管理 EC2 实例)。

1.7 — 为 Cloud9 EC2 实例分配管理角色。依次点击 Actions(操作)和 Security(安全),然后选择 Modify IAM role(修改 IAM 角色)。

1.8 — 为实例分配 eks-tutorial-admin 角色。

1.9 — 点击 Settings(设置)(右上角的齿轮图标),然后选择 AWS Settings(AWS 设置)。关闭 AWS managed temporary credentials(AWS 托管临时凭据),然后点击关闭按钮(设置页面上的“x”)。

1.10 — 在 Cloud9 中的终端窗口内输入以下命令:

rm -vf ${HOME}/.aws/credentials

步骤 2::设置 AWS CLI、kubectl 和 eksctl

如果您已经拥有使用 eksctl 启动的 EKS 集群,请跳到步骤 4,在现有集群中添加 Spot 实例。

2.1 — 通过运行以下命令安装 AWS CLI 版本 2。 

如果您使用的是 Linux,请遵循 AWS CLI 安装指南中有关不同操作系统的说明。

sudo curl --silent --location -o "awscliv2.zip" "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"

sudo unzip awscliv2.zip && sudo ./aws/install

2.2 — 安装 Kubernetes 命令行工具 kubectl。


按照此处 Kubernetes 官方文档中的说明获取最新版本的 kubectl。

sudo curl -o /usr/local/bin/kubectl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

sudo chmod +x /usr/local/bin/kubectl

2.3 — 安装官方 EKS 命令行工具 eksctl,用于部署 EKS 集群和节点组。

使用以下命令下载并解压最新版本的 eksctl。

curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

sudo mv -v /tmp/eksctl /usr/local/bin

2.4 — 使用以下命令进行测试,确认安装成功。 

aws --version
kubectl version
eksctl version

步骤 3:使用按需节点组创建 Amazon EKS 集群

在这个步骤中,您将使用 eksctl 命令行工具创建一个 Amazon EKS 集群。这一操作将会创建一个 EKS 控制面板以及一个节点组,该节点组中包含两个 t3.medium 实例。

3.1 — Eksctl 会自动创建 kube 配置文件,因此在集群部署步骤完成后,您无需进行任何额外配置即可在集群中使用 kubectl。在执行之前使用您的区域参数更新命令:

这个步骤大约需要 15 到 20 分钟。

eksctl create cluster --version=1.20 --name=eksspottutorial --nodes=2 --managed --region=<your-desired-region> --node-type t3.medium --asg-access

3.2 — 完成后,运行以下命令来确认该集群已启动、具有两个实例的按需节点组已部署,且安装的 kubectl 工具可以连接到该集群。

kubectl get nodes

步骤 4:在 EKS 集群中添加 Spot 托管节点组

为了利用多个 Spot 容量池,从而在发生中断时(此时 EC2 需要恢复容量)增加维持容量的机会,您将创建两个节点组,每个节点组包含多种实例类型。每个节点组(EC2 Auto Scaling 组)将使用根据可用 Spot 容量选择的最佳 Spot 池来启动实例。

4.1 — 在 eksctl 上按需使用您的区域参数更新命令后,创建两个 Spot 托管节点组。

此步骤大约需要 3 分钟来创建每个节点组。

请注意在选择实例类型时,每个节点组都包含具有相同 vCPU 数量和内存容量的实例类型,虽然一些实例类型会存在性能差异,但是许多容器化应用程序通常可以接受这种差异。

 

eksctl create nodegroup --cluster=eksspottutorial --region=<AWS Region where you started your EKS cluster> --managed --spot --name=spot-node-group-2vcpu-8gb --instance-types=m5.large,m5d.large,m4.large,m5a.large,m5ad.large,m5n.large,m5dn.large --nodes-min=2 --nodes-max=5 --asg-access

eksctl create nodegroup --cluster=eksspottutorial --region=<AWS Region where you started your EKS cluster> --managed --spot --name=spot-node-group-4vcpu-16gb --instance-types=m5.xlarge,m5d.xlarge,m4.xlarge,m5a.xlarge,m5ad.xlarge,m5n.xlarge,m5dn.xlarge --nodes-min=2 --nodes-max=5 --asg-access

4.2 — 上一个步骤完成后,确认新节点已添加到集群中。

kubectl get nodes --show-labels --selector=eks.amazonaws.com/capacityType=SPOT | grep SPOT

4.3 — 使用 AWS 管理控制台检查您新部署的 Kubernetes 集群。选择 Elastic Kubernetes Service,点击 Clusters(集群),然后点击 eksspottutorial 集群。依次选择 Configuration(配置)页签和 Compute(计算)子页签。

您可以看到在前面的步骤中创建的节点组:一个按需节点组和两个 Spot 节点组。

4.4 — 点击 spot-node-group-2vcpu-8gb 组,您可以看到通过 create 命令设置的实例类型。

4.5 — 在 Details(详细信息)页签中,点击 Auto Scaling 组名称。滚动到 Purchase options and instance types(购买选项和实例类型)设置。请注意如何以开箱即用的方式应用 Spot 最佳实践:Auto Scaling 组采用容量优化型分配策略,该策略将从最深的容量池启动 Spot 实例。此外,该集群还启用了容量再平衡,通过主动替换中断风险较高的实例,帮助 EKS 托管节点组管理 Spot 实例的生命周期。

ASG configuration

4.6 — 恭喜您!现在,您已将 Spot 实例连接到 EKS 集群,接下来就能以相较于按需型实例更加经济实惠的价格运行容器化工作负载了。

步骤 5:(可选)部署 Kubernetes Cluster Autoscaler

当 Pod 因资源不足而无法启动时,或者当集群中的节点未得到充分利用,并且它们的 Pod 可以重新调度到集群中的其他节点时,Kubernetes Cluster Autoscaler 会自动调整集群中的节点数量。

5.1 — 部署最新版本的 Kubernetes Cluster Autoscaler。

首先下载 yaml 文件。

curl -LO https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

5.2 — 为了指示 cluster-autoscaler 使用我们新部署的节点组(EC2 Auto Scaling 组),我们将使用 Cluster Autoscaler 的自动发现模式。Cluster Autoscaler 将通过以下标签来识别我们的 EC2 Auto Scaling 组:
tag=k8s.io/cluster-autoscaler/enabled 和
k8s.io/cluster-autoscaler/eksspottutorial

运行以下命令以将这些标签更新到 Cluster Autoscaler,并将 Cluster Autoscaler 的版本更新到 1.20.0。

sed -i 's/<YOUR CLUSTER NAME>/eksspottutorial/g' cluster-autoscaler-autodiscover.yaml
sed -i 's/v1.17.3/v1.20.0/g' cluster-autoscaler-autodiscover.yaml

5.3 — 部署 Cluster Autoscaler。

kubectl apply -f cluster-autoscaler-autodiscover.yaml

5.4 — 以下是多个节点组的直观表示,每个节点组都包含大小相似的实例类型,并采用 Spot 实例的容量优化型分配策略。此配置的重点在于利用多个备用容量池来提高 Spot 工作节点的弹性,以及让 Kubernetes Cluster Autoscaler 能够做出正确的扩缩决策。

步骤 6:部署示例应用程序

6.1 — 创建新文件 nginx-to-scaleout.yaml,将以下规格粘贴到该文件中,然后保存该文件:

请注意,我们倾向于使用节点亲和性的调度策略在 EKS Spot 托管节点组上部署此应用程序:preferredDuringSchedulingIgnoredDuringExecution

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-to-scaleout
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        service: nginx
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key:  eks.amazonaws.com/capacityType
                operator: In
                values:
                - SPOT
      containers:
      - image: nginx
        name: nginx-to-scaleout
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
          requests:
            cpu: 1000m
            memory: 1024Mi

6.2 — 完成部署文件的部署,并确认该文件已部署并正在运行 Nginx Web 服务器的一个副本。

kubectl apply -f nginx-to-scaleout.yaml
kubectl get deployment/nginx-to-scaleout

6.3 — 扩展该部署(增加副本数量)。

kubectl scale --replicas=20 deployment/nginx-to-scaleout

6.4 — 检查是否有一些 Pod 因现有工作节点上没有可用的 vCPU 或 RAM 而处于待定状态 (Status=Pending)。

kubectl get pods

6.5 — 检查 Cluster Autoscaler 日志,确认其已发现待处理 Pod 并正在通过扩大节点组来进行扩展活动。

[scale_up.go:263] Pod default/nginx-to-scaleout-84f9cdbd84-vn7px is unschedulable

可能采用的扩展方案:
[Final scale-up plan: [{eks-98bcc7e7-0457-f6a3-98dc-292ebc980547 2->5 (max: 5)}]
[Final scale-up plan: [{eks-fcbcc7e4-0c28-df1a-9669-8260c526d237 2->3 (max: 5)}]

kubectl logs -f deployment/cluster-autoscaler -n kube-system | grep -i scale_up

6.6 — 在 AWS 管理控制台上确认 Spot 节点组已启动更多实例。选择 Elastic Kubernetes Service,点击 Clusters(集群),然后点击 eksspottutorial 集群。依次选择 Configuration(配置)页签和 Compute(计算)子页签。

6.7 — 在 AWS 管理控制台上确认一个或多个 EC2 Auto Scaling 组已启动更多 Spot 实例。

6.8 — 确认所有待处理的 Pod 均已调度,这一过程需要 1 到 3 分钟。

kubectl get pods

步骤 7:清除

7.1 — 删除 Nginx Web 服务器部署。

kubectl delete -f nginx-to-scaleout.yaml

7.2 — 移除您在本教程中部署的两个 EKS Spot 托管节点组。

eksctl delete nodegroup --cluster=eksspottutorial --name=spot-node-group-2vcpu-8gb
eksctl delete nodegroup --cluster=eksspottutorial --name=spot-node-group-4vcpu-16gb

7.3 — 如果您在本教程中使用了新创建的 EKS 集群而不是现有集群,请删除此集群。

eksctl 将立即确认是否删除集群的 CloudFormation 堆栈,删除操作最多可能需要 15 分钟。您可以选择在 CloudFormation 控制台上进行跟踪。

eksctl delete cluster --name eksspottutorial

恭喜您

恭喜您!在本教程中,您学习了如何使用 Spot 托管节点组部署 Amazon EKS 集群并在 Spot 实例上运行 Kuberentes 部署和服务,同时遵循 Spot 实例的最佳实践。通过创建包含多种性能相似的实例类型的多个节点组,您可以提高在 Spot 工作节点上运行的应用程序的弹性,同时在不影响性能或可用性的情况下满足应用程序的 SLA。

此页内容对您是否有帮助?

推荐的后续步骤

了解 Spot 托管节点组

了解 Amazon EKS 如何应用 Spot 实例最佳实践,为托管节点组中 EC2 Spot 实例的预配和管理提供支持。

深入探讨如何将 Spot 实例和 Amazon EKS 结合使用

通过实践研讨会深入探讨如何在 Spot 实例上借助 Amazon EKS 预配、管理和维护任何规模的 Kubernetes 集群。

了解 Amazon EC2 Spot 实例

详细了解 Amazon EC2 Spot 实例如何让您以经济实惠的价格利用 AWS 中未使用的 EC2 容量,其价格相较于按需型实例,最高可享受 90% 的折扣。