ADG Оставить заявку
Блог DevOps 5 мин чтения

Managed Kubernetes в Яндекс.Облаке: первый продакшн-проект, Terraform и CI/CD из GitLab

Запускаем первый проект на Managed Kubernetes в Яндекс.Облаке: node groups, autoscaling, балансировщики - и сравниваем с self-hosted кластером по реальным ops-затратам.

Контекст момента

Яндекс.Облако расширяет Managed Kubernetes: поддержка node groups, autoscaling, интеграция с балансировщиками нагрузки

Яндекс.Облако на этой неделе объявило о расширении Managed Kubernetes - node groups с настраиваемым autoscaling, нормальная интеграция с облачными балансировщиками. Для нас это совпало с конкретным поводом: мы как раз завершаем первый продакшн-проект на этой платформе. Есть что рассказать.

Почему managed, а не self-hosted

Исходная ситуация у клиента была стандартная: несколько VM в Яндекс.Облаке, приложения в Docker Compose, ручные деплойменты. Задача - перейти на Kubernetes с нормальным CI/CD. Кластер в облаке можно было поднять двумя путями: самостоятельно через kubeadm на VM или взять Managed Kubernetes от провайдера.

Мы выбрали managed - и не потому что «облако это хорошо», а по конкретному расчёту операционных затрат. Control plane в self-hosted кластере - это минимум три master-ноды для отказоустойчивости, etcd с резервным копированием, ручные обновления версий Kubernetes, мониторинг самого кластерного слоя. В рамках нашего managed-сопровождения это всё ложится на нас. В случае Яндекс.Облака control plane скрыт за managed-слоем: ноды etcd, апгрейды мастеров, сертификаты - это чужая головная боль. Мы управляем только worker-нодами и тем, что на них запускается.

Экономия по времени реальная, но с оговоркой: управляемая плоскость - это чёрный ящик. Если что-то пошло не так внутри - наблюдаемость ограничена тем, что провайдер считает нужным показать.

Terraform как единственный источник истины

Инфраструктуру полностью описали в Terraform с lock-файлом - про это писали недавно. Провайдер yandex для Terraform достаточно зрелый: ресурсы для кластера, node group, сервисных аккаунтов, статических IP и балансировщиков там есть.

Структура получилась примерно такая:

resource "yandex_kubernetes_cluster" "main" {
  name        = "prod"
  network_id  = yandex_vpc_network.main.id

  master {
    version = "1.19"
    zonal {
      zone      = "ru-central1-a"
      subnet_id = yandex_vpc_subnet.main.id
    }
    public_ip = true
  }

  service_account_id      = yandex_iam_service_account.k8s.id
  node_service_account_id = yandex_iam_service_account.nodes.id
}

resource "yandex_kubernetes_node_group" "workers" {
  cluster_id = yandex_kubernetes_cluster.main.id
  version    = "1.19"

  instance_template {
    platform_id = "standard-v2"
    resources {
      memory = 8
      cores  = 4
    }
    boot_disk {
      type = "network-ssd"
      size = 64
    }
  }

  scale_policy {
    auto_scale {
      min     = 2
      max     = 6
      initial = 2
    }
  }
}

Autoscaling через auto_scale - это как раз из нового в Яндекс.Облаке. До этого расширения node group приходилось трогать вручную или через скрипты. Теперь кластер сам добавляет ноды при нагрузке и убирает их при простое - в рамках заданного диапазона.

Один нюанс с сервисными аккаунтами: нужны два отдельных - один для управления кластером, другой для нод (чтобы они могли пуллить образы из Container Registry). Это не очевидно из документации с первого раза, но после того как разобрались - в Terraform это фиксируется раз и навсегда.

CI/CD из GitLab

Деплой настроен через GitLab CI с runner'ом на отдельной VM вне кластера. Схема намеренно простая:

  • Сборка образа и push в Яндекс Container Registry
  • kubectl apply с обновлённым тегом образа через envsubst в манифестах
  • Раскатка через rolling update, без Helm на первом этапе

GitLab runner получает доступ к кластеру через kubeconfig - его генерируем Terraform'ом и кладём в переменные CI как protected secret. Версия Kubernetes в кластере фиксирована в Terraform, значит неожиданных сюрпризов при kubectl быть не должно.

На практике сборка + деплой укладываются в приемлемое время. Основной bottleneck оказался не Kubernetes, а Docker build без кеша в чистом runner-окружении - это решается отдельно, но пока не критично.

Балансировщик и ingress

Яндекс.Облако интегрирует свои сетевые балансировщики с Kubernetes через Service типа LoadBalancer. Создаёшь сервис - облако поднимает L4-балансировщик и выдаёт внешний IP. Для большинства сценариев этого достаточно.

Для HTTP-трафика с routing по хостам поставили nginx ingress controller. Он создаёт один LoadBalancer-сервис для всего ingress, а дальше маршрутизация уже внутри nginx. Сертификаты через cert-manager с Let's Encrypt - стандартная схема.

На момент запуска L7 Application Load Balancer от Яндекса для Kubernetes был в preview и мы его не трогали - предпочли проверенный nginx ingress с понятным поведением.

Чем managed отличается на практике

Честный список наблюдений:

Обновления версий Kubernetes. В managed-кластере обновление мастера - кнопка в консоли (или ресурс в Terraform). Ноды обновляются rolling'ом через node group. Никакого kubeadm upgrade apply, никакого ручного drain/uncordon мастеров. Это реально удобно. Обратная сторона - расписание доступных версий диктует провайдер, не мы.

Логи и метрики. Control plane logs можно направить в Yandex Cloud Logging. Для метрик нод работает стандартный prometheus-стек - ничего экзотического. Но метрики самого etcd или API-сервера через managed-слой не достать.

Сеть. Под капотом - Calico. Это хорошо: предсказуемое поведение Network Policy, знакомые инструменты отладки. Но настроить параметры Calico напрямую нельзя - только то, что выставляет облако.

Цена. Control plane тарифицируется отдельно, worker-ноды - по стоимости VM. Итоговая сумма сопоставима с self-hosted на аналогичном железе, но без затрат времени на поддержку мастеров. Для клиента это выгодно: платит деньгами, не нашим временем на инфраструктурные рутины.

Где сейчас

Кластер работает первую неделю в продакшне. Autoscaling ещё не проверили под реальной пиковой нагрузкой - будем смотреть. Следующий шаг - добавить Helm для управления chart'ами приложений и настроить нормальный мониторинг через Prometheus + Grafana в кластере.

Self-hosted Kubernetes никуда не денется - у части клиентов железо вне облака и там managed не вариант. Но для проектов полностью в Яндекс.Облаке managed-кластер снимает достаточно операционного шума, чтобы выбор в его пользу был оправдан.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.