Всем привет, меня зовут Сергей Прощаев, и в этой статье расскажу про фундамент, без которого сегодня невозможно представить серьёзную работу с микросервисами — архитектуру и ключевые абстракции Kubernetes.
Я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech & E-commerce, преподаю на курсах разработки и архитектуры в OTUS. Через мои руки прошли десятки проектов, и везде, где появлялся Kubernetes, возникал один и тот же парадокс: инструмент называют стандартом, но реальное понимание его механик встречается редко.
Давайте разбираться.

Почему Kubernetes — это не «ещё один Docker»
Бытует мнение, что Kubernetes — это просто «запускатор контейнеров». Заблуждение дорогое. Когда говорят «контейнеры», чаще всего подразумевают Docker. Но Docker отвечает за упаковку и запуск одного контейнера на одной машине. Kubernetes — про другое: про оркестрацию тысяч контейнеров на сотнях машин как единой системы.
Помню, как в одном проекте мы честно пытались жить на голом Docker Swarm. Пока сервисов было 15-20, ручное управление ещё работало. Когда перевалили за полсотни, начались ночные звонки: «падает балансировка», «отжирает память на третьем хосте», «мы не можем понять, кто кого зовёт». Kubernetes решает ровно эти проблемы — и делает это автоматически.
Архитектура: что под капотом
Кластер Kubernetes состоит из двух логических частей: Control Plane (мозг) и Worker Nodes(руки). Визуально это выглядит так:

API Server — единственная точка входа. Всё, что вы делаете через kubectl или через CI/CD-пайплайн, проходит через него. Scheduler решает, на каком узле запускать новый под, анализируя доступные ресурсы. Controller Manager — непрерывно сверяет текущее состояние кластера с желаемым: если вы заявили три реплики сервиса, а упала одна, контроллер мгновенно запустит новую. etcd — распределённое key-value хранилище, где хранится всё состояние кластера. Потеряете etcd без бэкапа — потеряете кластер.
На стороне Worker Nodes работает kubelet — агент на ноде, который отслеживает объекты Pod в API Server и приводит запущенные контейнеры к описанному состоянию. kube-proxy реализует сетевую модель Service (iptables/ipvs), обеспечивая маршрутизацию трафика к подам.
Спросите любого SRE, который поднимал прод-кластер с нуля: самая болезненная точка — это не приложения, а настройка Control Plane под высокую доступность. Три мастер-ноды, распределённый etcd, правильный load balancing перед API Server — без этого 99.9% uptime остаются фантазией.
Абстракции, в которых стоит разобраться раньше, чем случится прод
Документация Kubernetes огромна. Но есть несколько абстракций, без которых не получится даже стартануть. Вот мой «прожиточный минимум»:
Pod — минимальная единица развёртывания в Kubernetes: группа из одного или нескольких контейнеров, которые работают в рамках одной ноды и разделяют сеть и тома (volumes). Если вам кажется, что «один контейнер на под» — это избыточно, вспомните sidecar-паттерн: контейнер с приложением и рядом контейнер с прокси Envoy для service mesh. Вот тут pod раскрывается по-настоящему.
Service — стабильный сетевой endpoint для группы подов. Под может умереть и возродиться с новым IP, но Service предоставляет стабильный ClusterIP и DNS-имя на время своего существования. Без этого микросервисы просто не смогли бы найти друг друга. В моей практике был случай, когда команда разработки пыталась хардкодить IP подов в конфигах. После третьего перезапуска кластера они пришли к нам со словами «у нас всё сломалось». Service — это не опция, это базовая гигиена.
Deployment — декларативное описание желаемого состояния приложения: сколько реплик, какой образ, какие ресурсы. Вы говорите: «Хочу три пода с версией 1.2.0», и Kubernetes делает всё, чтобы это держалось, даже если ноды выходят из строя. Именно через Deployment работает механизм rolling update — постепенная замена старых подов новыми без даунтайма.
Namespace — логическая изоляция внутри кластера. Не путать с аппаратной изоляцией — это скорее organisational unit. Прод, стейджинг, дев должны жить в разных неймспейсах как минимум. Видел проекты, где всё валилось в default, а потом удивлялись, почему тестовый скрипт положил продовую базу.
Вот как выглядит типичный процесс от подачи команды до запуска пода (рис. 3):

Из этой диаграммы видно, что Kubernetes работает не по командам «сделай то-то», а по декларативному принципу. Разработчик или CI/CD-пайплайн заявляет желаемое состояние (три реплики Deployment), а дальше кластер сам распределяет ответственность: Scheduler выбирает подходящую ноду, kubelet через container runtime скачивает образ из реестра и запускает контейнер. Главная мысль: пользователь не указывает, на какой именно ноде запускать поды — Kubernetes берёт это на себя, постоянно сверяя реальное состояние с желаемым.
История, которая отрезвляет: миграция Tinder на Kubernetes
Ничто так не учит, как чужой production-опыт. В 2018–2019 годах инженерная команда Tinder провела полную миграцию платформы на Kubernetes, и это не был безболезненный переезд.
Исходная ситуация: более 200 микросервисов, написанных на Node.js, Java, Scala и Go, работали на EC2-инстансах с ручным масштабированием. Каждый новый инстанс поднимался минутами; при всплесках трафика команда физически не успевала реагировать. Деплой требовал координации нескольких человек и занимал часы.
Решение: контейнеризация всех сервисов, развёртывание Kubernetes-кластера с использованием инструментов автоматизации для AWS, переход на полностью автоматизированные деплой-пайплайны. Результат — кластер из 1 000 узлов, 15 000 подов и 48 000 запущенных контейнеров. Платформа Tinder теперь работает исключительно на Kubernetes.
Но дьявол в деталях. Когда кластер достиг «критической массы» в начале 2019 года, начались проблемы с DNS. CoreDNS в базовой конфигурации не справлялся с пиковыми DNS-запросами при массовом масштабировании подов, что потребовало тюнинга кеширования и масштабирования DNS-компонента. Инженерам пришлось внедрять кеширование на уровне нод и пересматривать архитектуру Service-объектов. Ещё один неочевидный момент: для 30+ репозиториев с разными языками команда построила универсальную систему сборки с паттерном «Builder Container», которая гарантировала идентичность окружения на дев-стендах и в проде.
Важно понимать: Tinder не просто «включил Kubernetes и всё поехало». Потребовался почти год методичного переноса сервисов и постоянного мониторинга. Зато теперь кластер держит нагрузку в десятки миллионов активных пользователей, а время деплоя сократилось.
Вывод, который я вынес для себя: Kubernetes не прощает «старта по-быстрому». Он требует инвестиций в компетенции команды до того, как вы выкатите первый под в прод!
Немного практики в тему — пройдите вступительный тест по Kubernetes и узнаете, есть ли пробелы в знаниях. |
Best Practices: что работает в реальных командах
На основе опыта команд вроде Tinder, а также рекомендаций CNCF и ведущих провайдеров, вот практики, которые я считаю обязательными:
Ресурсные requests и limits — не опция, а must. Без них один «прожорливый» под может положить всю ноду. В FinTech я видел, как отсутствие limits на Java-сервис вызывало каскадное вытеснение других подов при пиковой нагрузке. Правило простое: requests = гарантированный минимум, limits = «дальше не лезь».
Liveness и Readiness probes. Kubernetes должен знать, жив ли ваш контейнер (liveness) и готов ли он принимать трафик (readiness). Без readiness-пробы трафик льётся на ещё не стартовавшее приложение; без liveness-пробы подвисший контейнер висит вечно. В одном из проектов мы потратили два дня, выясняя, почему балансировщик шлёт запросы на полумёртвые поды — ответ был в отсутствии readinessProbe.
Строгий RBAC и Network Policies. Минимальные привилегии для каждого сервисного аккаунта. Согласно опросам CNCF, лишь 9% организаций имеют документированные процессы безопасности для cloud-native, а 85% требуют более безопасных значений по умолчанию в Kubernetes. Wildcard-доступы («*») должны вызывать аллергию, как пароли в открытом виде.
GitOps как единственный источник истины. Весь desired state кластера — в Git. Никаких ручных правок через kubectl edit в проде. ArgoCD или Flux синхронизируют репозиторий с кластером автоматически. Это спасает от ситуации «я поправил, но забыл записать».
Метрики, алерты, трейсы. Минимальный стек: Prometheus + Grafana для метрик, Loki для логов, Tempo или Jaeger для распределённой трассировки. Без этого вы летите вслепую.
Что остаётся за кадром и о чём поговорим на открытом уроке
Я сознательно не касаюсь в этой статье таких тем, как настройка автомасштабирования (HPA/VPA), service mesh на базе Istio, управление секретами через External Secrets Operator и построение инфраструктурной платформы на базе Kubernetes. Это те темы, где «дьявол в деталях» проявляется особенно остро, и именно их мы разберём на открытом уроке OTUS.
Если вы дочитали до этого места и чувствуете, что хотите не просто «знать, что такое под», а уметь проектировать платформу, которая выдержит прод — приходите. Урок бесплатный, нужно только зарегистрироваться. Он пройдёт 18 мая в 20:00 в рамках курса «Инфраструктурная платформа на основе Kubernetes», где мы вместе с практикующими инженерами разбираем реальные кейсы — от настройки кластера до эксплуатации под нагрузкой.
Хороший инженер не тот, кто знает все команды kubectl наизусть. Хороший инженер — тот, кто понимает, почему Kubernetes поступает так, а не иначе, и может спроектировать систему, которая не развалится в три часа ночи. Если этот разбор показался вам полезным — буду рад видеть вас на уроке.
Полный список бесплатных уроков мая смотрите в дайджесте.