Рабочие узлы в режиме реального времени с помощью Karpenter

Одним из главных преимуществ Kubernetes является возможность динамического масштабирования инфраструктуры в зависимости от потребностей. Она предоставляет несколько уровней функциональности автомасштабирования: горизонтальный pod autoscaler (HPA) и вертикальный pod autoscaler (VPA) в качестве pod и кластерный autoscaler в качестве узла.

Однако настройка автомасштабирования кластера с помощью существующих решений Kubernetes может быть сложной и ограничивающей. Например, в кластере AWS EKS нельзя управлять узлами напрямую. Вместо этого нам необходимо использовать дополнительные механизмы оркестровки, такие как node groups. Предположим, мы определили t3.large как тип экземпляра nodegroup. Когда необходимо предоставить новый узел для кластера, Kubernetes Cluster Autoscaler создает новый экземпляр типа t3.large, независимо от требований к ресурсам. Хотя мы можем использовать смешанные экземпляры в группах узлов, это не всегда позволяет удовлетворить потребности в ресурсах и быть экономически эффективным.

Автомасштабирование Kubernetes

K8S Autoscaling помогает нам масштабироваться горизонтально или в наших приложениях. Масштабирование на основе Pod или HPA — это отличный первый шаг. Однако проблема возникает, когда нам нужно несколько узлов K8S для размещения наших POD.

Karpenter

Karpenter — это решение для масштабирования на основе узлов, созданное для K8S и направленное на повышение эффективности и затрат. Это отличное решение, поскольку нам не нужно настраивать типы экземпляров или создавать пулы узлов, что значительно упрощает настройку. С другой стороны, интеграция с инстансами Spot проходит безболезненно и позволяет нам снизить затраты (до 90% меньше, чем у инстансов On-Demand).

Karpenter — это проект развертывания узлов с открытым исходным кодом, разработанный для Kubernetes. Добавление Karpenter в кластер Kubernetes может значительно повысить эффективность и стоимость выполнения рабочих нагрузок на этом кластере.

Особенности Karpenter

  • Остерегайтесь стручков, которые планировщик Kubernetes пометил как не подлежащие планированию.
  • Оценивать ограничения планирования (требования к ресурсам, селекторы узлов, сродства, допуски и ограничения на распределение топологии).
  • Востребованные узлы развертывания стручков, которые отвечают потребностям стручков.
  • Запланировать запуск стручков на новых узлах.
  • Удаление узлов, когда узлы больше не нужны.

Контуры управления Karpenter

Karpenter имеет два контура управления, которые максимизируют доступность и эффективность вашего кластера.

Распределитель

Быстродействующий контроллер, который обеспечивает максимально быстрое планирование стручков.

Перераспределитель

Медленно действующий контроллер заменяет узлы по мере изменения емкости стручков.

Cluster Autoscaler

Cluster Autoscaler — это утилита Kubernetes, которая увеличивает или уменьшает размер кластера Kubernetes (путем добавления или удаления узлов), основываясь на наличии ожидающих капсул и метриках использования узлов.

Автоматическое изменение размера кластера Kubernetes при выполнении одного из следующих условий:

  1. Есть стручки, которые не могут работать на кластере из-за недостатка ресурсов.
  2. В кластере есть узлы, которые не используются в течение длительного периода времени, и их стручки могут быть размещены на других существующих узлах.

Решение для автомасштабирования узлов Kubernetes — это инструмент, который автоматически масштабирует кластер Kubernetes в зависимости от потребностей наших рабочих нагрузок. Поэтому нет необходимости вручную создавать (или удалять) новый узел Kubernetes каждый раз, когда он нам нужен.

Karpenter автоматически предоставляет новые узлы в ответ на непрограммируемые капсулы. Для этого он наблюдает за событиями в кластере Kubernetes, а затем отправляет команды базовому облачному провайдеру. Он предназначен для работы с любым кластером Kubernetes в любой среде.

Архитектура кластерного автоскалера

  • Кластерный автоскалер ищет стручки, которые не могут быть запланированы, и узлы, которые недостаточно используются.
  • Затем он имитирует добавление или удаление узлов, прежде чем применить изменения к кластеру.
  • Реализация облачного провайдера AWS в Cluster Autoscaler контролирует поле .DesiredReplicas ваших групп автомасштабирования EC2.
  • Автоскалер кластера Kubernetes автоматически регулирует количество узлов в вашем кластере, когда стручки выходят из строя или переносятся на другие узлы.
  • Автоскалер кластера обычно устанавливается в качестве развертывания на вашем кластере.

Архитектура Karpenter

Karpenter работает с планировщиком Kubernetes, наблюдая за входящими стручками на протяжении всего времени существования кластера. Он запускает или останавливает узлы для оптимизации доступности приложений и использования кластера. Когда в кластере достаточно мощности, планировщик Kubernetes размещает входящие стручки как обычно.

Когда запускаются стручки, которые не могут быть запланированы с использованием существующих мощностей кластера, Karpenter обходит планировщик Kubernetes и работает напрямую с вычислительной службой вашего провайдера, чтобы запустить минимально необходимые вычислительные ресурсы в этих стручках и связать стручки с узлами инициализации.

Когда стручки удаляются, Karpenter ищет возможности для завершения работы недоиспользуемых узлов.

Karpenter утверждает, что предлагает следующие усовершенствования:

Разработан для работы с полной гибкостью облака

Karpenter имеет возможность эффективно работать с полным спектром типов экземпляров, доступных через AWS. Cluster Autoscaler изначально не был создан с гибкостью для управления сотнями типов экземпляров, зон и вариантов покупки.

Предоставление узлов без групп

Karpenter управляет каждым экземпляром напрямую, без использования дополнительных механизмов оркестровки, таких как группы узлов. Это позволяет выполнять повторные попытки за миллисекунды, а не за минуты, когда мощности недоступны. Это также позволяет Karpenter использовать преимущества различных типов экземпляров, зон доступности и вариантов приобретения без создания сотен групп узлов.

Применение планирования

Cluster Autoscaler не связывает стручки с узлами, которые он создает. Вместо этого он полагается на планировщик kube, чтобы принять решение о планировании после того, как узел будет запущен. Куплету не нужно ждать, пока планировщик или узел подготовятся. Он может немедленно начать подготовку среды выполнения контейнера, включая предварительную выборку образа. Это может сократить задержку при запуске узла на несколько секунд.

В этом руководстве вы узнаете, как:

  1. Создать кластер EKS для Karpenter.
  2. Настроить роли AWS.
  3. Установить Karpenter.
  4. Настроить Karpenter Provisioner.
  5. Тест автоматического изменения размера узла Karpenter

Требования

  1. AWS CLI
  2. eksctl
  3. kubectl
  4. helm

Создание кластера EKS для Karpenter

Прежде чем мы продолжим, нам необходимо настроить некоторые переменные окружения

export CLUSTER_NAME=YOUR-CLUSTER-NAME
export AWS_ACCOUNT_ID=YOUR-ACCOUNT-ID

Вход в полноэкранный режим Выйти из полноэкранного режима

Создание кластера с помощью eksctl — самый простой способ сделать это на AWS. Сначала нам нужно создать yaml-файл. Например, test-demo.yaml

cat <<EOF > test-demo.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: ${CLUSTER_NAME}
  region: us-east-1
  version: "1.21"
  tags:
    karpenter.sh/discovery: ${CLUSTER_NAME}

managedNodeGroups:
  - instanceType: t3.medium
    amiFamily: AmazonLinux2
    name: ${CLUSTER_NAME}-ng
    desiredCapacity: 1
    minSize: 1
    maxSize: 3
iam:
  withOIDC: true
EOF

Войти в полноэкранный режим Выйти из полноэкранного режима

Создайте кластер, используя созданный файл

eksctl create cluster -f test-demo.yaml

Войти в полноэкранный режим Выйти из полноэкранного режима

Настройка ролей AWS

Для использования Karpenter на AWS нам необходимо настроить 3 права доступа:

IAM-роль KarpenterNode

Профиль экземпляра с разрешениями на запуск контейнеров и настройку сетей.

Создание IAM-роли KarpenterNode

  • Необходимо создать IAM-ресурсы с помощью AWS CloudFormation. Нам нужно загрузить стек облачной формации с сайта karpenter и развернуть его с информацией об имени нашего кластера.
curl -fsSL https://karpenter.sh/v0.5.5/getting-started/cloudformation.yaml > cloudformation.tmp


[ec2-user@ip-*-*-*-* ~]$ aws cloudformation deploy --stack-name ${CLUSTER_NAME} --template-file cloudformation.tmp --capabilities CAPABILITY_NAMED_IAM --parameter-overrides ClusterName=${CLUSTER_NAME}

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - makendran

Вход в полноэкранный режим Выход из полноэкранного режима

  • Необходимо предоставить доступ к экземплярам с помощью профиля для подключения к кластеру. Эта команда добавляет роль узла Karpenter в каталог конфигурации aws-auth, чтобы узлы с этой ролью могли подключаться к кластеру.
[ec2-user@ip-*-*-*-* ~]$ eksctl create iamidentitymapping --username system:node:{{EC2PrivateDNSName}} --cluster ${CLUSTER_NAME} --arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME} --group system:bootstrappers --group system:nodes
2022-08-10 07:57:55 [] adding identity "arn:aws:iam::262211057611:role/KarpenterNodeRole-makendran" to auth ConfigMap

Войти в полноэкранный режим Выход из полноэкранного режима

Теперь Karpenter может запускать новые экземпляры EC2, и эти экземпляры могут подключаться к вашему кластеру.

IAM-роль KarpenterController

Авторизация для запуска экземпляров

Создание IAM-роли KarpenterController

Создайте роль AWS IAM и учетную запись службы Kubernetes и свяжите их с помощью ролей IAM для учетных записей службы.

[ec2-user@ip-*-*-*-* ~]$ eksctl create iamserviceaccount --cluster $CLUSTER_NAME --name karpenter --namespace karpenter --attach-policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/KarpenterControllerPolicy-$CLUSTER_NAME --approve
2022-08-10 07:59:39 [] 1 existing iamserviceaccount(s) (kube-system/aws-node) will be excluded
2022-08-10 07:59:39 [] 1 iamserviceaccount (karpenter/karpenter) was included (based on the include/exclude rules)
2022-08-10 07:59:39 [!] serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
2022-08-10 07:59:39 [] 1 task: { 
    2 sequential sub-tasks: { 
        create IAM role for serviceaccount "karpenter/karpenter",
        create serviceaccount "karpenter/karpenter",
    } }2022-08-10 07:59:39 [] building iamserviceaccount stack "eksctl-makendran-addon-iamserviceaccount-karpenter-karpenter"
2022-08-10 07:59:39 [] deploying stack "eksctl-makendran-addon-iamserviceaccount-karpenter-karpenter"
2022-08-10 07:59:39 [] waiting for CloudFormation stack "eksctl-makendran-addon-iamserviceaccount-karpenter-karpenter"
2022-08-10 08:00:09 [] waiting for CloudFormation stack "eksctl-makendran-addon-iamserviceaccount-karpenter-karpenter"
2022-08-10 08:00:09 [] created namespace "karpenter"
2022-08-10 08:00:09 [] created serviceaccount "karpenter/karpenter"

Вход в полноэкранный режим Выход из полноэкранного режима

Роль, связанная с сервисом EC2 Spot

Чтобы запустить EC2 Spot в нашей учетной записи. Экземпляр EC2 Spot — это неиспользуемый экземпляр EC2, доступный по запросу за меньшую цену.

Создайте роль, связанную с сервисом EC2 Spot.

Этот шаг требуется только в том случае, если вы впервые используете EC2 Spot в этой учетной записи.

[ec2-user@ip-*-*-*-* ~]$ aws iam create-service-linked-role --aws-service-name spot.amazonaws.com
{
    "Role": {
        "Path": "/aws-service-role/spot.amazonaws.com/",
        "RoleName": "AWSServiceRoleForEC2Spot",
        "RoleId": "AROAT2DH7G7F6JRN6LIPO",
        "Arn": "arn:aws:iam::262211057611:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot",
        "CreateDate": "2022-08-10T08:00:58+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": [
                        "sts:AssumeRole"
                    ],
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [
                            "spot.amazonaws.com"
                        ]
                    }
                }
            ]
        }
    }
}

Вход в полноэкранный режим Выход из полноэкранного режима

Установите Karpenter

Мы можем использовать Helm для установки Karpenter.

helm repo add karpenter https://charts.karpenter.sh
helm repo update
helm upgrade --install karpenter karpenter/karpenter --namespace karpenter --create-namespace --set serviceAccount.create=false --version v0.5.5 --set controller.clusterName=${CLUSTER_NAME} --set controller.clusterEndpoint=$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output json) --wait # for the defaulting webhook to install before creating a Provisioner

Войти в полноэкранный режим Выйти из полноэкранного режима

Проверьте ресурсы Karpenter на K8S.

[ec2-user@ip-*-*-*-* ~]$ kubectl get all -n karpenter
NAME READY STATUS RESTARTS AGE
pod/karpenter-controller-6474d8f77b-sntgb 1/1 Running 0 2m24s
pod/karpenter-webhook-7797fd8b6d-7tcd6 1/1 Running 0 2m24s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/karpenter-metrics ClusterIP 10.100.122.232 <none> 8080/TCP 8m37s
service/karpenter-webhook ClusterIP 10.100.197.109 <none> 443/TCP 8m37s

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/karpenter-controller 1/1 1 1 8m37s
deployment.apps/karpenter-webhook 1/1 1 1 8m37s

NAME DESIRED CURRENT READY AGE
replicaset.apps/karpenter-controller-54d76d6f98 0 0 0 8m37s
replicaset.apps/karpenter-controller-6474d8f77b 1 1 1 2m24s
replicaset.apps/karpenter-webhook-7797fd8b6d 1 1 1 2m24s
replicaset.apps/karpenter-webhook-95d6dd84 0 0 0 8m37s

Войти в полноэкранный режим Выход из полноэкранного режима

Настройка провайдера Karpenter

Фреймворк Karpenter предназначен для управления различными решениями о предоставлении ресурсов на основе атрибутов стручков, таких как метки и сродства.

cat <<EOF > provisioner.yaml
---
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot"]
  limits:
    resources:
      cpu: 1000
  provider:
    subnetSelector:
      karpenter.sh/discovery: ${CLUSTER_NAME}
    securityGroupSelector:
      karpenter.sh/discovery: ${CLUSTER_NAME}
    instanceProfile: KarpenterNodeInstanceProfile-${CLUSTER_NAME}
  ttlSecondsAfterEmpty: 30
EOF


kubectl apply -f provisioner.yaml

Войти в полноэкранный режим Выход из полноэкранного режима

Karpenter готов начать инициализацию узлов.

Тест автомасштабирования узлов Karpenter

Эта реализация использует образ паузы и начинается с нулевых реплик.

cat <<EOF > deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate
spec:
  replicas: 0
  selector:
    matchLabels:
      app: inflate
  template:
    metadata:
      labels:
        app: inflate
    spec:
      terminationGracePeriodSeconds: 0
      containers:
        - name: inflate
          image: public.ecr.aws/eks-distro/kubernetes/pause:3.2
          resources:
            requests:
              cpu: 1
EOF


kubectl apply -f deployment.yaml

Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем масштабировать распределение до 4 реплик

kubectl scale deployment inflate --replicas 4

Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем проверить журналы Karpenter.

kubectl logs -f -n karpenter $(k get pods -n karpenter -l karpenter=controller -o name)
2022-08-10T08:32:46.737Z INFO controller.provisioning Launched instance: i-0d1406393eaee0b4c, hostname: ip-192-168-121-175.ec2.internal, type: t3.2xlarge, zone: us-east-1c, capacityType: spot {"commit": "723b1b7", "provisioner": "default"}
2022-08-10T08:32:46.780Z INFO controller.provisioning Bound 4 pod(s) to node ip-192-168-121-175.ec2.internal {"commit": "723b1b7", "provisioner": "default"}
2022-08-10T08:32:46.780Z INFO controller.provisioning Waiting for unschedulable pods {"commit": "723b1b7", "provisioner": "default"}

Войти в полноэкранный режим Выйти из полноэкранного режима

Karpenter создал новый экземпляр.

  • Экземпляр: i-0d1406393eaee0b4c
  • Имя хоста: ip-192-168-121-175.ec2.internal
  • Тип: t3.2xlarge
  • Зона: us-east-1c

Мы можем проверить узлы,

[ec2-user@ip-*-*-*-* ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-121-175.ec2.internal Ready <none> 8m34s v1.21.12-eks-5308cf7
ip-192-168-39-32.ec2.internal Ready <none> 52m v1.21.12-eks-5308cf7

Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь у нас есть новый рабочий узел. Этот узел является экземпляром EC2 Spot. Мы можем проверить цену SpotPrice.

[ec2-user@ip-*-*-*-* ~]$ aws ec2 describe-spot-instance-requests | grep "InstanceType|InstanceId|SpotPrice"
            "InstanceId": "i-0d1406393eaee0b4c",
                "InstanceType": "t3.2xlarge",
            "SpotPrice": "0.332800",

Войти в полноэкранный режим Выход из полноэкранного режима

Наконец, мы можем изменить размер распределения на 0, чтобы проверить, был ли узел удален

kubectl scale deployment inflate --replicas 0

Войти в полноэкранный режим Выход из полноэкранного режима

Karpenter оцепил узел, а затем удалил его.

kubectl logs -f -n karpenter $(kubectl get pods -n karpenter -l karpenter=controller -o name)
2022-08-10T08:32:46.780Z INFO controller.provisioning Waiting for unschedulable pods {"commit": "723b1b7", "provisioner": "default"}
2022-08-10T08:47:14.742Z INFO controller.node Added TTL to empty node {"commit": "723b1b7", "node": "ip-192-168-121-175.ec2.internal"}
2022-08-10T08:47:44.763Z INFO controller.node Triggering termination after 30s for empty node {"commit": "723b1b7", "node": "ip-192-168-121-175.ec2.internal"}
2022-08-10T08:47:44.790Z INFO controller.termination Cordoned node {"commit": "723b1b7", "node": "ip-192-168-121-175.ec2.internal"}
2022-08-10T08:47:45.038Z INFO controller.termination Deleted node {"commit": "723b1b7", "node": "ip-192-168-121-175.ec2.internal"}

Войти в полноэкранный режим Выход из полноэкранного режима

Проверьте узлы еще раз. Второй узел был удален

[ec2-user@ip-*-*-*-* ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-39-32.ec2.internal Ready <none> 60m v1.21.12-eks-5308cf7

Войдите в полноэкранный режим Выйти из полноэкранного режима

Очистка

Чтобы избежать дополнительных расходов, удалите демонстрационную инфраструктуру из учетной записи AWS.

helm uninstall karpenter --namespace karpenter
eksctl delete iamserviceaccount --cluster ${CLUSTER_NAME} --name karpenter --namespace karpenter
aws cloudformation delete-stack --stack-name Karpenter-${CLUSTER_NAME}
aws ec2 describe-launch-templates 
    | jq -r ".LaunchTemplates[].LaunchTemplateName" 
    | grep -i Karpenter-${CLUSTER_NAME} 
    | xargs -I{} aws ec2 delete-launch-template --launch-template-name {}
eksctl delete cluster --name ${CLUSTER_NAME}

Вход в полноэкранный режим Выход из полноэкранного режима

Заключение

Karpenter — отличный инструмент для настройки автомасштабирования узлов Kubernetes, он довольно новый. Однако он имеет интеграцию со Spot, Fargate (бессерверные) инстансы и другие замечательные возможности. Самое приятное то, что вам не нужно настраивать пулы узлов или выбирать размер инстансов, это также очень быстро, на развертывание стручков на новом узле уходит около 1 минуты.

Благодарю за то, что дочитали мою статью до конца. Надеюсь, сегодня вы поняли что-то уникальное. Если вам понравилась эта статья, пожалуйста, поделитесь с друзьями, а если у вас есть предложения или мысли, которыми вы хотите поделиться со мной, пожалуйста, напишите в поле для комментариев.

Следуйте за мной и делитесь своими мыслями,
GitHub
LinkedIn
Twitter

Оцените статью
devanswers.ru
Добавить комментарий