亚马逊AWS官方博客

Amazon EKS 集群故障转移和集群扩容时间测试报告

1. 测试背景

Amazon Elastic Kubernetes Service(EKS)是一种托管的 Kubernetes 服务,用于在亚马逊云科技上运行 Kubernetes,而无需安装、操作和维护 Kubernetes 控制平面。借助 Amazon EKS,客户可以充分利用亚马逊云科技平台的卓越性能、可扩展性、可靠性和可用性。

客户在使用 Amazon EKS 时,通常需要选择节点配置和扩容方式,本文测试 Amazon EKS 在不同实例机型、有无工作负载情况下集群托管节点组故障转移时间,以及在不同实例机型、有无工作负载、不同扩容方式(Cluster AutoscalerKarpenter)多种情况下集群托管节点组的扩容时间,为客户在亚马逊云科技上选择 Amazon EKS 集群的节点配置和扩容方式提供参考。

2. 测试环境

被测服务 Amazon EKS
测试区域 孟买区域(ap-south-1)
测试版本 Amazon EKS 1.26
测试机型 m5.4xlarge 和 m5.8xlarge
部署模式

托管节点组包含两种配置:

2 个 m5.4xlarge,初始部署 25 个 Pod,扩容到 40 个 Pod

2 个 m5.8xlarge,初始部署 50 个 Pod,扩容到 80 个 Pod

测试应用 nginx:latest 镜像(单个 Pod:1CPU,2GB 内存)
压测机型 c5.12xlarge * 1
压测软件 Apache ab(https://httpd.apache.org/docs/2.4/programs/ab.html

3. 测试前提

本次测试基于以下三个前提:

  • Amazon EKS 使用默认配置
  • 压测机与 Amazon EKS 集群在同一个 VPC
  • ELB 健康检查次数为 3 次,检查间隔为 10 秒

4. 测试架构图

5. 测试用例

5.1 基于以下 2 种模式,分别测试无工作负载和有工作负载两种情况下集群托管节点组故障转移时间

模式
m5.4xlarge 机型共计 2 个节点,终止其中的 1 个节点
m5.8xlarge 机型共计 2 个节点,终止其中的 1 个节点

5.2 基于以下 4 种模式,分别测试无工作负载和有工作负载两种情况下集群托管节点组的扩容时间

模式
集群初始包含 2 个 m5.4xlarge 实例,部署 25 个 Pod,通过 HPA[1]扩容到 40 个 Pod,触发 Cluster Autoscaler 将集群扩容到 3 个 m5.4xlarge 实例
集群初始包含 2 个 m5.4xlarge 实例,部署 25 个 Pod,通过 HPA 扩容到 40 个 Pod,触发 Karpenter 将集群扩容到 3 个 m5.4xlarge 实例
集群初始包含 2 个 m5.8xlarge 实例,部署 50 个 Pod,通过 HPA 扩容到 80 个 Pod,触发 Cluster Autoscaler 将集群扩容到 3 个 m5.8xlarge 实例
集群初始包含 2 个 m5.8xlarge 实例,部署 50 个 Pod,通过 HPA 扩容到 80 个 Pod,触发 Karpenter 将集群扩容到 3 个 m5.8xlarge 实例

[1]Horizontal Pod Autoscaler: https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale/

6. 测试方法

6.1 使用 nginx:latest 镜像部署测试 Pod

  1. 设置环境变量
export EC2_INSTANCE_TYPE="m5"
export EC2_INSTANCE_SIZE="4xlarge"
export CLUSTER_NAME="eks-${EC2_INSTANCE_TYPE}-${EC2_INSTANCE_SIZE}"
  1. 生成部署文件
cat << EOF > deployment-for-${CLUSTER_NAME}
---
apiVersion: v1
kind: Namespace
metadata:
  name: namespace-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: namespace-nginx
  name: deployment-nginx
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-nginx
  replicas: 0
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-nginx
    spec:
      containers:
        - image: nginx:latest
          imagePullPolicy: Always
          name: app-nginx
          ports:
            - containerPort: 80
          resources:
            limits:
              cpu: 1
              memory: 2Gi
            requests:
              cpu: 1
              memory: 2Gi
---
apiVersion: v1
kind: Service
metadata:
  namespace: namespace-nginx
  name: service-nginx
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: app-nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: namespace-nginx
  name: ingress-nginx
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: service-nginx
                port:
                  number: 80
EOF
  1. 部署 Pod
kubectl apply -f deployment-for-${CLUSTER_NAME}

6.2 模拟生产工作负载的方法

  1. 安装 Apache ab
sudo yum -y install httpd-tools
  1. 使用 Apache ab 产生工作负载
ab -c 1000 -n 100000000000 http://<ALB-DNS>/

6.3 集群托管节点组故障转移测试方法

  1. 使用 EC2 控制台,选择 EKS 集群托管节点组中的一个节点,依次点击“实例状态”、 “终止实例”,触发集群托管节点组故障转移

  1. 使用 CloudTrail 查找终止实例所对应的 TerminateInstances 事件,将其“事件时间”作为集群托管节点组故障转移开始时间

  1. 使用 CloudTrail 查找 Pod 注册到 ALB 的 RegisterTargets 事件,记录其“事件时间”

  1. 本测试中健康检查采用“间隔 10 秒、3 次成功”规则确定 Pod 健康,因此需要额外的 30~40 秒,本测试取 35 秒的平均值。最终集群托管节点组故障转移结束时间为“RegisterTargets 事件时间 + 35 秒”

6.4 集群托管节点组无工作负载扩容测试方法

  1. 使用以下命令调整 Pod 副本数到 50,同时显示当前时间作为集群托管节点组扩容开始时间
kubectl scale deployment deployment-nginx --replicas 50 -n namespace-nginx && date
  1. 使用 CloudTrail 查找 Pod 注册到 ALB 的 RegisterTargets 事件,记录其“事件时间”

  1. 本测试中健康检查采用“ 间隔 10 秒、3 次成功”规则确定 Pod 健康,因此需要额外的 30~40 秒,本测试取 35 秒的平均值。最终集群托管节点组的扩容结束时间为“RegisterTargets 事件时间 + 35 秒”

6.5 集群托管节点组有工作负载扩容测试方法

  1. 使用 Apache ab 发起请求,设置 HPA 规则“当 CPU 达到 50%时”进行扩容
  1. 查找 Cluster Autoscaler 日志或者 Karpenter 日志中 Pod 无法被调度的时间,作为集群托管节点组的扩容开始时间
  1. 使用 CloudTrail 查找 Pod 注册到 ALB 的 RegisterTargets 事件,记录其“事件时间”

  1. 本测试中健康检查采用“间隔 10 秒、3 次成功”规则确定 Pod 健康,因此需要额外的 30~40 秒,本测试取 35 秒的平均值。最终集群托管节点组的扩容结束时间为“RegisterTargets 事件时间 + 35 秒”

7. 测试数据

7.1 集群托管节点组故障转移测试数据

模式 无工作负载故障转移时间 有工作负载故障转移时间
m5.4xlarge 机型共计 2 个节点,终止其中的 1 个节点 00:02:31 00:02:21
m5.8xlarge 机型共计 2 个节点,终止其中的 1 个节点 00:02:10 00:02:28

表格中记录的时间均为 3 次测试的平均时间。Amazon EKS 集群托管节点组使用 Amazon EC2 Auto Scaling 管理节点,上表中任意两组时间差均小于 30 秒,小于 Amazon EC2 Auto Scaling 检测变更的时间周期,因此上表数据不能体现集群托管节点组故障转移时间与实例机型和工作负载有关。

7.2 集群托管节点组扩容测试数据

模式 无工作负载扩容,使用 Cluster Autoscaler 无工作负载扩容,使用 Karpenter 有工作负载扩容,使用 Cluster Autoscaler 有工作负载扩容,使用 Karpenter
集群初始包含 2 个 m5.4xlarge 实例,部署 25 个 Pod,通过 HPA 扩容到 40 个 Pod 00:01:42 00:01:16 00:01:38 00:01:14
集群初始包含 2 个 m5.8xlarge 实例,部署 50 个 Pod,通过 HPA 扩容到 80 个 Pod 00:01:47 00:01:16 00:01:41 00:01:12

本测试中健康检查采用“间隔 10 秒、3 次成功”规则确定 Pod 健康,因此需要额外的 30~40 秒,本测试取 35 秒的平均值。最终集群扩容结束时间为“RegisterTargets 时间 + 35 秒”。

8. 测试结论

  1. Amazon EKS 集群托管节点组故障转移时间的平均值分布在 2 分 10 秒-2 分 31 秒之间,任意两组时间差均小于 30 秒,小于 Amazon EC2 Auto Scaling 检测变更的时间周期,因此,Amazon EKS 集群托管节点组故障转移时间与实例机型和工作负载相关性较小。
  2. Amazon EKS 集群托管节点组使用 4xlarge 机型,在无工作负载扩容时,Karpenter 的扩容时间为 1 分 16 秒,比 Cluster Autoscaler 的扩容时间少 26 秒,在有工作负载扩容时,Karpenter 的扩容时间为 1 分 14 秒,比 Cluster Autoscaler 的扩容时间少 24 秒。Amazon EKS 集群托管节点组使用 m5.8xlarge 机型,Karpenter 的扩容时间为 1 分 16 秒,比 Cluster Autoscaler 的扩容时间少 31 秒,在有工作负载扩容时,Karpenter 的扩容时间为 1 分 12 秒,比 Cluster Autoscaler 的扩容时间少 29 秒。因此,Amazon EKS 集群托管节点组扩容时间与实例机型和工作负载相关性较小,与扩容方式相关性较大。综合来看,Karpenter 的扩容时间比 Cluster Autoscaler 少 24%-29%,推荐使用 Karpenter 作为 Amazon EKS 的扩容组件。
  3. Cluster Autoscaler 通过 EC2 Auto Scaling Groups 间接创建 EC2 实例[1][2],EC2 Auto Scaling Groups 检测变更的时间周期为 30 秒,扩容时,Cluster Autoscaler 首先调整 EC2 Auto Scaling Groups 配置,然后等待 EC2 Auto Scaling Groups 检测到配置变更后创建 EC2 实例,这个过程花费额外等待时间。Karpenter 通过 EC2 Fleet API 直接创建 EC2 实例[3][4],无需使用 EC2 Auto Scaling Groups,当需要扩容时,Karpenter 立即启动 EC2,无需等待额外的检测变更时间周期,所以 Karpenter 在扩容时比 Cluster Autoscaler 时间短。因此,推荐使用 Karpenter 作为 Amazon EKS 的扩容组件。

[1]Cluster Autoscaler on AWS: https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler/cloudprovider/aws

[2]Autoscaling: https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/autoscaling.html

[3]Learn about Karpenter Provisioners: https://karpenter.sh/v0.29/concepts/provisioners

[4]How does Karpenter dynamically select instance types: https://karpenter.sh/docs/faq/#how-does-karpenter-dynamically-select-instance-types

本篇作者

何超

亚马逊云科技解决方案架构师,现负责集团战略客户,拥有超过 18 年的研发经验,对企业级应用架构和互联网应用架构有丰富的实战经验。

郭立

郭立于 2019 年加入亚马逊云科技,担任资深解决方案架构师和解决方案架构师经理,负责带领架构师团队支持战略客户和企业客户,同时为亚马逊云科技机器学习、数据分析与安全合规技术专家。