Блог ДоверьсяСервису
Kubernetes: как устроен кластер и создать первый Deployment
Kubernetes — открытая платформа оркестрации контейнерных приложений. Она принимает декларацию желаемого состояния, размещает контейнеры на узлах, следит за их работой, заменяет отказавшие экземпляры и помогает выполнять обновления. Для первого знакомства важно разделять образ, контейнер, Pod, Deployment и Service: каждый объект решает свою задачу.
Kubernetes — открытая платформа оркестрации контейнерных приложений. Она принимает декларацию желаемого состояния, размещает контейнеры на узлах, следит за их работой, заменяет отказавшие экземпляры и помогает выполнять обновления. Для первого знакомства важно разделять образ, контейнер, Pod, Deployment и Service: каждый объект решает свою задачу.
Главная идея: вы не запускаете контейнер на выбранном сервере вручную. Вы сообщаете Kubernetes, что приложению нужны, например, два экземпляра определенного образа. Контроллеры постоянно сравнивают фактическое состояние с желаемым и пытаются устранить расхождение.
Docker и Kubernetes — не конкуренты
Образ — пакет с приложением, библиотеками и конфигурацией запуска. Контейнер — изолированный процесс из образа. Docker дает инструменты сборки, распространения и локального запуска.
Kubernetes управляет workload в кластере. Он не собирает код и не требует Docker Engine на узлах: кластер запускает OCI-образ через совместимую container runtime.
Карточка Docker помогает изучить инструментальный контекст контейнеризации. Для Kubernetes критичен не бренд локального приложения, а корректный образ, доступный registry и совместимость среды выполнения.
Из чего состоит кластер
| Компонент | Роль |
|---|---|
| API server | Принимает запросы и предоставляет Kubernetes API |
| etcd | Хранит состояние и конфигурацию кластера |
| Scheduler | Выбирает подходящий node для нового Pod |
| Controller manager | Запускает контроллеры согласования состояния |
| Node | Виртуальная или физическая машина для workload |
| kubelet | Следит, чтобы назначенные Pod работали на node |
| Container runtime | Запускает контейнеры |
| Сетевые компоненты | Реализуют связь Pod и Service по модели кластера |
Control plane управляет состоянием, а worker nodes выполняют приложения. В учебном кластере роли могут быть на одной машине; в production резервируют общие зависимости.
Pod, ReplicaSet и Deployment
Pod — минимальный развертываемый объект Kubernetes. Он содержит один или несколько тесно связанных контейнеров с общей сетью и томами. Pod считается временным: его имя и IP могут измениться после пересоздания.
ReplicaSet поддерживает число одинаковых Pod. Deployment управляет ReplicaSet и обновлением stateless-приложения, обеспечивая самовосстановление и историю rollout.
Зачем нужен Service
Pod создаются и удаляются, их IP меняются. Service выбирает их по labels и дает стабильную точку доступа. ClusterIP служит внутренней связи, а другие типы публикации требуют отдельной сетевой политики.
Deployment не публикует приложение автоматически. containerPort документирует порт контейнера, но не создает внешний endpoint. Для первого теста можно использовать kubectl port-forward, а для постоянного доступа — Service и, при необходимости, Ingress или Gateway.
Декларативная модель
Объекты обычно описывают в YAML и отправляют через API командой kubectl apply. Манифест содержит apiVersion, kind, metadata и spec. Kubernetes сохраняет желаемое состояние и запускает контроллеры для его достижения.
Декларативный подход не означает мгновенного успеха. API может принять Deployment, но Pod останется Pending из-за нехватки ресурсов, ImagePullBackOff из-за registry или CrashLoopBackOff из-за ошибки приложения. После apply всегда проверяйте условия и события.
Что подготовить перед первым запуском
- учебный кластер или изолированный namespace в тестовом кластере;
kubectl, совместимый с Kubernetes API вашей среды;- активный context и право создавать объекты в namespace;
- контейнерный образ, доступный узлам;
- план хранения конфигурации и секретов;
- лимит ресурсов учебного workload;
- способ удалить созданные объекты после упражнения.
Проверьте текущую цель до выполнения команд:
kubectl config current-context
kubectl cluster-info
kubectl auth can-i create deployments --namespace demo
Не экспериментируйте в production-контексте с широкими правами.
Создаем отдельный namespace
kubectl create namespace demo
kubectl config set-context --current --namespace=demo
Namespace — область имен, а не полная граница безопасности. Для разделения нужны RBAC, NetworkPolicy, квоты и Pod Security. Снова проверьте context.
Манифест первого Deployment
Создайте файл deployment.yaml. Образ nginx:stable-alpine подходит для учебного примера; в рабочем процессе используйте собственный проверенный образ и фиксируйте digest, чтобы одно имя не начало указывать на другое содержимое.
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-web
labels:
app: demo-web
spec:
replicas: 2
selector:
matchLabels:
app: demo-web
template:
metadata:
labels:
app: demo-web
spec:
containers:
- name: web
image: nginx:stable-alpine
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 2
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 10
selector.matchLabels должен совпадать с labels шаблона Pod. Deployment использует селектор, чтобы определить принадлежащие ему экземпляры. Небрежные общие labels могут привести к пересечению объектов, поэтому применяйте согласованную схему имен.
Применяем и наблюдаем rollout
kubectl apply -f deployment.yaml
kubectl rollout status deployment/demo-web
kubectl get deployments,replicasets,pods -l app=demo-web
kubectl describe deployment demo-web
rollout status ждет готовности, get показывает объекты, а describe — условия и события. Создание объекта еще не гарантирует готовность приложения.
Категория контейнеров и Kubernetes полезна при выборе платформы, но команды и доступные интеграции зависят от конкретного кластера. Сначала проверьте версию API, документацию поставщика и ограничения политики.
Добавляем Service
Создайте service.yaml:
apiVersion: v1
kind: Service
metadata:
name: demo-web
spec:
selector:
app: demo-web
ports:
- name: http
port: 80
targetPort: http
type: ClusterIP
kubectl apply -f service.yaml
kubectl get service demo-web
kubectl get endpointslices -l kubernetes.io/service-name=demo-web
kubectl port-forward service/demo-web 8080:80
После port-forward приложение доступно на локальном адресе и порту 8080, пока команда работает. EndpointSlice должен содержать готовые адреса Pod. Если список пуст, проверьте совпадение selector и labels, а также readiness.
Readiness, liveness и startup probes
| Probe | Вопрос | Последствие ошибки |
|---|---|---|
| Readiness | Можно ли направлять трафик? | Pod убирается из готовых endpoints |
| Liveness | Нужно ли перезапустить контейнер? | kubelet перезапускает контейнер |
| Startup | Завершился ли долгий старт? | Защищает остальные probes до запуска |
Не проверяйте внешнюю базу через liveness: ее сбой вызовет перезапуски исправных контейнеров. Параметры probe выбирают по реальному времени старта.
Requests и limits
Requests помогают scheduler выбрать node с доступной емкостью. Limits ограничивают потребление контейнера средствами runtime и ОС. CPU может быть throttled, а превышение memory limit способно завершить процесс. Значения учебного Deployment не являются рекомендацией для вашего приложения.
Измерьте потребление под характерной нагрузкой. Отсутствие requests мешает планированию, а маленький memory limit создает перезапуски.
Обновление и откат
После публикации нового образа измените поле image в манифесте и снова выполните apply. Для разовой демонстрации можно использовать:
kubectl set image deployment/demo-web web=registry.example.com/demo-web@sha256:<digest>
kubectl rollout status deployment/demo-web
kubectl rollout history deployment/demo-web
kubectl rollout undo deployment/demo-web
RollingUpdate постепенно создает новые Pod и уменьшает старую ReplicaSet согласно стратегии. Откат возвращает шаблон Deployment, но не отменяет внешние миграции базы и несовместимые изменения данных. Планируйте совместимость версий отдельно.
ConfigMap и Secret
Некритичные параметры передавайте через ConfigMap, чувствительные — через Secret и систему управления секретами. Secret сам по себе не гарантирует шифрование во всех точках.
Не помещайте секреты в Git, shell history и логи. Ограничьте RBAC, настройте ротацию и защиту etcd.
Хранилище и stateful-приложения
Файловая система контейнера эфемерна. Если Pod пересоздан, локальные изменения могут исчезнуть. Для постоянных данных используют PersistentVolumeClaim и StorageClass, а для стабильной идентичности и порядка — иногда StatefulSet.
Deployment подходит stateless-приложениям. Для базы нужны хранилище, backup, восстановление, обновление и отказоустойчивость.
Базовая безопасность
- используйте минимальный образ из доверенного процесса сборки;
- фиксируйте digest и сканируйте образ до допуска;
- запускайте процесс не от root, если приложение это поддерживает;
- запрещайте повышение привилегий и лишние Linux capabilities;
- задавайте read-only root filesystem, когда возможно;
- ограничивайте ServiceAccount и RBAC;
- применяйте NetworkPolicy при поддержке сетевого плагина;
- не публикуйте Service наружу без необходимости;
- обновляйте кластер, nodes, runtime и образы;
- собирайте audit, события, логи и метрики.
Управляемый Kubernetes снимает часть эксплуатации control plane, но не ответственность за workload, RBAC, образы, секреты и сетевую экспозицию. Карточка Yandex Cloud показывает пример облачной платформы; границу ответственности уточняют в документации конкретного сервиса.
Как диагностировать неисправность
| Состояние | Первые проверки |
|---|---|
| Pending | Events, requests, taints, affinity, квоты и PVC |
| ImagePullBackOff | Имя образа, tag/digest, registry и imagePullSecrets |
| CrashLoopBackOff | Логи текущего и предыдущего контейнера, command, config |
| Running, но не Ready | Readiness endpoint, порт, timeout и зависимости |
| Service без endpoints | Selector, labels и готовность Pod |
| Rollout завис | Новый ReplicaSet, maxUnavailable, probes и емкость |
kubectl get pods -l app=demo-web
kubectl describe pod <pod-name>
kubectl logs <pod-name> -c web
kubectl logs <pod-name> -c web --previous
kubectl get events --sort-by=.metadata.creationTimestamp
События полезны для scheduler и kubelet, логи — для процесса приложения, метрики — для ресурсов. Не начинайте с удаления Pod: это может стереть симптомы и запустить такой же сбой снова.
Матрица готовности к production
Скоринг на 20 баллов
Поставьте 0, 1 или 2 балла по десяти направлениям: воспроизводимый образ, фиксированный digest, requests/limits, probes, конфигурация, секреты, least privilege, сеть, наблюдаемость и восстановление. Ноль — решение отсутствует, один — частично проверено, два — автоматизировано и протестировано.
0–7: только учебный стенд. 8–14: возможен ограниченный тест, но есть эксплуатационные пробелы. 15–20: база подготовлена к review, однако безопасность, емкость и отказоустойчивость все равно подтверждают нагрузочными и аварийными тестами. Критичная утечка секрета или отсутствие восстановления блокирует запуск независимо от суммы.
Очистка учебного окружения
kubectl delete -f service.yaml
kubectl delete -f deployment.yaml
kubectl delete namespace demo
Проверьте context: удаление namespace затрагивает все объекты внутри. Внешние балансировщики и диски могут иметь отдельный жизненный цикл.
Типичные ошибки
- создавать отдельный Pod вместо Deployment;
- использовать mutable tag в production;
- путать containerPort с публикацией Service;
- не задавать requests и копировать случайные limits;
- делать liveness зависимой от внешней системы;
- не проверять совпадение labels и selectors;
- хранить секреты в манифесте репозитория;
- считать namespace полноценной изоляцией;
- выполнять apply в неверном context;
- удалять Pod вместо анализа событий и логов;
- считать успешный rollout доказательством качества приложения;
- запускать stateful-систему без плана данных.
Чек-лист первого Deployment
- context, namespace и права проверены;
- образ доступен узлам и имеет понятное происхождение;
- selector совпадает с labels шаблона;
- задано нужное число replicas;
- requests и limits обоснованы;
- readiness отражает готовность к трафику;
- Service выбирает правильные Pod;
- rollout status завершен успешно;
- логи, события и endpoints проверены;
- путь обновления и отката понятен;
- секреты не попали в открытый YAML;
- созданные ресурсы можно безопасно удалить.
Частые вопросы
Нужно ли сначала изучить Docker?
Нужно понимать образ, контейнер, registry, порты, volume и переменные окружения. Глубокое знание всех Docker-инструментов не обязательно, но без основ контейнеризации ошибки Kubernetes трудно диагностировать.
Deployment запускает виртуальные машины?
Нет. Он управляет ReplicaSet и Pod с контейнерами на существующих nodes. Создание и масштабирование самих nodes выполняет инфраструктурный слой и его контроллеры.
Можно ли открыть приложение без Service?
Для диагностики можно обратиться к Pod или использовать port-forward, но IP Pod нестабилен. Service дает устойчивую абстракцию для группы экземпляров.
Почему replicas равно двум, а доступен один Pod?
Второй может быть Pending, не пройти readiness или не загрузить образ. Смотрите Deployment conditions, ReplicaSet, Pod events и доступную емкость.
Kubernetes сам делает резервную копию данных?
Нет. Он управляет объектами и workload, но backup приложений, баз, PersistentVolume и состояния control plane проектируется и проверяется отдельно.
Вывод
Kubernetes управляет желаемым состоянием контейнерных приложений: Deployment поддерживает и обновляет Pod, а Service дает им устойчивую сетевую точку. Первый успешный apply — только начало. Проверьте rollout, labels, endpoints, probes, ресурсы и события, затем зафиксируйте образ, ограничьте права и отрепетируйте обновление, откат и удаление. Так учебный манифест становится понятной основой для безопасного рабочего процесса.