- PVSM.RU - https://www.pvsm.ru -
Главный прикол с 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 Hard Way [2]» и «Kubernetes Simple Way [3]»: там статьи разной степени упоротости. Поскольку на дворе — XXI век, можно попросить помочь и LLM, но это будет step-by-step-воспроизведение одной из этих двух инструкций.
Третий путь — пойти к облачному провайдеру и там найти managed-service для k8s, обычно выглядящий для пользователя как волшебная кнопка «Создать кластер Kubernetes». Жмакнули, подождали минут 10–15, и вам вываливается файлик с конфигом. А дальше наступает ступор. Смотрите на этот файлик и думаете: «Ну зашибись, а дальше-то что?»
Мой личный совет: прежде чем лезть в облака или мучиться со своими серверами, поставьте себе на ноут Minikube. Это такая песочница, маленький Кубер на одной машине. Погоняйте его, потыкайте палочкой, разберитесь с базовыми понятиями: что такое Pod, Service, Deployment — вот это всё. Освойте kubectl — это главная команда для общения с кластером. Вот когда вы через это пройдёте, тогда и Managed Service в облаке станет в разы понятнее, и вы будете знать, что делать с этим загадочным admin.conf.
Итак, вариантов три с половиной:
Последний способ — запустить отдельный контейнер в контейнерном
Как ставить
На какую ОС ставить ноды
Если нет особых требований к безопасности или специфике, то начинайте с обычной Ubuntu LTS — не ошибётесь.
Container Runtime
Рекомендация: начинайте с 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 может перестать работать или перейти в состояние «Только для чтения». Там лучше разбираться руками.
В целом нет ничего хуже, чем развал кластера. В этой ситуации придётся долго и весело танцевать с бубном, если у вас не настроены итеративные бэкапы.
Ещё варианты:
Вы можете определить разные «классы» хранения (StorageClass), например, fast-ssd, slow-hdd, cloud-premium. А потом в манифесте для вашего приложения (в PersistentVolumeClaim) вы просто указываете имя нужного класса. Кубер через CSI-драйвер сам создаст диск нужного типа в соответствующем бэкенде (Ceph, облако, etc.). Это позволяет абстрагироваться от конкретной реализации хранилища.

Если диски ещё более-менее понятны, то тут спотыкаются даже опытные админы. Сеть в Кубере — это, пожалуй, одна из самых сложных тем. Вам точно понадобятся хотя бы базовые знания сетей (IP-адресация, маршрутизация, файрволы).
Kubernetes создаёт свою собственную виртуальную сеть поверх вашей физической (или облачной) сети. Каждый под (контейнер) получает свой IP-адрес в этой виртуальной сети. И поды, запущенные на разных физических нодах, должны иметь возможность общаться друг с другом по этим виртуальным IP. Чтобы эта магия работала, нужно выбрать и установить CNI-плагин (Container Network Interface). Это такой софт, который и отвечает за настройку сети для подов. Наши фавориты:
В зависимости от выбранного CNI и вашей инфраструктуры вам может потребоваться разбираться с BGP, VXLAN, IPIP-туннелями, настройкой маршрутов и файрволов. Сеть — это то место, где можно застрять надолго. Как сказал один наш сетевик, когда разбирался с какой-то проблемой: «По идее должно быть так, но хрен его знает, иди копай». Эта фраза будет преследовать вас примерно везде по мере реализации.
«Я запустил Nginx в поде, как мне его открыть в браузере?»
В Кубере есть специальная штука — Service. Это абстракция, которая даёт постоянный IP-адрес и DNS-имя для группы подов (например, для всех реплик вашего веб-сервера) и умеет балансировать трафик между ними.
Типы сервисов:
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 и ConfigMaps вашему приложению как переменные окружения для контейнера или как файлы, смонтированные в определённую директорию внутри контейнера.
Конечно, ваше приложение должно быть готово к этому. Оно должно уметь читать конфигурацию и секреты из переменных окружения или из файлов по указанным путям, а не из своего config.ini, лежащего рядом с бинарником. Часто это требует доработки кода приложения.
Но идеальный сценарий — это когда, например, кластер Cassandra создаётся автоматически через оператор типа k8ssandra, и приложение берёт креды для доступа из секрета, созданного оператором при запуске кластера. Ни в БД, ни в приложение ручками их никто не прокидывает.
Аутентификация и авторизация
В вашем кластере наверняка будут работать разные люди: DevOps/SRE, разработчики команды А, разработчики команды Б, может быть, QA-инженеры… Кто может деплоить приложения, кто может смотреть секреты, кто может удалять ноды?
Вот мы и приехали к той самой волшебной части. Работать с кластером Kubernetes без настроенной системы мониторинга и логирования — это посадить админом слепого котёнка.
Метрики:
А я предупреждал )
Логи:
Это, кстати, значит, что логи должны быть структурированными, чтобы их было легко парсить и искать по ним. Вероятно, тут вам ещё раз придётся вернуться к разработке приложения и навести порядок в том, как оно кладёт логи под себя.
Трассировка. Если у вас микросервисная архитектура, то один запрос пользователя может проходить через десяток разных сервисов. Чтобы понять, где именно возникла задержка или ошибка, нужна распределённая трассировка. Инструменты: Jaeger, Zipkin, Tempo.
Конечно, приложения должны уметь принимать и передавать дальше специальные заголовки (trace ID, span ID) и отправлять информацию о своих операциях (спанах) в коллектор трейсов. Это тоже требует доработки кода.
Ну что, база есть, доступ настроен, всё видно. Теперь можно и фишками обмазаться.
Устали поднимать руками и настраивать PostgreSQL, Kafka, Redis, Elasticsearch в Кубере? Следить за их состоянием, бэкапами, обновлениями? Для этого придумали операторов. Оператор — это, по сути, ваш кастомный контроллер внутри Кубера, который знает, как управлять определённым типом сложного приложения. Он расширяет API Кубера с помощью Custom Resource Definitions.
Работает это так:
Существует огромное количество готовых операторов от сообщества и вендоров для баз данных, очередей, мониторинга, CI/CD — да чего угодно! Это очень мощный механизм расширения Кубера. Для совсем уж специфичных внутренних систем можно даже написать свой оператор (но это уже высший пилотаж).
Автомасштабирование — одна из главных фишек Кубера, ради которой его часто и внедряют.
Кстати, тут надо передать пламенный привет некоторым российским облакам. У них часто есть довольно смешные лимиты на максимальное количество нод в одном Managed-кластере: где-то — 100 (привет, ТаймВеб), где-то — вообще 32 (Яндекс). А Кубер, на минуточку, сам по себе спокойно тянет 5 000 нод в кластере и 150 тысяч подов и даже не поперхнётся (по официальным тестам). У ВК вроде лимит побольше — 500 нод, у Сбера — 249 (хотя в доке пишут, что 500). Всё равно не 5 000. У нас в H3LLO CLOUD мы постарались эту проблему решить и даём возможность строить реально большие кластеры, близкие к максимальным возможностям Кубера.

Думаете, это конец?
Нет, это начало.
Развернули кластер, настроили сеть, сторадж, мониторинг? Поздравляю! Вы прошли… ну, скажем, разминку.
Короткий анонс. Приложения должны быть готовыми жить в динамичной эфемерной среде Кубера. Почитайте про 12-factor app [5] — это мастхэв. Приложение должно:
Вам нужны конвейеры, которые будут автоматически:
Инструментов для этого — море: Jenkins, GitLab CI, GitHub Actions, Tekton, Argo CD, Flux…
В идеальном розовом мире единорогов ваши разработчики вообще не должны знать слова «Kubernetes». Они просто пишут код, коммитят в Git, а дальше некая «платформа» сама всё собирает, тестирует и выкатывает куда надо. Нажал кнопку — получил фичу в проде. Достичь такого уровня абстракции — это Грааль платформенного инжиниринга. Это требует не только зрелого Кубера со всеми обвесами, но и глубокого понимания ваших приложений, процессов разработки и кучи инструментов поверх Кубера (часто это называют Internal Developer Platform). Это долгий и сложный путь.
А оно вообще того стоит? Если у вас реально сложная, большая, динамичная система, которая должна быть отказоустойчивой, масштабироваться под нагрузкой, часто обновляться без простоя, то однозначно — ДА, стоит. Головной боли на старте будет много, но потом вы получите такие гибкость, скорость и надёжность, которых другими путями добиться очень сложно, если вообще возможно. Вы реально сможете выкатывать фичи быстрее и спать спокойнее (но это неточно).
Если вы прочитали всё это и подумали: «Мама дорогая, да я в этом никогда не разберусь!», но при этом фишки Кубера вам нужны — не отчаивайтесь. Есть решения, которые берут на себя большую часть этой боли:
Для старта — Minikube.
Запуск Кубера без заморочек — kubespray [6].
Концепции Кубера из первоисточника — курим доку. Начать лучше с туториала [7], а потом читать Concepts [8] и Tasks [9].
Хорошая книга — Production Kubernetes [10]. Есть на русском [11].
Глубже по сетям — Networking and Kubernetes [12]. Тоже есть на русском [13].
GUI для Кубера — Lens [14].
The Twelve-Factor App [15].
Жирнющие бесплтаные лимиты на облачные сервисы на целый год, включая Managed Kubernetes — H3LLO.CLOUD. [16]
Не менее щедрые лимиты на платформу для запуска приложений в контейнере — L1veStack [17].
Автор: km1337
Источник [18]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/virtualizatsiya/417400
Ссылки в тексте:
[1] мышление: http://www.braintools.ru
[2] Kubernetes Hard Way: https://github.com/kelseyhightower/kubernetes-the-hard-way
[3] Kubernetes Simple Way: https://kubespray.io/#/docs/getting_started/setting-up-your-first-cluster%20-%20%D1%8D%D1%82%D0%BE%20Easy%20Way
[4] хостинге: https://www.reg.ru/?rlink=reflink-717
[5] 12-factor app: https://12factor.net
[6] kubespray: https://kubespray.io/#/
[7] туториала: https://kubernetes.io/docs/tutorials/
[8] Concepts: https://kubernetes.io/docs/concepts/
[9] Tasks: https://kubernetes.io/docs/tasks/
[10] Production Kubernetes: https://www.oreilly.com/library/view/production-kubernetes/9781492092292/
[11] Есть на русском: https://bhv.ru/product/kubernetes-na-praktike/
[12] Networking and Kubernetes: https://www.oreilly.com/library/view/networking-and-kubernetes/9781492081647/
[13] Тоже есть на русском: https://bhv.ru/product/kubernetes-i-seti-mnogourovnevyj-podhod/?srsltid=AfmBOor2txX-FVxwBHfkegy7mTLH325bgI4YgoFMtip4KIyVNrmvV5fY
[14] Lens: https://k8slens.dev
[15] The Twelve-Factor App: https://12factor.net/
[16] H3LLO.CLOUD.: https://beta.h3llo.cloud/?utm_source=habr&utm_medium=post&utm_campaign=dont-touch-kubernetes
[17] L1veStack: https://l1vestack.ru/?utm_source=habr&utm_medium=post&utm_campaign=dont-touch-kubernetes
[18] Источник: https://habr.com/ru/companies/h3llo_cloud/articles/902188/?utm_source=habrahabr&utm_medium=rss&utm_campaign=902188
Нажмите здесь для печати.