Олег Марков
Гайд по запуску проекта на Kubernetes
Введение
Kubernetes — популярная платформа для оркестрации контейнеров, сегодня её используют для запуска самых разных приложений — от небольших сервисов до сложных распределённых систем. Если у вас уже есть контейнеризированное приложение (Docker-контейнеры), следующий логичный шаг — запуск его в Kubernetes, чтобы получить преимущества масштабирования, автоматизации и высокой доступности. В этом гайде я покажу пошагово, как запустить свой проект на Kubernetes — от подготовки окружения до деплоя и базового управления.
Здесь вы разберётесь, как работает базовый процесс развертывания, создадите основные манифесты, и познакомитесь с командами kubectl. Примеры будут максимально универсальными, для большей наглядности многие моменты иллюстрируются практическими фрагментами YAML и комментариями. Рассмотрим ключевые концепции Kubernetes (Pod, Deployment, Service, ConfigMap и др.), а также шаги мониторинга и масштабирования. По ходу изложения обращаю внимание на моменты, которые вызывают вопросы у новичков.
Что потребуется для запуска проекта в Kubernetes
Перед началом убедитесь, что у вас есть:
- Исходный код приложения, собранный в виде одного или нескольких Docker-образов и опубликованный в реестре (например, Docker Hub).
- Доступ к работе с Kubernetes-кластером. Можно воспользоваться локальным кластером (minikube, kind), кластером в публичном облаке (Yandex.Cloud, GKE, EKS, AKS) или корпоративным окружением.
- Установленная утилита
kubectl
— основной инструмент для управления Kubernetes.
Ниже приведу краткое описание установки minikube и kubectl для вашей локальной машины — это простой способ начать знакомство с Kubernetes.
Быстрый старт — локальный кластер с помощью minikube
Приложения часто тестируют на локальной машине, не заходя на крупные облака. Minikube — это минимальный Kubernetes, который запускается в виртуальной машине или контейнере.
Установка Minikube и kubectl
Для macOS:
brew install minikube
brew install kubectl
Для Ubuntu/Debian:
curl -sLO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
sudo snap install kubectl --classic
Запуск локального кластера
minikube start # Запускаем кластер
kubectl version --client # Проверяем, что kubectl установлен
kubectl get nodes # Смотрим список рабочих узлов
Теперь у вас есть свой кластер Kubernetes для первых экспериментов.
Подготовка Docker-образа приложения
Первый шаг — убедитесь, что у вас есть рабочий Docker-образ, размещённый в реестре (например, Docker Hub). Пример реализации Dockerfile для простого Python-сервиса:
# Официальный образ Python
FROM python:3.10-slim
# Копируем файлы приложения
WORKDIR /app
COPY . /app
# Устанавливаем зависимости
RUN pip install -r requirements.txt
# Открываем порт 8000 для приложения
EXPOSE 8000
# Команда для запуска сервиса
CMD ["python", "app.py"]
Проверьте, что собирается корректно и запускается командой (например, docker run -p 8000:8000 myuser/myapp:latest
).
Базовые сущности Kubernetes — краткий обзор
Прежде чем переходить к практике, кратко опишу основные сущности, которые понадобятся в маршруте развертывания:
- Pod — минимальная единица запуска, один или несколько контейнеров, которые работают совместно на одном узле и делят сетевой стек, хранилище.
- Deployment — объект, который определяет желаемое количество реплик Pod и управляет их созданием/обновлением/замещением (важен для автослучайных апдейтов образов).
- Service — определяет способ доступа к вашим Pod (через внутренний ClusterIP, внешний LoadBalancer или NodePort).
- ConfigMap и Secret — объекты для передачи переменных окружения, конфигураций и секретных данных внутрь контейнеров.
- Namespace — логическая изоляция ресурсов внутри кластера.
Теперь давайте создадим базовые манифесты для вашего приложения.
Создание Deployment-манифеста
Deployment — основа повторяемого развертывания контейнеров. Пример YAML для минимального сервиса:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app-deployment # Имя деплоймента
spec:
replicas: 2 # Запускаем две копии приложения
selector:
matchLabels:
app: demo-app # Критерий для выбора Pod
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: demo-app
image: myuser/demo-app:latest # Ваш контейнер (замените на свой)
ports:
- containerPort: 8000 # Порт приложения внутри контейнера
env:
- name: ENV_TYPE
value: "production" # Переменные окружения
Пояснения:
replicas
— сколько экземпляров приложения будет запущено (масштабирование по умолчанию).selector
— определяет, какие Pod подпадают под этот Deployment.- Блок
env
— позволяет прокинуть переменные окружения внутрь контейнера.
Сохраните этот манифест в файл, например, deployment.yaml
.
Создание манифеста Service
Чтобы сделать ваш сервис доступным внутри и/или снаружи кластера, требуется Service. Пример — NodePort (открывает порт на всех узлах):
apiVersion: v1
kind: Service
metadata:
name: demo-app-service # Имя сервиса
spec:
type: NodePort # Тип сервиса (ClusterIP, NodePort, LoadBalancer)
selector:
app: demo-app # Находит Pod, созданные нашим Deployment
ports:
- protocol: TCP
port: 8000 # Порт внутри кластера
targetPort: 8000 # Порт контейнера
nodePort: 30080 # Внешний порт на каждом узле (настраивайте при необходимости)
type: NodePort
полезен для локального тестирования с minikube.selector
должен совпадать с лейблом из Deployment.- Не указывайте лишние порты, если они не используются.
Применение манифестов и деплой приложения
Теперь задеплойте ваши манифесты в кластер. Kubectl применяет описанные объекты, автоматически создаёт нужное количество Pod и настраивает сервис.
kubectl apply -f deployment.yaml # Применяем Deployment
kubectl apply -f service.yaml # Применяем Service
kubectl get pods # Смотрим все Pod
kubectl get svc # Смотрим все сервисы
Проверьте статус Pod:
kubectl describe pods # Получаем подробности состояния всех Pod
Чтобы попасть внутрь Pod для отладки:
kubectl exec -it <имя-пода> -- /bin/sh
— Вместо <имя-пода>
подставьте имя конкретного Pod, например demo-app-deployment-xxxx.
Доступ к приложению
Для NodePort сервис в minikube доступ можно получить такой командой:
minikube service demo-app-service
Kubernetes автоматически пробросит ваш браузер по адресу, где сервис доступен снаружи.
Либо вручную можно узнать IP кластера:
minikube ip
# Затем открываете http://<этот-IP>:30080
Для сервисов типа LoadBalancer (на облачных платформах) Kubernetes выдаст внешний адрес после создания ресурса Service.
Использование переменных окружения и ConfigMap
Если ваш проект зависит от переменных конфигурации, их удобно хранить в Kubernetes в ConfigMap — отдельно от манифеста самого приложения. Например:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
ENV_TYPE: "production"
API_URL: "https://api.example.com"
В самом Deployment подключаете эти значения так:
envFrom:
- configMapRef:
name: app-config
Раздел envFrom
автоматически импортирует все пары ключ-значение из ConfigMap
в переменные окружения контейнера.
Здесь можно использовать Secrets для хранения токенов, паролей, ключей — принцип почти тот же, но содержимое шифруется и доступ к нему ограничивается.
Автоматическое обновление образа (Rolling Update)
Deployment по умолчанию использует стратегию Rolling Update. Это значит, что если пересобрать Docker-образ и поменять тег, Kubernetes сначала создаст новые Pod, а потом постепенно удалит старые.
Обновить Deployment на новый тег можно так:
kubectl set image deployment/demo-app-deployment demo-app=myuser/demo-app:NEW_TAG
- Вместо NEW_TAG указываете вашу новую версию контейнера.
- Новый Pod запускается, старый удаляется только после успешного старта нового.
Проверить прогресс обновления можно командой:
kubectl rollout status deployment/demo-app-deployment
Масштабирование приложения
Изменить количество экземпляров сервиса можно тремя способами:
- Отредактировать манифест и пересоздать ресурс.
- Выполнить команду:
kubectl scale deployment demo-app-deployment --replicas=5
- Включить автоскейлер:
Если у вас настроен Horizontal Pod Autoscaler:
kubectl autoscale deployment demo-app-deployment --cpu-percent=80 --min=2 --max=10
- При нагрузке Kubernetes будет увеличивать или уменьшать количество Pod в зависимости от загрузки процессора.
Работа с логами и мониторинг
Просмотреть логи приложения можно так:
kubectl logs <имя-пода>
Для нескольких Pod удобно:
kubectl logs -l app=demo-app --tail=100
- Флаг
-l app=demo-app
позволяет выбрать сразу все Pod c данным лейблом.
Для мониторинга состояния Pod, Deployment, Service:
kubectl get all # Показывает все основные ресурсы
kubectl get events # Показывает последние системные события (ошибки при деплое и др.)
Организация доступа: Ingress
Для роутинга HTTP-трафика по специальным доменам/поддоменам обычно используют объект Ingress.
Пример простого Ingress для теста в minikube:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-app-ingress
spec:
rules:
- host: demo-app.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-app-service
port:
number: 8000
Обратите внимание: Ingress-контроллер должен быть установлен в кластере.
Установить в minikube:
minikube addons enable ingress
Теперь можно обратиться к вашему приложению по адресу http://demo-app.local, добавив его в файл hosts вашей системы.
Работа с неймспейсами для изоляции
Если вы хотите запустить несколько окружений (dev, staging), используйте неймспейсы:
kubectl create namespace staging
kubectl apply -f deployment.yaml -n staging
kubectl apply -f service.yaml -n staging
— Так ресурсы одного окружения не пересекаются с другим.
Организация постоянного хранения данных: Volumes
Если ваше приложение должно хранить данные (например, база данных или файлы), используйте PersistentVolumeClaim (PVC).
Пример:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
В шаблоне Pod или Deployment указать подключение:
volumeMounts:
- mountPath: /data
name: storage
volumes:
- name: storage
persistentVolumeClaim:
claimName: app-pvc
— Теперь каталог /data внутри контейнера будет храниться на внешнем томе, даже после удаления Pod.
Типичные ошибки и отладка
Kubernetes довольно информативно сообщает об ошибках, но иногда сообщения сбивают с толку. Вот некоторые частые ситуации:
- Контейнер не стартует: проверьте логи (
kubectl logs
), убедитесь, что нет ошибок в образе или переменных окружения. - Service не находит Pod: проверьте, совпадают ли лейблы selector и labels.
- Приложение не доступно: убедитесь, что порты правильно проброшены (targetPort и port в Service), используйте
kubectl describe service
. - Pending статус Pod: обычно не хватает ресурсов или тома, проверьте
kubectl describe pod
.
Заключение
Вы познакомились с базовым процессом деплоя приложения в Kubernetes: от подготовки Docker-образа до развертывания и управления жизненным циклом через Deployment, Service, ConfigMap и дополнительные возможности вроде Volumes, Ingress и масштабирования. Теперь вы понимаете структуру манифестов, умеете запускать сервисы, организовывать доступ и отлаживать типичные проблемы. Kubernetes — мощная, но сложная система, поэтому совершенствуйте практические навыки и не стесняйтесь обращаться к официальной документации.
Частозадаваемые технические вопросы по теме и ответы
Как прокинуть секретные переменные окружения (API-ключи, пароли) в контейнеры Kubernetes?
Используйте объект Secret. Пример создания:
kubectl create secret generic my-secret --from-literal=SECRET_KEY=supersecret
Подключите secret к контейнеру в манифесте deployment.yaml:
envFrom:
- secretRef:
name: my-secret
Теперь SECRET_KEY
станет переменной окружения внутри контейнера.
Как удалить все ресурсы, относящиеся к одному проекту?
Если вы использовали отдельный namespace, достаточно удалить его:
kubectl delete namespace my-namespace
В ином случае удаляйте вручную:
kubectl delete deployment,service,configmap,secret -l app=demo-app
Флаг -l
удалит только ресурсы с нужным лейблом.
Что делать, если Pod постоянно перезапускается (CrashLoopBackOff)?
- Проверьте логи контейнера:
kubectl logs <имя-пода> --previous
- Проверьте настройки readiness и liveness probes (могут быть слишком строгими).
- Убедитесь, что все переменные окружения и зависимости на месте.
Как подключиться к базе данных или другому внешнему сервису из приложения внутри Pod?
Передайте внешний адрес через переменную окружения или в ConfigMap. Убедитесь, что сеть кластера разрешает доступ (с cloud-кластерами могут быть ограничения firewall, для локального — настройки сети вашей машины).
Как обновить только один контейнер в случае multi-container Pod/Deployment?
Выполните команду с указанием имени контейнера:
kubectl set image deployment/my-deployment <container-name>=myuser/image:tag
- Для multi-container укажите нужный контейнер в Deployment.
Если необходимо обновить несколько — укажите их через пробел.
Постройте личный план изучения Kubernetes до уровня Middle — бесплатно!
Kubernetes — часть карты развития DevOps
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Kubernetes
Лучшие курсы по теме

Kubernetes и Helm
Антон Ларичев
Docker и Ansible
Антон Ларичев