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

Kubernetes 1.1: namespaces на практике и HPA который не дал завалить соседей

Запустили первый рабочий кластер Kubernetes для разработки: namespaces разделили dev/staging/prod, а HPA во время нагрузочного теста удержал остальные сервисы.

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

Kubernetes 1.1 вышел с улучшенными namespaces и горизонтальным автомасштабированием подов (HPA)

В июле мы разворачивали тестовый кластер Kubernetes 1.0 и честно написали что до продакшна ещё далеко - слишком много мест где можно обжечься. В начале ноября вышел 1.1, и именно он подтолкнул нас к тому чтобы поднять первый рабочий кластер - не лабораторный стенд, а реальную инфраструктуру для разработки нескольких команд.

Два конкретных новшества 1.1 сделали это возможным: доработанные namespaces с нормальными квотами ресурсов и Horizontal Pod Autoscaler. Без них задача «несколько команд, один кластер» выглядела как приглашение к войне за ресурсы.

Почему вообще один кластер

Логичный вопрос - зачем мучиться с мультиарендой, не проще ли дать каждой команде свой кластер?

Проще. Но у нас к тому моменту было несколько клиентских проектов на managed-инфраструктуре, и каждый из них тянул окружения dev, staging и prod. Три кластера на проект - это три набора etcd, трёх control plane нод, тройная операционная нагрузка. Умножаем на количество проектов и понимаем что это не масштабируется. Один кластер с нормальной изоляцией - разумный компромисс.

Что дали namespaces в 1.1

Namespaces были и раньше, но в 1.0 это был скорее логический тег без зубов. В 1.1 к ним добавили ResourceQuota и LimitRange - инструменты которые реально работают.

ResourceQuota на namespace - это жёсткий потолок. Мы назначили dev-неймспейсу лимит по CPU и памяти, staging получил побольше, prod - по фактической потребности плюс запас. Описывается одним манифестом:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    cpu: "4"
    memory: 8Gi
    pods: "20"

LimitRange задаёт дефолтные лимиты на под - если разработчик забыл указать requests/limits, неймспейс подставляет своё. До этого под без лимитов мог занять всё что есть на ноде. Это была реальная дыра.

RBAC по неймспейсам - у 1.1 он пока базовый, но достаточный: разработчики проекта А не видят поды проекта Б и не могут в них залезть. Простая вещь, но без неё разговора о мультиарендности нет.

Разделить dev/staging/prod на уровне namespace оказалось проще чем мы ожидали. Настройка заняла вечер, после чего окружения живут на одном кластере и не знают друг о друге.

Нагрузочный тест который мог всё положить

Вот тут и появился HPA - и очень вовремя.

Одна из команд запустила нагрузочный тест staging-окружения. Инструмент тупо молотил HTTP-запросами, приложение начало отъедать ресурсы. В старой схеме это означало бы деградацию всего кластера - или кто-то вручную масштабирует реплики, или все остальные ждут пока тест закончится.

С HPA картина другая. Настроили автомасштабирование для тестируемого деплоймента:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: staging-web
  namespace: staging
spec:
  scaleTargetRef:
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 8
  targetCPUUtilizationPercentage: 70

Во время теста HPA поднял количество реплик с двух до шести - кластер вытянул нагрузку горизонтально. Важный момент: namespace staging имел квоту, за пределы которой HPA выйти не мог. Prod и dev при этом работали без изменений - ни деградации, ни конкуренции за ресурсы. Соседи не пострадали.

Это не магия - это просто два механизма которые работают вместе: quota держит namespace в рамках, HPA распределяет нагрузку внутри этих рамок. Элегантно.

Что пришлось решать по дороге

Без шероховатостей не обошлось.

Сеть между namespace. По умолчанию поды из разных неймспейсов видят друг друга - изоляция логическая, не сетевая. Нам это не подходило: staging не должен случайно попасть в prod-базу. Решили через NetworkPolicy - в 1.1 она экспериментальная и работает только с конкретными network плагинами. Использовали Calico, повозились с конфигурацией, в итоге сделали.

Мониторинг. kubectl get pods --all-namespaces даёт общую картину, но для нормального наблюдения нужно что-то снаружи. Подключили Heapster который в 1.1 научился агрегировать метрики по namespace - это помогло видеть потребление ресурсов по окружениям.

Persistent storage. Статефул-сервисы - базы, очереди - мы не стали тащить в кластер. Они живут отдельно, поды в кластере к ним подключаются по адресу. Это осознанный выбор: меньше риска, проще бэкапы, не нужно возиться с PersistentVolume на этом этапе.

Где мы сейчас

Кластер с разделением по namespace работает вторую неделю. Команды деплоят в dev самостоятельно, staging накатывается по пушу в ветку, prod пока руками через kubectl - автоматический деплой в прод ещё обсуждаем.

HPA включён только в staging - смотрим как ведёт себя в реальных условиях прежде чем включать в prod. ResourceQuota в prod выставили консервативно, с запасом: лучше потом поднять потолок чем разбираться почему соседний namespace упёрся в чужие лимиты.

Шишки ещё будут - кластер молодой, и первый серьёзный инцидент покажет где мы что не учли. Но пока картинка выглядит управляемее чем была.

Контакт

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

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