Антон Ларичев

Введение
Если вы уже работали с Docker и запускали контейнеры вручную, то рано или поздно столкнулись с вопросом: а как управлять десятками контейнеров в продакшне? Как перезапускать упавший контейнер, распределять нагрузку, обновлять приложение без простоя?
Kubernetes (или k8s) решает именно эти задачи. Это платформа оркестрации контейнеров, которую Google открыл в 2014 году. Сегодня она стала стандартом индустрии для запуска production-нагрузок.
В этой статье мы разберём ключевые концепции Kubernetes и запустим простое приложение в локальном кластере с помощью minikube.
Основные концепции Kubernetes
Прежде чем писать конфигурационные файлы, нужно понять, из чего состоит кластер Kubernetes.
Кластер
Кластер — это набор машин (узлов), на которых запускаются ваши приложения. Он делится на две части:
- Control Plane — управляет кластером: планирует запуск контейнеров, следит за состоянием системы
- Worker Nodes — рабочие узлы, где непосредственно работают ваши контейнеры
Pod
Pod — минимальная единица развёртывания в Kubernetes. Внутри пода может быть один или несколько контейнеров, которые всегда запускаются вместе на одном узле и делят сеть.
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
Однако поды напрямую почти не создают — для этого используют более высокоуровневые объекты.
Deployment
Deployment управляет группой одинаковых подов и гарантирует, что нужное количество реплик всегда запущено. Если под упадёт, Deployment автоматически создаст новый.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3 # хотим три копии приложения
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
Обратите внимание на секцию resources — всегда указывайте лимиты, иначе один контейнер может потребить все ресурсы узла.
Service
Поды имеют динамические IP-адреса, которые меняются при перезапуске. Service — стабильная точка доступа к группе подов. Он находит поды по лейблам и балансирует трафик между ними.
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app # ищем все поды с этим лейблом
ports:
- protocol: TCP
port: 80 # порт сервиса
targetPort: 80 # порт контейнера
type: ClusterIP # доступен только внутри кластера
Установка minikube и первый запуск
Для локальной разработки используем minikube — инструмент, который запускает одноузловой кластер прямо на вашей машине.
# Установка kubectl — CLI для управления кластером
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# Установка minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Запуск кластера
minikube start
# Проверка состояния
kubectl get nodes
После запуска вы увидите один узел в статусе Ready.
Деплой первого приложения
Создадим файл deployment.yaml и применим его:
# Применяем конфигурацию
kubectl apply -f deployment.yaml
# Смотрим статус подов
kubectl get pods
# Подробная информация о поде (полезно при ошибках)
kubectl describe pod my-app-xxxxxx
# Логи контейнера
kubectl logs my-app-xxxxxx
Применим также Service и проверим доступность:
kubectl apply -f service.yaml
# Для minikube открываем туннель к сервису
minikube service my-app-service
Масштабирование
Одна из ключевых возможностей Kubernetes — простое масштабирование:
# Увеличиваем количество реплик до 5
kubectl scale deployment my-app --replicas=5
# Смотрим, как создаются новые поды
kubectl get pods -w
Обновление образа без простоя
# Обновляем версию образа — Kubernetes сделает rolling update
kubectl set image deployment/my-app web=nginx:1.26
# Следим за процессом обновления
kubectl rollout status deployment/my-app
# Если что-то пошло не так — откат к предыдущей версии
kubectl rollout undo deployment/my-app
Namespace — изоляция окружений
Namespace позволяет логически разделить кластер. Удобно создавать отдельные namespace для dev, staging и production:
# Создаём namespace для разработки
kubectl create namespace development
# Деплоим приложение в конкретный namespace
kubectl apply -f deployment.yaml -n development
# Смотрим поды в namespace
kubectl get pods -n development
Частые ошибки
ImagePullBackOff — Kubernetes не может скачать образ. Проверьте имя образа, тег и доступность registry. Если используете приватный registry, нужен Secret с кредами.
CrashLoopBackOff — контейнер запускается и сразу падает. Смотрите логи: kubectl logs <pod-name> --previous покажет логи упавшего контейнера.
Pending-поды — поду не хватает ресурсов. Проверьте kubectl describe pod <name> — в секции Events будет причина. Часто решается снижением requests в конфигурации.
Отсутствие лимитов ресурсов — без limits один под может вытеснить остальные с узла. Всегда указывайте resources.limits.
Прямое редактирование подов — поды созданы Deployment-ом пересоздаются при изменении конфига. Всегда меняйте Deployment, а не под напрямую.
Заключение
Mы разобрали базовые строительные блоки Kubernetes: Pod, Deployment, Service и Namespace. Этого достаточно, чтобы запускать и обновлять приложения, масштабировать их и изолировать окружения.
Дальнейшие шаги для изучения: ConfigMap и Secret для конфигурации, Ingress для HTTP-маршрутизации, PersistentVolume для хранения данных, а также HorizontalPodAutoscaler для автоматического масштабирования по нагрузке.
Kubernetes поначалу кажется сложным, но его декларативный подход — описываем желаемое состояние, а система сама к нему стремится — делает управление инфраструктурой предсказуемым и воспроизводимым.






Комментарии
0