
Kubernetes: как устроен кластер и когда он действительно нужен
Подробно разбираем Kubernetes: control plane, nodes, Pods, Deployments, Services, сеть, хранилища, обновления, отказоустойчивость и эксплуатационные затраты.
Содержание
Kubernetes — платформа для запуска контейнерных приложений на группе серверов. Вы описываете желаемое состояние: какой образ запустить, сколько копий нужно, какие порты открыть и сколько ресурсов выделить. Контроллеры Kubernetes сравнивают это описание с фактическим состоянием и стараются устранить расхождение.
Главная ценность Kubernetes не в команде запуска контейнера. Он координирует множество изменений: размещает экземпляры приложения на доступных узлах, пересоздаёт упавшие, постепенно обновляет версию, даёт им стабильные сетевые имена и подключает хранилища. За это приходится платить сложностью самой платформы.
Задача, которую решает оркестратор
На одном сервере приложение можно запустить через systemd или Docker Compose. Пока сервисов мало, такой вариант легче понять и восстановить. Сложности появляются, когда экземпляры распределены по нескольким машинам:
- нужно выбрать узел, где достаточно процессора и памяти;
- после отказа машины требуется запустить копию на другой;
- новая версия должна заменить старую без одновременного простоя всех экземпляров;
- внутренним сервисам нужен стабильный адрес, хотя контейнеры пересоздаются;
- секреты и настройки приходится передавать одинаковым способом;
- команды должны видеть, кто и когда изменил рабочую среду.
Систему, которая решает эти задачи по общим правилам, называют оркестратором. Kubernetes — один из оркестраторов, а кластер — набор управляющих и рабочих машин, связанных его API и сетью.
Control plane принимает решения
Управляющую часть кластера называют control plane. Она не обслуживает пользовательский HTTP-запрос сайта напрямую. Её компоненты хранят описание объектов и принимают решения о размещении.
API server — центральная точка управления. Команда kubectl, контроллеры и внешние системы обращаются к Kubernetes API. Проверка личности, прав и допустимости объекта происходит на этом пути.
etcd — распределённое хранилище ключей и значений, где находится состояние кластера. Потеря его данных означает потерю описания объектов. Резервная копия обычных файлов приложений не заменяет backup etcd.
scheduler выбирает рабочий узел для нового Pod. Он учитывает запросы ресурсов, ограничения размещения, доступность томов и другие правила.
controller manager запускает контроллеры. Каждый контроллер наблюдает за частью состояния: например, поддерживает нужное количество реплик. Это цикл согласования, а не однократный сценарий установки.
В production control plane сам должен быть доступен при отказе одной машины. Управляемый Kubernetes переносит значительную часть этой работы на провайдера, но не снимает ответственность за workloads, права доступа, сетевые правила и данные приложений.
Node запускает рабочую нагрузку
Рабочую машину называют node. На ней действуют как минимум:
kubeletполучает назначение Pod и следит за их состоянием;- container runtime создаёт и запускает контейнеры;
- сетевой компонент реализует связь Service и Pod согласно выбранной сетевой схеме.
Kubernetes не планирует «контейнер на сервер» напрямую. Минимальной планируемой единицей является Pod. В Pod находится один основной контейнер или несколько тесно связанных контейнеров, которым нужны общий сетевой адрес и общие тома.
Pod считается расходуемым. При пересоздании он может получить другой IP и оказаться на другом node. Поэтому базу данных нельзя бездумно хранить только во внутреннем слое файловой системы контейнера. Долгоживущие данные подключают через persistent volume или выносят в управляемое хранилище.
Почему Pod редко создают вручную
Один вручную созданный Pod не обеспечивает обновление и восстановление нужного числа копий. Для stateless-приложения обычно создают Deployment. Он управляет ReplicaSet, а тот поддерживает заданное количество Pod.
Stateless означает, что конкретный экземпляр не хранит незаменимое пользовательское состояние у себя. Запрос можно отправить любой готовой реплике, а данные находятся в общей базе или внешнем хранилище.
Ниже — учебное описание Deployment. Оно не готово для production: образ, ресурсы, проверки и политика безопасности должны соответствовать реальному приложению.
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-api
spec:
replicas: 3
selector:
matchLabels:
app: catalog-api
template:
metadata:
labels:
app: catalog-api
spec:
containers:
- name: application
image: registry.example.com/catalog-api:1.8.2
ports:
- containerPort: 8080
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
memory: "512Mi"
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 10
replicas: 3 задаёт три желаемые копии. Label app: catalog-api связывает Deployment с его Pod. requests сообщает scheduler минимально планируемые CPU и память; значение 200m означает 0,2 ядра. Memory limit ограничивает память контейнера, но CPU limit здесь намеренно не задан: необходимость такого ограничения оценивают по профилю нагрузки.
Readiness probe обращается к /ready. Пока проверка не проходит, Pod не должен получать трафик через Service. Этот адрес обязан проверять готовность зависимостей, необходимых для обслуживания запроса, но не выполнять тяжёлую диагностику.
Применение такого файла меняет кластер, поэтому сначала работайте в учебном namespace и проверьте текущий контекст kubectl. Ошибка контекста — частая причина изменения не той среды.
Service отделяет клиента от Pod
IP-адреса Pod меняются, а приложению нужен стабильный способ обращения. Объект Service выбирает Pod по labels и предоставляет постоянное DNS-имя и виртуальный адрес внутри кластера.
apiVersion: v1
kind: Service
metadata:
name: catalog-api
spec:
selector:
app: catalog-api
ports:
- name: http
port: 80
targetPort: 8080
Клиент внутри того же namespace обращается к catalog-api:80, а Service направляет запрос одному из готовых Pod на порт 8080. Если selector не совпадает с labels, Service существует, но не имеет endpoint и трафик не доходит до приложения.
Service типа ClusterIP доступен только внутри кластера. Для внешнего HTTP-трафика используют Gateway API, Ingress с установленным контроллером или Service типа LoadBalancer — выбор зависит от платформы. Сам объект Ingress без контроллера ничего не маршрутизирует.
Как Kubernetes выполняет обновление
При смене тега образа Deployment создаёт новый ReplicaSet и постепенно заменяет Pod. Параметры стратегии ограничивают, сколько дополнительных и недоступных реплик допустимо во время rollout.
Без readiness probe новая копия может получить трафик до окончания запуска. Без нескольких реплик обновление может оставить короткое окно недоступности. Если приложение несовместимо со старой схемой базы, плавная замена контейнеров не спасёт: миграции нужно проектировать так, чтобы старая и новая версии могли временно работать одновременно.
Состояние обновления проверяют из доверенного компьютера, уже настроенного для нужного кластера:
kubectl config current-context
kubectl -n production rollout status deployment/catalog-api
kubectl -n production get pods -l app=catalog-api -o wide
Первая команда показывает выбранный контекст. Не продолжайте, если имя кластера или пользователя неожиданное. Вторая ждёт итог rollout, третья показывает Pod и узлы размещения. Успех — rollout завершён, нужное число Pod имеет Ready, а старые реплики удаляются по стратегии.
Если rollout остановился, не перезапускайте все Pod. Сначала выполните kubectl -n production describe pod ИМЯ для новой реплики и прочитайте Events: там видны ошибки образа, планирования, тома и probe. Для возврата Deployment хранит историю ревизий, но откат образа не отменяет миграцию данных.
Liveness, readiness и startup отвечают на разные вопросы
Readiness probe отвечает: можно ли направлять экземпляру новые запросы? Неуспех убирает Pod из готовых endpoint, но не обязан перезапускать контейнер.
Liveness probe отвечает: застряло ли приложение так, что его нужно перезапустить? Если она зависит от временно недоступной внешней базы, сбой базы способен вызвать перезапуск всех экземпляров и ухудшить ситуацию.
Startup probe даёт медленно запускающемуся приложению время до включения остальных проверок. Она полезна, когда нормальный liveness-порог слишком короток для старта.
Probe проверяет наблюдаемое состояние процесса, а не качество бизнеса. Ответ 200 от /health не доказывает, что пользователь может оформить заказ. После rollout нужны внешние smoke-тесты и мониторинг.
Ресурсы влияют на размещение и стабильность
Scheduler опирается на requests, а не на случайное текущее потребление. Если requests занижены, на node помещается слишком много Pod. Если завышены, свободные ресурсы остаются неиспользованными, а новые Pod получают Pending.
При превышении memory limit процесс контейнера может быть завершён из-за нехватки памяти. CPU обычно ограничивается иначе: контейнер получает меньше процессорного времени, что проявляется ростом задержки. Причину отличают по состоянию Pod, событиям и метрикам, а не по одному слову «тормозит».
Рабочие узлы также расходуют ресурсы на операционную систему, kubelet, сетевой плагин и системные Pod. Нельзя планировать пользовательские requests на все 100% физической памяти.
Сеть, DNS и сетевые политики
Каждый Pod получает адрес в кластерной сети. Реализацию предоставляет CNI-плагин — сетевой компонент, который Kubernetes вызывает через стандартный интерфейс. Выбор плагина влияет на маршрутизацию, политики и наблюдаемость.
По умолчанию наличие разных namespaces не обязательно изолирует трафик. Для ограничения соединений используют NetworkPolicy, но только если сетевой плагин её поддерживает. Политика должна разрешать DNS и необходимые зависимости; иначе приложение может потерять разрешение имён.
Для исходного IP посетителя путь через внешний балансировщик, Ingress и Service создаёт несколько промежуточных точек. Доверять X-Forwarded-For можно только после настройки списка доверенных proxy. Общий принцип разобран в статье об исходном IP за Nginx.
ConfigMap, Secret и хранилища
ConfigMap хранит несекретную конфигурацию. Secret предназначен для чувствительных значений, но его название не означает автоматическое шифрование в etcd. Нужно отдельно включить шифрование данных покоя, ограничить RBAC, доступ Pod и журналы.
Секрет в переменной окружения удобен, но остаётся в окружении процесса до перезапуска. Монтируемый файл можно обновлять иначе, однако приложение должно перечитать его. Внешний secret manager добавляет управление жизненным циклом, но не отменяет права внутри кластера.
PersistentVolume отделяет запрос хранилища от конкретной реализации. Доступные режимы, snapshots и поведение при переносе Pod зависят от CSI-драйвера и поставщика. StatefulSet даёт устойчивые имена и порядок для stateful-нагрузок, но не делает базу данных отказоустойчивой автоматически.
Что Kubernetes восстанавливает, а что нет
Если контейнер завершился, kubelet может его перезапустить. Если node пропал, контроллер создаст замену Pod на другом доступном node. Это самовосстановление желаемого количества экземпляров.
Но Kubernetes не исправляет:
- ошибку, одинаково присутствующую во всех репликах;
- повреждённые данные в общем хранилище;
- неверный Secret или ConfigMap;
- исчерпание ресурсов всего кластера;
- отказ единственной базы или внешнего DNS;
- потерю etcd без пригодной резервной копии.
Высокая доступность появляется только после анализа всех общих зависимостей. Три Pod на одном node не переживут отказ этого node. Три node в одной зоне не защищают от отказа зоны. Разнос по зонам, topology constraints и бюджеты disruption нужно согласовать с возможностями хранилища и стоимостью.
Эксплуатация важнее первого запуска
До production определите:
- кто обновляет control plane и nodes;
- как проверяется совместимость API и addons;
- где хранятся manifests и кто одобряет изменения;
- как резервируются etcd и данные приложений;
- какие логи, метрики и события сохраняются вне Pod;
- как ограничены права людей, ServiceAccount и CI;
- как восстанавливается кластер и сколько это занимает;
- какой запас ресурсов нужен при отказе node и обновлении.
Мониторить нужно не только CPU. Важны Pending Pod, ошибки probe, перезапуски, заполнение томов, срок сертификатов, задержка API server и состояние nodes. Основы связки метрик разобраны в статье о Prometheus и Grafana.
Когда Kubernetes оправдан
Платформа подходит, когда организация действительно использует её общие возможности: много сервисов и команд, несколько сред, регулярные релизы, автоматическое масштабирование, единые политики и потребность переносить workloads между узлами.
Kubernetes преждевременен, если один человек обслуживает несколько контейнеров на одном VPS, нет тестов, мониторинга и процедуры восстановления. В таком случае Docker Compose или systemd оставляют меньше скрытых частей и быстрее диагностируются.
Правильный вопрос не «сколько контейнеров нужно для Kubernetes», а «какие операционные проблемы он решит и есть ли команда, способная поддерживать саму платформу». Если ответ сводится к модному названию, дополнительные контроллеры, сеть и хранилище только увеличат число отказов.
Источники
Самопроверка
Проверьте, что материал усвоен
Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.
Разбираем коротко
Частые вопросы
Kubernetes заменяет Docker?
Нет. Kubernetes управляет контейнерными workloads на группе машин, а образы и контейнеры запускает совместимая container runtime. Docker может использоваться для сборки образов, но кластеру не требуется Docker Engine.
Нужен ли Kubernetes для сайта на одном VPS?
Обычно нет. Один сервер с systemd или Docker Compose проще обновлять, резервировать и диагностировать. Kubernetes оправдан, когда несколько сервисов и команд требуют общей платформы, автоматического размещения и масштабирования.
Обеспечивает ли несколько реплик полную отказоустойчивость?
Нет. Реплики помогают только при независимом размещении, исправных проверках готовности и отсутствии общей точки отказа в сети, хранилище, базе данных и control plane.


