+++ title = " Scaling with Karpenter”

hidden=true

weight = 47 pre = “47.

+++

标题: 使用 Karpenter 进行扩展 权重: 65

:::alert[如果您直接来到这一部分,请确保您已完成上述描述的先决条件 ]

简介

Karpenter 是一个动态的、高性能的、开源的 Kubernetes 集群自动扩展解决方案。Karpenter 的工作原理如下:

  • 监视标记为无法调度的 pod
  • 评估 pod 请求的调度约束(资源请求、节点选择器、亲和性、容忍度和拓扑传播约束)
  • 配置满足 pod 需求的节点
  • 在不需要这些节点时删除它们

Karpenter 的任务是添加节点来处理无法调度的 pod、在这些节点上调度 pod,以及在不需要这些节点时删除它们。要配置 Karpenter,您需要创建供应商,它们定义 Karpenter 如何管理无法调度的 pod 和过期节点。下图说明了它的工作原理:

概述

本工作坊会话将向您展示如何在为您在本工作坊中配置的 EKS 集群中设置 Karpenter。我们将使用 TPC-DS 数据,依次运行 3 个 Spark SQL 查询,每个查询使用 50 个执行器处理 177 亿条记录。我们将使用来自 emr-on-eks-benchmark 存储库的基准测试。

我们将使用 pod 模板 在按需实例上调度 Spark 驱动程序,在 EC2 Spot 实例上调度执行器。

为您的 EKS 集群配置 Karpenter 的步骤

  1. 在您的 Cloud9 工作站中,请确保您已运行了本部分 中描述的引导程序。安装的工具包括:

还有另一个工具需要安装,但在上面提供的引导程序中没有包括:

请按照以下说明安装 Helm:

curl -L https://git.io/get_helm.sh | bash -s -- --version v3.8.2
  1. 下载将在本节中使用的脚本:

:button[下载 zip 文件]{href=”/static/zip/karpenter_files.zip” action="download”}

  1. 解压缩 karpenter_files.zip 并将以下文件上传到提供的 S3 存储桶的以下前缀:
export ACCOUNTID="${ACCOUNTID:-$(aws sts get-caller-identity --query Account --output text)}"
export AWS_REGION="${AWS_REGION:-$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.region')}"

## 从 CloudFormation 输出选项卡获取 S3 存储桶名称
## 示例: emr-eks-workshop-123456789012
export S3BUCKET="emr-eks-workshop-123456789012"

unzip karpenter_files.zip
aws s3 cp karpenter-driver-pod-template.yaml s3://${S3BUCKET}/pod-template/
aws s3 cp karpenter-executor-pod-template.yaml s3://${S3BUCKET}/pod-template/
  1. 确保您可以使用 kubectl 并访问 EKS 集群。
# 使用以下命令进行测试,您应该会看到节点列表

kubectl get nodes
NAME                           STATUS   ROLES    AGE     VERSION
ip-10-0-113-17.ec2.internal    Ready    <none>   4m20s   v1.22.17-eks-0a21954
ip-10-0-113-86.ec2.internal    Ready    <none>   2d1h    v1.22.17-eks-0a21954
ip-10-0-128-138.ec2.internal   Ready    <none>   2d1h    v1.22.17-eks-0a21954
ip-10-0-155-242.ec2.internal   Ready    <none>   7m49s   v1.22.17-eks-0a21954

如果您没有看到上述节点列表,请通过以下方式更新您的 kubeconfig:

export EKSCLUSTER_NAME="${EKSCLUSTER_NAME:-emr-eks-workshop}"

aws eks update-kubeconfig --region ${AWS_REGION} --name ${EKSCLUSTER_NAME}
  1. 运行 karpenter-setup.sh 脚本,它将安装所有必要的 Karpenter 组件。输入为您在本工作坊中创建的 S3 存储桶名称。如果方括号中显示的存储桶名称正确,只需按 Enter 继续。
./karpenter-setup.sh 
Please enter the bucket name [emr-eks-workshop-XXXXXXXXXXXX]: 
  1. 验证设置:
# 验证 Karpenter pod 已安装在 karpenter 命名空间中

kubectl get pods -n karpenter

NAME                        READY   STATUS    RESTARTS   AGE
karpenter-9746cb6b8-dc5lp   2/2     Running   0          22h
karpenter-9746cb6b8-dlnt4   2/2     Running   0          14h

查看为 Karpenter 部署的供应商:

# 获取安装的供应商列表

kubectl get provisioners

NAME      AGE
default   3d21h


# 描述默认供应商 

kubectl describe provisioners default

Name:         default
Namespace:    
Labels:       <none>
Annotations:  <none>
API Version:  karpenter.sh/v1alpha5
Kind:         Provisioner
Metadata:
  Creation Timestamp:  2023-07-20T22:39:54Z
  Generation:          1
  Managed Fields:
    API Version:  karpenter.sh/v1alpha5
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
      f:spec:
        .:
        f:labels:
          .:
          f:app:
        f:limits:
          .:
          f:resources:
            .:
            f:cpu:
        f:provider:
          .:
          f:launchTemplate:
          f:subnetSelector:
        f:requirements:
        f:ttlSecondsAfterEmpty:
    Manager:         kubectl-client-side-apply
    Operation:       Update
    Time:            2023-07-20T22:39:54Z
  Resource Version:  748457
  UID:               d1381ee0-f5bb-45c0-ac1b-5de837c04560
Spec:
  Labels:
    App:  kspark
  Limits:
    Resources:
      Cpu:  2k
  Provider:
    Launch Template:  emr-eks-workshop-karpenter-launchtemplate
    Subnet Selector:
      karpenter.sh/discovery:  emr-eks-workshop
  Requirements:
    Key:       karpenter.sh/capacity-type
    Operator:  In
    Values:
      on-demand
      spot
    Key:       kubernetes.io/arch
    Operator:  In
    Values:
      amd64
    Key:       karpenter.k8s.aws/instance-family
    Operator:  In
    Values:
      c5
      c5a
      c5d
      c5ad
      m5
      c6a
    Key:       karpenter.k8s.aws/instance-size
    Operator:  In
    Values:
      2xlarge
      4xlarge
      8xlarge
      9xlarge
    Key:       topology.kubernetes.io/zone
    Operator:  In
    Values:
      us-east-1a
  Ttl Seconds After Empty:  30
Status:
Events:  <none>

从上面的供应商描述中,Karpenter 将部署具有以下特征的 EC2 节点:

  • EC2 节点标签: App = kspark
  • Karpenter 将部署 EC2 节点的 VPC 子网标签: karpenter.sh/discovery = emr-eks-workshop
  • 部署 ON_DEMAND 和 SPOT 实例
  • 创建并使用 EC2 启动模板: emr-eks-workshop-karpenter-launchtemplate
  1. 使用 emr6.5-tpcds-karpenter.sh 脚本提交一个 Spark 作业:
# 此脚本将运行 EMR 基准脚本,每个执行器使用 4 个 vCPU 和 7 GB RAM

./emr6.5-tpcds-karpenter.sh 4 7

上面的脚本使用 pod 模板来自定义 Spark pod 被调度到哪些 EC2 节点。作业提交中指示 pod 模板的配置在这里描述:

  "spark.kubernetes.node.selector.app": "kspark",
  "spark.kubernetes.driver.podTemplateFile": "s3://'$S3BUCKET'/pod-template/karpenter-driver-pod-template.yaml",
  "spark.kubernetes.executor.podTemplateFile": "s3://'$S3BUCKET'/pod-template/karpenter-executor-pod-template.yaml",

该作业将在标签为 app = kspark 的 EC2 节点上运行,Spark 驱动程序和 Spark 执行器将根据各自的 pod 模板被调度到 EC2 节点上。

Spark 驱动程序 pod 模板如下:

# // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# // SPDX-License-Identifier: MIT-0
apiVersion: v1
kind: Pod
spec:
  nodeSelector:
    karpenter.sh/capacity-type: on-demand
  containers:
  - name: spark-kubernetes-driver
    volumeMounts:
      - name: spark-local-dir-1
        mountPath: /data1
  initContainers:  
  - name: volume-permission
    image: public.ecr.aws/y4g4v0z7/busybox
    command: ['sh', '-c', 'mkdir /data1; chown -R 999:1000 /data*'] # grant volume access to hadoop user  
    volumeMounts:
      - name: spark-local-dir-1
        mountPath: /data1
  volumes:
    - name: spark-local-dir-1
      hostPath:
        path: /local1 

Spark 执行器 pod 模板如下:

# // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# // SPDX-License-Identifier: MIT-0
apiVersion: v1
kind: Pod
spec:
  nodeSelector:
    karpenter.sh/capacity-type: spot
  containers:
  - name: spark-kubernetes-executor
    volumeMounts:
      - name: spark-local-dir-1
        mountPath: /data1
  initContainers:  
  - name: volume-permission
    image: public.ecr.aws/y4g4v0z7/busybox
    command: ['sh', '-c', 'mkdir /data1; chown -R 999:1000 /data*'] # grant volume access to hadoop user  
    volumeMounts:
      - name: spark-local-dir-1
        mountPath: /data1
  volumes:
    - name: spark-local-dir-1
      hostPath:
        path: /local1 

两个 pod 模板是相似的,除了 nodeSelector 设置。Spark 驱动程序在 ON_DEMAND EC2 节点上运行,而 Spark 执行器在 SPOT EC2 节点上运行。

  1. 通过运行以下命令观察和监控进度:
  • 在一个终端中,观察调度的 pod
# 此命令将显示生成的 pod。第一个 pod 将是 job-runner,第二个将是 Spark 驱动程序 pod,然后大约 50 个执行器 pod 将被调度

watch -n1 "kubectl get pod -n emr-karpenter"

Every 1.0s: kubectl get po -n emr-karpenter                                                                                                             Fri Jul 21 23:40:11 2023
NAME                               READY   STATUS            RESTARTS   AGE                                                                                             
000000032bqpqgfmbe4-7zb87          3/3     Running           0          5m2s 
karpenter-4vcpu-7gb-exec-1         2/2     Running           0          104s
karpenter-4vcpu-7gb-exec-10        2/2     Running           0          102s
karpenter-4vcpu-7gb-exec-11        2/2     Running           0          101s
karpenter-4vcpu-7gb-exec-12        2/2     Running           0          101s
karpenter-4vcpu-7gb-exec-13        2/2     Running           0          101s
karpenter-4vcpu-7gb-exec-14        2/2     Running           0          101s
karpenter-4vcpu-7gb-exec-15        2/2     Running           0          101s
karpenter-4vcpu-7gb-exec-16        2/2     Running           0          100s
karpenter-4vcpu-7gb-exec-17        2/2     Running           0          100s
karpenter-4vcpu-7gb-exec-18        2/2     Running           0          99s
karpenter-4vcpu-7gb-exec-19        2/2     Running           0          99s
karpenter-4vcpu-7gb-exec-2         2/2     Running           0          104s
  • 在另一个终端