
Главный прикол с k8s: поднять базовый кластер займёт всего 15 минут. А вот чтобы он реально заработал, ответить на все вопросы перед установкой, всё спланировать — на это нужны дни, реально дни мозгового штурма и планирования. Ну или потом придётся разбирать и делать ещё раз. Несколько раз.
Кубер унижает человеческое достоинство разными способами и на разных этапах. Это часть опыта от пользования продуктом. Так задумано.
И вот про эти самые вопросы мы сейчас и поговорим, потому что там целое волшебное поле грабель.
Начнём с простых вещей, например, выбора дистрибутива, выбора способа хранения данных (и динамического выделения места), а также того, куда складывать пароли к критичным ресурсам. На этих трёх выборах ломается примерно 50 % админов.
Поехали в ад!
Архитектура
Kubernetes — это кластер. То есть много серверов, которые работают вместе. Эти серверы называются нодами, или узлами. Есть ноды управляющие (Control Plane). Раньше их звали Master, но сейчас это слово немодное, так что Control Plane. А есть ноды рабочие (Worker Nodes) — вот на них-то и крутятся ваши приложения в контейнерах (точнее, в подах).
Рядом с Control Plane живёт etcd. Это распределённая база данных (ключ-значение), где Кубер хранит всю инфу о себе и о том, что в нём запущено: какие поды, какие сервисы, какие конфиги — вот это всё. Она тоже обычно распределена по нескольким управляющим нодам для надёжности. Для полной надёжности её ставят отдельно.
Работает это так: вы пишете файл с конфигом, который описывает условия и состояния, например: «Хочу такой-то деплой из стольких-то подов, чтобы он при таких условиях вёл себя так, а при таких — вот так». Эти правила хранятся в etcd, а Control Plane следит за их исполнением. Если есть разница между тем, как надо, и тем, как есть, — всё приводится в нужное состояние. То есть что-то грохается или добавляется. Автоматически.
Казалось бы, всё просто, но тут огромная кроличья нора.
Дело — в условиях и работе приложений. Чтобы прописать нормальные условия для работы кластера, придётся вытащить наружу кучу метрик изнутри ваших приложений. Потому что более-менее доступные условия «из коробки» — это, например, «Если нагрузка на процессор больше 80 % 10 секунд подряд», а не «Если я записываю в базу данных быстрее чем за 0,1 секунды, и очередь — меньше 1 000 событий».
То есть вам надо будет продумать внешнюю сигнализацию своим приложениям, чтобы отдельные контейнеры могли сообщать внешнему миру о своём состоянии. Например, когда они перегружены, недогружены или что-то ещё.
Вторая особенность — вам надо обеспечить правильное поведение приложения при добавлении-убавлении контейнеров. Это касается транзакций (надо корректно закрываться после обработки транзакции, а не терять её), записи на диск и так далее.
С диском — тоже отдельный сюрприз: мышление придётся изменить. Но давайте по порядку.
Если у вас планируется реально большой нагруженный кластер, то Control Plane и особенно etcd лучше выносить на отдельные выделенные ноды. Не надо на них вешать рабочую нагрузку, пусть они занимаются только управлением. У себя на деве или стейдже мы можем и совмещать, чтобы экономить ресурсы, но на проде лучше делить. В наших собственных продуктах на dev-части мы совмещаем узлы, а на прод-части создаём два отдельных контура.
Почему это проблема?

Потому что это унижает человеческое достоинство. Просто знайте: то, что у вас поначалу не всё получается, — это нормально. Это часть процесса. Так задумано. Вот как сталкивались с этим наши участники команды разработки:
- Начинаешь с Kubernetes — вроде всё понятно по верхам, курс прошёл, потыкал. Гугл и AI помогают. Но потом лезешь глубже: драйверы для хранилищ, autoprovisioning, сети… и это просто стена! Понять базово — это одно, а настроить под себя — совсем другое. Нужны или огромный опыт, или куча времени, чтобы просто сидеть и ковыряться. Настроить выход наружу? Тоже целая история с кучей нюансов: часто просто копируешь решения, не до конца понимая.
- Написать код — быстро. А вот развернуть его в Кубере первый раз — это дни мучений! Сертификаты, связь между сервисами, настройка Argo CD с ключами — всё совершенно неинтуитивно. Если рядом нет опытного DevOps, который проведёт за ручку, то это просто взрыв мозга и боль: не понимаешь, за что страдаешь! Но когда наконец всё настроишь, думаешь: «Боже, как же хорошо! Теперь только так и буду работать! Только, пожалуйста, пусть кто-нибудь другой развернёт сам Кубер, я этого больше не хочу!»
- Пытаешься соединить внутренние сервисы Кубера с внешним миром — и тут начинаются танцы с бубном. Куча технологий, и все — на разной стадии готовности.
- Самое сложное в начале — просто понять, как вообще работать с Kubernetes. У тебя не запускается простой сайт в Docker-контейнере, а DevOps объясняет проблему терминами Кубера, и ты даже не понимаешь, как это отладить, куда смотреть. Потом тебе дают конфиг для kubectl и говорят: «Разбирайся сам». Ощущение, будто тебя выкинули с лодки посреди озера: плыви!
Что ставить
Это классика жанра для новичка. Открываешь доку Кубера, а там бац — десяток способов установки! И хрен поймёшь, какой тебе нужен.
Дальше можно гуглить «Kubernetes Hard Way» и «Kubernetes Simple Way»: там статьи разной степени упоротости. Поскольку на дворе — XXI век, можно попросить помочь и LLM, но это будет step-by-step-воспроизведение одной из этих двух инструкций.
Третий путь — пойти к облачному провайдеру и там найти managed-service для k8s, обычно выглядящий для пользователя как волшебная кнопка «Создать кластер Kubernetes». Жмакнули, подождали минут 10–15, и вам вываливается файлик с конфигом. А дальше наступает ступор. Смотрите на этот файлик и думаете: «Ну зашибись, а дальше-то что?»
Мой личный совет: прежде чем лезть в облака или мучиться со своими серверами, поставьте себе на ноут Minikube. Это такая песочница, маленький Кубер на одной машине. Погоняйте его, потыкайте палочкой, разберитесь с базовыми понятиями: что такое Pod, Service, Deployment — вот это всё. Освойте kubectl — это главная команда для общения с кластером. Вот когда вы через это пройдёте, тогда и Managed Service в облаке станет в разы понятнее, и вы будете знать, что делать с этим загадочным admin.conf.
Итак, вариантов три с половиной:
- Managed Service в облаке (типа нашего H3LLO CLOUD) — это когда вы приходите к провайдеру, говорите: «Хочу Кубер», нажимаете пару кнопок (ну или не пару: всё зависит от упоротости провайдера), получая готовый кластер и kubeconfig. Плюсы: не надо париться с установкой и обновлением управляющих нод (Control Plane, etcd): всё это — головная боль провайдера. Масштабирование нод — часто «из коробки»: настроил правило, и если нагрузка растёт, то провайдер сам добавит виртуалок в ваш кластер. Автоматическое выделение persistent volume любого размера в любом количестве — тоже на провайдере, как и LoadBalancer для внешнего доступа. Минусы: зависимость от провайдера, его ограничений (про них ещё скажу) и его ценовой политики.
- На своих серверах (Bare Metal) или своих виртуалках. Полный контроль над железом, над софтом, над настройками. Делайте что хотите. Но на вас падает вся сложность установки, настройки, обновлений, бэкапов. Масштабировать кластер новыми серверами? Только ручками: пошёл, купил сервер, поставил в стойку, настроил, добавил в кластер. Никакой магии.
- Руками в облаке на виртуалках: можно, но зачем? Если очень хочется поковыряться в кишках, но своего железа нет. Или если Managed-сервис чем-то критично не устраивает (например, версией Кубера или доступными опциями). По сути, это то же самое, что и Bare Metal, только серверы арендованные. Вся сложность — ваша, но хотя бы серверы покупать не надо.
Последний способ — запустить отдельный контейнер в контейнерном хостинге типа нашего L1VESTACK. Тут вообще от платформы и серверов полностью абстрагируемся. Но это скорее для быстрого решения текущей задачи, а не для того, чтобы правильно настроить Кубер.
Как ставить
- Kubeadm — официальная утилита от создателей Кубера. Но это, как я говорю, «путь самурая». Все команды — ручками, все конфиги — ручками, бутстрэп каждой ноды — ручками. Если вы не мазохист и ставите Кубер первый раз — не советую категорически: намучаетесь и проклянёте всё на свете.
- Kubespray — это наш выбор для своих инсталляций на железе или виртуалках. Это, по сути, набор готовых Ansible-сценариев. Он автоматизирует 90 % рутины по развёртыванию кластера на куче нод. Есть неплохие статьи, как его подготовить и запустить. Очень рекомендую начинать именно с него, если вы решили ставить сами и уже выросли из Minikube. Очевидный плюс — в дальнейшем удачный конфиг можно многократно воспроизвести.
- Экзотика — есть и другие штуки, часто привязанные к специфичным ОС. Например, для Talos OS есть свои утилиты — Talos CTL (ручками) и talm (типа Helm, но для Талоса). Интересные вещи, но это уже для тех, кто в теме.
На какую ОС ставить ноды
- Есть обычные Linux — старая добрая Ubuntu, CentOS, Debian, и всё это прекрасно работает. Привычно, понятно, куча доков в сети.
- Специализированные ОС — есть дистрибутивы, заточенные специально под контейнеры и Кубер. Это Fedora CoreOS / Flatcar Container Linux: часто у них readonly — корневая файловая система для безопасности, атомарные обновления. Но есть нюансы: например, FCOS вместо привычного cloud-init использует свой формат конфигов — Ignition. Надо разбираться, как его готовить (там есть ещё утилита Butane). Talos — ещё более хардкорный вариант. Там вообще нет привычной ОС с shell! Всё управляется через API. Максимальная безопасность, минимализм. Но требует полного переосмысления подхода к управлению хостами.
Если нет особых требований к безопасности или специфике, то начинайте с обычной Ubuntu LTS — не ошибётесь.
Container Runtime
- Docker (точнее, dockershim) — до недавнего времени был стандартом де-факто. Сейчас его официально выпилили из Кубера, но многие дистрибутивы и инсталляторы по-прежнему его поддерживают через прослойку. Если у вас нет веских причин для другого — можно начать с него: он самый привычный.
- Containerd — а вот это стандарт де-факто сейчас, поддерживаемый Кубером напрямую через интерфейс Container Runtime Interface. Кстати, Docker сам под капотом использует containerd, так что переход на него обычно безболезненный. Большинство новых инсталляций использует именно его.
- CRI-O — ещё реализация CRI, разрабатываемая Red Hat. Тоже хороший вариант.
- Есть и совсем специфичные вещи типа Kata Containers (запускает контейнеры в легковесных виртуалках для изоляции) или Kubevirt (позволяет запускать полноценные ВМ внутри Кубера). Но это уже для особых случаев.
Рекомендация: начинайте с containerd. Это сейчас мейнстрим.
Хранение
Вот это критически важный вопрос, если у вас не только stateless-вебморды, но и базы данных, очереди, кэши — всё, что должно переживать перезапуск и падение подов.
Сразу забудьте про использование локальных дисков на нодах для хранения важных данных в продакшене! Нода умерла — данные пропали.
То есть данные должны быть размазаны по кластеру или храниться в выделенном отдельном хранилище.
Кубер для работы с хранилищами использует стандартный интерфейс Container Storage Interface. Это позволяет подключать к нему самые разные системы хранения данных — как локальные, так и сетевые.
Базовое решение Ceph — очень популярное, мощное и надёжное распределённое хранилище. Наш опыт показывает, что это отличный выбор. Его можно развернуть отдельно, а можно прямо внутри Кубера с помощью специального оператора Rook. Rook сам поднимает все компоненты Ceph (мониторы, OSD на дисках нод) в виде подов и делает его доступным для Кубера через CSI. Мы у себя часто используем именно связку Ceph + Rook.
Всё это работает так. У вас есть приложение, работающее в контейнере внутри Kubernetes K8s. Этому приложению, например, базе данных, нужно место для хранения данных — скажем, пять гигабайт. Создаётся PVC (Persistent Volume Claim). Это как заявка на диск. Кубер понимает запрос и обращается к системе хранения данных (например, Ceph) через autoprovisioning с командой: «Создай диск на пять гигабайт». В Ceph создаётся блочный диск (RBD) и выделяется Куберу в виде его сущности PV (Persistent Volume). И уже этот PV подключается к поду.
Ceph — это распределённая система хранения, которая обычно устанавливается на те же серверы (узлы), где работают и сами контейнеры (сейчас мы — про Bare Metal). Она объединяет диски этих серверов в единое большое хранилище.
Хотя компоненты Ceph (например, процессы, управляющие отдельными дисками — OSD) могут запускаться в своих управляющих контейнерах (часто — с помощью инструмента Rook), сама система хранения тесно связана с физическими дисками и серверами. Когда контейнер падает, диск в Ceph остаётся. Когда падает целый сервер, данные сохраняются. Система не хранит всех данных на одном диске или узле: при записи копии данных «размазываются» по разным дискам на разных серверах. Мы сами выбираем, какой уровень репликации установить. Ceph автоматически обнаружит потерю OSD и начнёт перераспределять данные по оставшимся рабочим дискам, чтобы восстановить нужный уровень избыточности.
Если контейнер поднимется на другой машине после перезапуска, то новый экземпляр контейнера просто подключится к тому же самому постоянному тому (Persistent Volume), который был создан для него в Ceph. Данные на диске никуда не делись. Управление самим кластером Ceph — тоже отказоустойчиво. Есть специальные процессы-мониторы и манагер с репликами в режиме standby. Если сервер с главным манагером выходит из строя, то управление автоматически переходит к другому манагеру на другом сервере.
Конечно, система не неуязвима. Если выйдет из строя слишком много серверов или дисков одновременно, так, что оставшегося места не хватит для хранения всех данных или их реплик, или если не останется достаточно узлов для поддержания кворума управления кластером, то Ceph может перестать работать или перейти в состояние «Только для чтения». Там лучше разбираться руками.
В целом нет ничего хуже, чем развал кластера. В этой ситуации придётся долго и весело танцевать с бубном, если у вас не настроены итеративные бэкапы.
Ещё варианты:
- LinStor — ещё одно распределённое хранилище, и тоже с CSI-драйвером. Говорят, может быть производительнее Ceph в некоторых сценариях. Тоже достойный вариант.
- Если вы в облаке, то у провайдера есть свои CSI-драйверы для их блочных хранилищ (Amazon EBS, Google Persistent Disk, Azure Disk, etc.). Обычно это самый простой вариант в облаке. Причём их можно смешивать для разных условий и для разных типов данных.
- Более экзотичные GlusterFS, локальные диски через Local Persistent Volumes (только для специфичных задач!) и куча других вариантов.
Вы можете определить разные «классы» хранения (StorageClass), например, fast-ssd, slow-hdd, cloud-premium. А потом в манифесте для вашего приложения (в PersistentVolumeClaim) вы просто указываете имя нужного класса. Кубер через CSI-драйвер сам создаст диск нужного типа в соответствующем бэкенде (Ceph, облако, etc.). Это позволяет абстрагироваться от конкретной реализации хранилища.

Сеть
Если диски ещё более-менее понятны, то тут спотыкаются даже опытные админы. Сеть в Кубере — это, пожалуй, одна из самых сложных тем. Вам точно понадобятся хотя бы базовые знания сетей (IP-адресация, маршрутизация, файрволы).
Kubernetes создаёт свою собственную виртуальную сеть поверх вашей физической (или облачной) сети. Каждый под (контейнер) получает свой IP-адрес в этой виртуальной сети. И поды, запущенные на разных физических нодах, должны иметь возможность общаться друг с другом по этим виртуальным IP. Чтобы эта магия работала, нужно выбрать и установить CNI-плагин (Container Network Interface). Это такой софт, который и отвечает за настройку сети для подов. Наши фавориты:
- Cilium — очень мощный и быстрый плагин. Он использует новомодную eBPF прямо в ядре Linux, что даёт ему производительность и кучу фич (сетевые политики, шифрование, балансировка). У Cilium есть ещё крутой инструмент Hubble — это UI и CLI для визуализации сетевых потоков и зависимостей между сервисами. Супервещь для отладки, мы его любим.
- Calico — тоже очень популярный и зрелый плагин. Часто идёт по умолчанию во многих инсталляторах (например, в Kubespray). Умеет работать как с оверлейными сетями (VXLAN, IPIP), так и без оверлея, используя BGP-маршрутизацию, если ваша сеть это поддерживает. Тоже отличный выбор.
- Flannel (простой, для начала неплох).
- Weave Net, Antrea и куча других, в том числе специфичных для облаков (AWS VPC CNI, Azure CNI, GKE Netd).
В зависимости от выбранного CNI и вашей инфраструктуры вам может потребоваться разбираться с BGP, VXLAN, IPIP-туннелями, настройкой маршрутов и файрволов. Сеть — это то место, где можно застрять надолго. Как сказал один наш сетевик, когда разбирался с какой-то проблемой: «По идее должно быть так, но хрен его знает, иди копай». Эта фраза будет преследовать вас примерно везде по мере реализации.
«Я запустил Nginx в поде, как мне его открыть в браузере?»
В Кубере есть специальная штука — Service. Это абстракция, которая даёт постоянный IP-адрес и DNS-имя для группы подов (например, для всех реплик вашего веб-сервера) и умеет балансировать трафик между ними.
Типы сервисов:
- ClusterIP: сервис получает внутренний IP, доступный только изнутри кластера. Для внутренних бэкендов — самое то.
- NodePort: сервис открывает порт на каждой ноде кластера. Вы можете обратиться на IP_любой_ноды:NodePort и попасть на сервис. Неудобно, небезопасно, порты надо выбирать из определённого диапазона. Для продакшена — фу.
- LoadBalancer: вот это уже интереснее. Если вы в облаке, то при создании сервиса такого типа облачный провайдер автоматически создаёт вам внешний облачный балансировщик (ELB, Google LB, etc.), назначает ему публичный IP и направляет трафик на ваш сервис (точнее, на его NodePort на нодах). Очень удобно! А что делать, если у вас свой кластер на железе (Bare Metal)? Облачного балансировщика нет. Тут на помощь приходит MetalLB. Это такой специальный контроллер, который эмулирует облачный LoadBalancer. Вы выделяете ему пул IP-адресов из вашей локальной или публичной сети (если вы крутой и имеете свою публичную сеть), и когда создаёте сервис типа LoadBalancer, MetalLB берёт свободный IP из пула и «анонсирует» его в вашей сети (обычно через ARP или BGP), чтобы трафик на этот IP приходил на ноды вашего кластера. Обязательная штука для Bare Metal!
- Есть еще ExternalName, который использует DNS с кастомными параметрами, но даже в официальной доке предупреждают, что для некоторых протоколов типа http(s) могут быть проблемы. Мы его не используем.
Ingress — стандарт для публикации веб-приложений (HTTP/HTTPS) в продакшене. Ingress — это не тип сервиса, это отдельный ресурс в Кубере. Он работает как умный реверс-прокси или «входные ворота» для внешнего трафика. Он позволяет рулить трафиком на разные сервисы внутри кластера на основе хоста (например, api.mysite.com -> сервис API, blog.mysite.com -> сервис блога) или пути (mysite.com/app1 -> сервис App1, mysite.com/app2 -> сервис App2). Ingress также обычно отвечает за TLS-терминацию (SSL-сертификаты).
Чтобы Ingress заработал, вам нужно установить Ingress-контроллер. Это, по сути, и есть тот самый реверс-прокси, который читает Ingress-ресурсы и настраивает себя соответствующим образом. Самый популярный — Nginx Ingress Controller: знакомый многим Nginx, но специально заточенный под Кубер. Мощный, гибкий. Но! Будьте осторожны: недавно в нём находили неприятные уязвимости, позволяющие читать секреты из кластера. Это к важности своевременных апдейтов. Из других хороши HAProxy Ingress, Traefik (очень популярен, умеет сам получать Let's Encrypt-сертификаты), Contour и другие.
Настроить Ingress, сертификаты, DNS — это тоже задача не на пять минут. А если обратиться к официальной документации, то она рекомендует идти не в Ingress, а в Gateway API. Тут может показаться, что надо начать с него, и даже есть классные GUI для Gateway API, и хорошо бы ими воспользоваться! Но погодите )
Gateway API — это относительно новая спецификация в Кубере, которая со временем должна заменить или дополнить Ingress. Она более гибкая, позволяет разделять ответственность по маршрутам для разработчиков. Выглядит перспективно. Но я бы пока советовал не лезть в экзотику типа Kong Gateway. Да, у него есть красивый UI, что подкупает в мире консольного Кубера. Но он ломает саму идеологию Кубера с его декларативными манифестами в etcd и использует другую логику представлений. Лучше освоить стандартный Ingress с Nginx или Traefik, а к Gateway API присматриваться постепенно по мере накопления опыта. Есть реализации на базе того же Nginx, Envoy (Istio, Contour), HAProxy. Если разбираться с Gateway API, то лучше начать с них.
Кусок информационной безопасности
Пароли от баз данных, ключи к внешним API, всякие токены — ни в коем случае нельзя хардкодить в коде приложения (если кто-то ещё так делает и не был распят) или пихать прямо в YAML-манифесты! Этим вы создаёте огромную дыру в безопасности.
Для этого в Кубере есть специальные объекты:
- Secrets — для хранения чувствительных данных (пароли, токены, TLS-сертификаты). Они хранятся в etcd в base64 (что не шифрование!), но Кубер предоставляет механизмы для их шифрования «at rest» и контроля доступа к ним через RBAC.
- ConfigMaps — для хранения нечувствительной информации конфигурации (URL’ы, параметры, конфиг-файлы целиком).
- Продвинутый уровень: можно интегрировать Кубер с внешними системами управления секретами, например, HashiCorp Vault, с помощью специальных инструментов (Vault Agent Injector, External Secrets Operator). Это даёт централизованное управление, ротацию секретов и т. д.
Вы можете «подсунуть» данные из Secrets и ConfigMaps вашему приложению как переменные окружения для контейнера или как файлы, смонтированные в определённую директорию внутри контейнера.
Конечно, ваше приложение должно быть готово к этому. Оно должно уметь читать конфигурацию и секреты из переменных окружения или из файлов по указанным путям, а не из своего config.ini, лежащего рядом с бинарником. Часто это требует доработки кода приложения.
Но идеальный сценарий — это когда, например, кластер Cassandra создаётся автоматически через оператор типа k8ssandra, и приложение берёт креды для доступа из секрета, созданного оператором при запуске кластера. Ни в БД, ни в приложение ручками их никто не прокидывает.
Аутентификация и авторизация
В вашем кластере наверняка будут работать разные люди: DevOps/SRE, разработчики команды А, разработчики команды Б, может быть, QA-инженеры… Кто может деплоить приложения, кто может смотреть секреты, кто может удалять ноды?
- Аутентификация. Сертификаты X.509, токены (статичные, JWT, через OIDC-провайдера типа Keycloak или Dex), интеграция с LDAP/AD.
- Авторизация (RBAC — Role-Based Access Control). Вот это — самое главное. RBAC позволяет очень гибко настроить, что (какие действия: get, list, create, update, delete) с какими ресурсами (pods, services, secrets, nodes, etc.) в каких неймспейсах (или во всём кластере) и кто может делать (какой пользователь, группа или сервисный аккаунт). Вы создаёте Роли (Roles) или Кластерные Роли (ClusterRoles), где описываете набор разрешений. Затем вы создаёте Привязки Ролей (RoleBindings) или Кластерные Привязки (ClusterRoleBindings), чтобы связать роль с конкретным пользователем, группой или сервисным аккаунтом.
- Namespaces: используйте неймспейсы для логической изоляции ресурсов разных команд, проектов или окружений (dev, stage, prod). Это помогает упорядочить кластер и упрощает настройку RBAC (роли можно создавать внутри неймспейса). Хотя для окружений более правильно и эффективно использовать разные кластеры (опять же привет, облака).
- Золотое правило — минимальные привилегии. Давайте пользователям и сервисным аккаунтам только те права, которые им реально необходимы для выполнения их задач. Не надо всем раздавать cluster-admin: это прямой путь к катастрофе.
Observability
Вот мы и приехали к той самой волшебной части. Работать с кластером Kubernetes без настроенной системы мониторинга и логирования — это посадить админом слепого котёнка.
Метрики:
- Нужен Metrics Server — это базовый компонент (обычно ставится аддоном), который собирает основные метрики использования ресурсов (CPU, RAM) с нод и подов. Он нужен как минимум для работы kubectl top и базового HPA.
- Стек Prometheus + Grafana — это де-факто стандарт для сбора, хранения и визуализации метрик в мире Кубера. Prometheus — это база данных временных рядов, которая сама опрашивает метрики с разных источников (ноды, поды, сервисы). Grafana — инструмент для построения красивых дашбордов на основе данных из Prometheus (и не только).
- Приложения должны сами отдавать метрики в формате, понятном Prometheus (обычно это текстовый формат по HTTP-эндпоинту /metrics). Не только CPU/RAM, но и специфичные для приложения: количество запросов в секунду, время ответа, размер очереди, количество ошибок, бизнес-метрики. Без этого ваш мониторинг будет неполным.
А я предупреждал )
Логи:
- Контейнеры в Кубере обычно пишут логи просто в stdout и stderr. Эти логи собираются движком контейнеров (containerd/docker) и доступны через kubectl logs. Но смотреть логи каждого пода по отдельности — это ад.
- Нужен централизованный сбор логов. Необходимо настроить агентов (например, Fluentd, Fluent Bit, Promtail), которые будут бегать на каждой ноде, собирать логи из файлов или напрямую от движка контейнеров и отправлять их в центральное хранилище.
- Популярные варианты хранилищ логов — Elasticsearch (в составе стека ELK/EFK: Elasticsearch + Logstash/Fluentd + Kibana) или Loki (от создателей Grafana, хорошо интегрируется с Prometheus, обычно используется в стеке LGTM: Loki + Grafana + Promtail).
Это, кстати, значит, что логи должны быть структурированными, чтобы их было легко парсить и искать по ним. Вероятно, тут вам ещё раз придётся вернуться к разработке приложения и навести порядок в том, как оно кладёт логи под себя.
Трассировка. Если у вас микросервисная архитектура, то один запрос пользователя может проходить через десяток разных сервисов. Чтобы понять, где именно возникла задержка или ошибка, нужна распределённая трассировка. Инструменты: Jaeger, Zipkin, Tempo.
Конечно, приложения должны уметь принимать и передавать дальше специальные заголовки (trace ID, span ID) и отправлять информацию о своих операциях (спанах) в коллектор трейсов. Это тоже требует доработки кода.
Масштабирование
Ну что, база есть, доступ настроен, всё видно. Теперь можно и фишками обмазаться.
Устали поднимать руками и настраивать PostgreSQL, Kafka, Redis, Elasticsearch в Кубере? Следить за их состоянием, бэкапами, обновлениями? Для этого придумали операторов. Оператор — это, по сути, ваш кастомный контроллер внутри Кубера, который знает, как управлять определённым типом сложного приложения. Он расширяет API Кубера с помощью Custom Resource Definitions.
Работает это так:
- Вы устанавливаете CRD для, скажем, PostgreSQL. Теперь Кубер знает о новом типе ресурса, например, PostgresCluster.
- Вы устанавливаете сам Оператор PostgreSQL (это обычное приложение, работающее в поде).
- Вы создаёте простой YAML-файл, где пишете — kind: PostgresCluster, name: my-db, spec: { replicas: 3, version: «15», storage: «fast-ssd» }.
- Применяете этот YAML (kubectl apply-f).
- Оператор видит, что вы создали новый ресурс PostgresCluster, и начинает действовать: создаёт нужные StatefulSets/Deployments, заказывает диски (PersistentVolumeClaims) нужного StorageClass, настраивает сервисы для доступа, конфигурирует репликацию, может настроить бэкапы и мониторинг — в общем, делает за вас всю грязную работу по развёртыванию и поддержке сложного stateful-приложения.
Существует огромное количество готовых операторов от сообщества и вендоров для баз данных, очередей, мониторинга, CI/CD — да чего угодно! Это очень мощный механизм расширения Кубера. Для совсем уж специфичных внутренних систем можно даже написать свой оператор (но это уже высший пилотаж).
Автомасштабирование — одна из главных фишек Кубера, ради которой его часто и внедряют.
- Горизонтальное автомасштабирование подов (HPA — Horizontal Pod Autoscaler) — самый частый и полезный вид. Вы создаёте HPA-ресурс и говорите: «Хочу, чтобы количество реплик моего приложения my-app было от двух до десяти, и чтобы оно масштабировалось, если средняя загрузка CPU по подам превысит 70 % (или RAM, или кастомная метрика из Prometheus, например, длина очереди)». Кубернейтс сам будет следить за метриками и автоматически добавлять или удалять поды my-app в указанных пределах.
- Вертикальное автомасштабирование подов (VPA — Vertical Pod Autoscaler). Менее популярный, но тоже бывает полезен. VPA анализирует реальное потребление ресурсов подами и может автоматически изменять requests и limits по CPU/RAM в манифесте пода. Чаще используется в режиме «рекомендаций», чтобы понять, сколько ресурсов реально нужно приложению. Использовать VPA вместе с HPA нужно осторожно: они могут конфликтовать.
- Масштабирование кластера (Cluster Autoscaler). Это уже про добавление и удаление целых серверов (нод) в кластер. Работает так: если в кластере появляются поды, которые не могут никуда запланироваться (состояние Pending) из-за нехватки ресурсов (CPU, RAM) на существующих нодах, то Cluster Autoscaler замечает это и автоматически заказывает у облачного провайдера новую ноду (или несколько), ждёт, пока она не поднимется, и добавляет её в кластер. Поды тут же планируются на неё. И наоборот: если Cluster Autoscaler видит, что какие-то ноды долгое время недозагружены и все их поды можно переместить на другие ноды, то он может автоматически удалить эти лишние ноды, чтобы сэкономить деньги. Это главная фишка облачных Managed Kubernetes. Там это обычно работает «из коробки». Если у вас свой кластер — на железе или виртуалках, то заставить Cluster Autoscaler работать можно, но сложнее. Нужно использовать Cluster API. Это такой проект, который позволяет управлять жизненным циклом кластеров Kubernetes (в том числе создавать и удалять ноды) с помощью самого Kubernetes. Cluster API имеет провайдеров для разных инфраструктур (vSphere, OpenStack, AWS, Azure, Bare Metal через Tinkerbell/MAAS). Но это отдельная большая тема.
Кстати, тут надо передать пламенный привет некоторым российским облакам. У них часто есть довольно смешные лимиты на максимальное количество нод в одном Managed-кластере: где-то — 100 (привет, ТаймВеб), где-то — вообще 32 (Яндекс). А Кубер, на минуточку, сам по себе спокойно тянет 5 000 нод в кластере и 150 тысяч подов и даже не поперхнётся (по официальным тестам). У ВК вроде лимит побольше — 500 нод, у Сбера — 249 (хотя в доке пишут, что 500). Всё равно не 5 000. У нас в H3LLO CLOUD мы постарались эту проблему решить и даём возможность строить реально большие кластеры, близкие к максимальным возможностям Кубера.

Думаете, это конец?
Нет, это начало.
Развернули кластер, настроили сеть, сторадж, мониторинг? Поздравляю! Вы прошли… ну, скажем, разминку.
Короткий анонс. Приложения должны быть готовыми жить в динамичной эфемерной среде Кубера. Почитайте про 12-factor app — это мастхэв. Приложение должно:
- Читать конфиги и секреты из окружения или файлов (никаких локальных config.xml!).
- Писать логи в stdout/stderr (а не в файлы!).
- Быть максимально stateless (состояние хранить во внешних базах, кэшах, хранилищах).
- Быстро стартовать.
- Корректно обрабатывать сигналы SIGTERM для graceful shutdown.
- Уметь отдавать метрики для мониторинга (health checks, readiness/liveness probes).
- Быть упаковано в легковесный Docker-образ.
Вам нужны конвейеры, которые будут автоматически:
- Собирать Docker-образы вашего приложения при коммите в Git.
- Пушить образы в Docker Registry (типа Harbor, GitLab Registry, Docker Hub).
- Обновлять YAML-манифесты (Deployments, StatefulSets, Services, Ingresses) с новой версией образа.
- Деплоить эти манифесты в Kubernetes (например, с помощью kubectl apply, Helm, Argo CD, Flux).
- Проводить тесты после деплоя.
- Обеспечивать лёгкий откат на предыдущую версию.
Инструментов для этого — море: Jenkins, GitLab CI, GitHub Actions, Tekton, Argo CD, Flux…
В идеальном розовом мире единорогов ваши разработчики вообще не должны знать слова «Kubernetes». Они просто пишут код, коммитят в Git, а дальше некая «платформа» сама всё собирает, тестирует и выкатывает куда надо. Нажал кнопку — получил фичу в проде. Достичь такого уровня абстракции — это Грааль платформенного инжиниринга. Это требует не только зрелого Кубера со всеми обвесами, но и глубокого понимания ваших приложений, процессов разработки и кучи инструментов поверх Кубера (часто это называют Internal Developer Platform). Это долгий и сложный путь.
А оно вообще того стоит? Если у вас реально сложная большая динамичная система, которая должна быть отказоустойчивой, масштабироваться под нагрузкой, часто обновляться без простоя, то однозначно — ДА, стоит. Головной боли на старте будет много, но потом вы получите такие гибкость, скорость и надёжность, которых другими путями добиться очень сложно, если вообще возможно. Вы реально сможете выкатывать фичи быстрее и спать спокойнее (но это неточно).
Если вы прочитали всё это и подумали: «Мама дорогая, да я в этом никогда не разберусь!», но при этом фишки Кубера вам нужны — не отчаивайтесь. Есть решения, которые берут на себя большую часть этой боли:
- L1VESTACK или другой контейнерный хостинг — тут мы пошли по пути максимального упрощения: полностью спрятали оркестратор под капот. Вы просто даёте нам свой docker-compose.yaml (да-да, прямо его!) или используете наш простой CLI — и ваше приложение магическим образом разворачивается и работает на нашей инфраструктуре. Вообще не надо думать ни про ноды, ни про сети, ни про стораджи, ни про Ингрессы, ни про RBAC. Просто код и деплой. Идеально для тех, кто хочет «просто чтобы работало». Естественно, нет фишек инфраструктуры для продвинутых, потому что вы запустили контейнер, который работает.
- H3LLO.CLOUD — на нашей платформе есть Managed Kubernetes. Здесь мы не прячем Кубер полностью, но берём на себя самую нудную и сложную часть: бутстреппинг, Control Plane, etcd, обновления базовой системы, обеспечение работы сети и хранилища, предоставляем автомасштабирование нод «из коробки». Вам всё ещё нужно понимать основные концепции Кубера (поды, сервисы, деплойменты) и уметь пользоваться kubectl, но основную инфраструктурную рутину и сложность мы снимаем. Это хороший баланс между контролем и удобством.
Что почитать или посмотреть
Для старта — Minikube.
Запуск Кубера без заморочек — kubespray.
Концепции Кубера из первоисточника — курим доку. Начать лучше с туториала, а потом читать Concepts и Tasks.
Хорошая книга — Production Kubernetes. Есть на русском.
Глубже по сетям — Networking and Kubernetes. Тоже есть на русском.
GUI для Кубера — Lens.
The Twelve-Factor App.
Жирнющие бесплтаные лимиты на облачные сервисы на целый год, включая Managed Kubernetes — H3LLO.CLOUD.
Не менее щедрые лимиты на платформу для запуска приложений в контейнере — L1veStack.