Node Pools в AKS

042ef68e176be51e0e0f53cac060257c.jpg

Привет, Хабр!

В Kubernetes кластер состоит из множества узлов (nodes), которые представляют собой виртуальные или физические машины, на которых запущены приложения. Node Pools — это группы узлов с одинаковой конфигурацией, управляемые как единое целое.

С Node Pools можно иметь разные пулы для разных задач или приложений, оптимизировать стоимость, используя различные типы виртуальных машин, и применять разные ОС в рамках одного кластера.

Azure Kubernetes Service (AKS) — это управляемый сервис Kubernetes от Microsoft, предназначенный для упрощения развертывания, управления и масштабирования приложений на базе контейнеров. AKS автоматически управляет хостовыми инфраструктурами, снимая бремя настройки и мониторинга, позволяя сосредоточиться на разработке приложений.

Node Poole

Для работы с AKS можно юзать Azure CLI войдя в систему через команду az login.

Начнем с его создания кластера AKS. Юзаем следующую команду:

az aks create --resource-group myResourceGroup --name myAKSCluster --node-count 1 --enable-addons monitoring --generate-ssh-keys --location eastus

Здесь создали кластер AKS с именем myAKSCluster в ресурсной группе myResourceGroup с одним узлом. Мониторинг включен, ключи SSH генерируются автоматически, и кластер размещается в регионе eastus.

Для добавления нового Node Pool есть команда:

az aks nodepool add --resource-group myResourceGroup --cluster-name myAKSCluster --name myNodePool --node-count 3

Команда добавляет новый Node Pool с именем myNodePool в кластер myAKSCluster, который находится в ресурсной группе myResourceGroup. В этом Node Pool будет 3 узла.

Можно настроить Node Pool, указав дополнительные параметры, такие как размер виртуальной машины и тип диска. Например:

az aks nodepool add --resource-group myResourceGroup --cluster-name myAKSCluster --name myCustomNodePool --node-count 2 --vm-size Standard_DS2_v2 --os-type Linux

Добавляем Node Pool с именем myCustomNodePool в кластер myAKSCluster, который находится в ресурсной группе myResourceGroup. В этом Node Pool будет 2 узла, каждый из которых использует виртуальную машину размера Standard_DS2_v2 с ос линукс.

Azure Portal предоставляет графический интерфейс для управления ресурсами Azure:

Входим в Azure Portal. На панели навигации выбираем «Kubernetes services» и переходим к кластеру AKS.

Добавление Node Pool выглядит довольно просто:

  1. В меню кластера AKS выбираем Node pools.

  2. Нажимаем кнопку + Add node pool.

  3. В форме добавления Node Pool вводим имя, выбераем размер виртуальной машины, количество узлов и другие параметры

  4. После настройки параметров нажимаем Add для создания Node Pool.

aa71eba77d794d0e884292cb8110b14e.png

После добавления Node Pool можно мониторить его состояние и управлять им через раздел Node pools вашего кластера AKS в Azure Portal. Здесь можно редактировать количество узлов, размер виртуальных машин и другие параметры.

Удалить узлы можно, уменьшив количество узлов в Node Pool с помощью Azure CLI или удалить весь Node Pool, если он больше не нужен:

Можно использовать команду az aks nodepool scale, указав меньшее количество узлов:

az aks nodepool scale --resource-group myResourceGroup --cluster-name myAKSCluster --name myNodePool --node-count 3

Это уменьшит количество узлов до 3 в Node Pool myNodePool.

Если Node Pool больше не нужен, его можно прост удалить:

az aks nodepool delete --resource-group myResourceGroup --cluster-name myAKSCluster --name myNodePool

Обновление узлов до новых версий позволяет внедрять последние функции, исправления безопасности и улучшения производительности. На практике обнова узлов обычно связана с обновлением версии Kubernetes для Node Pool. Делается это с помощью az aks nodepool upgradeи с проверкой доступных версий с помощью az aks get-versions:

az aks nodepool upgrade --resource-group myResourceGroup --cluster-name myAKSCluster --name myNodePool --kubernetes-version 1.29

AKS обновляет узлы в Node Pool по одному, чтобы минимизировать простои. Для каждого узла в Node Pool процесс включает такие шаги:

  1. AKS помечает узел как unschedulable, чтобы предотвратить размещение новых подов на нем.

  2. Существующие поды на узле перемещаются на другие узлы в кластере с использованием механизма эвакуации подов.

  3. Узел обновляется до новой версии Kubernetes.

  4. После успешного обновления узел возвращается в кластер как готовый к работе, и на нем снова могут быть запланированы поды.

Taints и Tolerations

Taints применяются к узлам и могут отталкивать поды, которые не имеют соответствующих tolerations. Это позволяет ограничить, какие поды могут быть запущены на определенных узлах. Taints состоят из ключа, значения и эффекта, который определяет, что происходит с подами, не имеющими соответствующего toleration. Эффекты могут быть следующими:

  • NoSchedule: под не будет запланирован на узел.

  • PreferNoSchedule: система будет стараться не планировать под на узел, но это не гарантировано.

  • NoExecute: под будет выгнан с узла, если он уже запущен и не имеет соответствующего toleration.

Предположим, есть узлы с высокопроизводительными GPU, которые нужно использовать только для задач ml. Можно добавить taint к этим узлам:

kubectl taint nodes gpu-node-1 gpu=true:NoSchedule

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

Пример toleration для пода:

apiVersion: v1
kind: Pod
metadata:
  name: ml-pod
spec:
  containers:
  - name: ml-container
    image: ml-image
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"

Этот под сможет запускаться на узле gpu-node-1, так как имеет соответствующий toleration.

Labels и Selectors

Labels — это ключ/значение метки, которые можно прикрепить к объектам, таким как поды и узлы, и затем использовать selectors для выбора объектов на основе этих меток.

Можно пометить узлы в зависимости от их физического расположения:

kubectl label nodes node-1 location=europe
kubectl label nodes node-2 location=asia

Чтобы запустить под на узле в определенном регионе, можно использовать node selector в спецификации пода:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-image
  nodeSelector:
    location: europe

Этот под будет запланирован на узле с меткой location=europe.

Примеры

Stateless приложения не сохраняют информацию о состоянии пользовательских сессий на сервере. К примеру для веб-странички конфигурация Node Pool может выглядеть так:

az aks nodepool add \
  --resource-group myResourceGroup \
  --cluster-name myAKSCluster \
  --name statelessNodePool \
  --node-count 3 \
  --enable-cluster-autoscaler \
  --min-count 1 \
  --max-count 10 \
  --node-vm-size Standard_F8s_v2 \
  --labels app=stateless \
  --no-wait

Здесь включено автоматическое масштабирование с минимальным количеством узлов 1 и максимальным 10, и используются виртуальные машины размера Standard_F8s_v2.

Развернем с yaml-манифестом:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web-container
        image: nginx
        ports:
        - containerPort: 80

Stateful приложения требуют сохранения данных или состояния между сессиями или запросами. Развернем бд PostgreSQL в кластере AKS

Конфигурация Node Pool:

az aks nodepool add \
  --resource-group myResourceGroup \
  --cluster-name myAKSCluster \
  --name batchNodePool \
  --node-count 2 \
  --node-vm-size Standard_D16s_v3 \
  --labels app=batch \
  --no-wait

Используем узлы Standard_D16s_v3, которые в целом дают хорошую производительность CPU

Создадим PVC для PostgreSQL и развертывание StatefulSet:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: "postgres"
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:latest
        ports:
        - containerPort: 5432
        volumeMounts:
        - mountPath: "/var/lib/postgresql/data"
          name: postgres-storage
      volumes:
      - name: postgres-storage
        persistentVolumeClaim:
          claimName: postgres-pvc

Статья подготовлена в преддверии старта курса Data Engineer. Узнать о курсе подробнее и зарегистрироваться на бесплатный урок можно по ссылке.

© Habrahabr.ru