Kubernetes

Теория: Первый деплой

Установка kubectl

Первый деплой в Kubernetes начинается не с Pod'а и не с манифеста, а с инструмента управления. Для работы с кластером нужен kubectl — командная строка, через которую происходит всё взаимодействие с Kubernetes. Через kubectl система получает команды, применяет конфигурации и показывает текущее состояние объектов. Без него Kubernetes фактически недоступен, даже если сам кластер уже запущен.

Kubectl — это клиент, а не часть кластера. Он не поднимает Pod'ы и не хранит состояние. Он отправляет HTTP-запросы в API-сервер Kubernetes и получает ответы. Именно поэтому kubectl устанавливается на локальную машину, а не внутрь кластера.

Прежде всего необходимо установить Kubernetes. Это можно сделать по инструкции. После установки проверим, что всё работает:

kubectl version --client
kubectl cluster-info
kubectl config current-context

Если видите версию — kubectl готов к работе.

Подключение к кластеру

После установки kubectl сам по себе ещё ничего не умеет. Он не знает, к какому кластеру подключаться. Для этого используется конфигурационный файл ~/.kube/config. Этот файл играет роль адресной книги и пропуска одновременно. В нём хранится адрес API-сервера кластера, сертификаты или токены для аутентификации и информация о контекстах — с каким кластером и namespace вы работаете.

Minikube

Для учебных целей проще всего поднять локальный кластер через minikube. Установим его по инструкции

И запустим кластер:

minikube start

Minikube создаст виртуальную машину с Kubernetes и автоматически настроит kubeconfig. Первый запуск занимает несколько минут — скачивается образ и поднимается кластер.

Проверка подключения

kubectl cluster-info

Если видите адрес API-сервера и CoreDNS — кластер работает, можно двигаться дальше.

Проверка текущего контекста

Если у вас несколько кластеров или kubeconfig настраивался вручную, важно понимать, куда именно сейчас отправляются команды kubectl. Иначе легко работать не с тем кластером, который вы ожидаете.

kubectl config current-context
kubectl config get-contexts

Первая команда показывает активный контекст — текущий профиль подключения. Вторая выводит список всех контекстов и отмечает активным звёздочкой.

Манифест — описание желаемого состояния

Kubernetes не всегда управляется через графический интерфейс или SSH. Большая часть работы идёт через манифесты — файлы, в которых вы описываете, что хотите получить. Kubernetes читает манифест и приводит кластер к описанному состоянию. Вы не говорите «запусти контейнер», вы говорите «должен существовать вот такой Pod».

Манифесты пишутся на YAML. Вот минимальный пример для запуска Pod с nginx:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80

Разберём ключевые поля:

  • apiVersion: v1 — версия API Kubernetes, через которую создаётся объект. Pod — базовый объект, он существует с первой версии API.
  • kind: Pod — тип объекта. Kubernetes поддерживает десятки типов: Pod, Deployment, Service, ConfigMap. Здесь работаем с Pod напрямую.
  • metadata — метаданные объекта. Здесь обязательно только имя (metadata.name). Имя должно быть уникальным в пределах namespace.
  • spec — спецификация, что именно должно быть внутри Pod.
  • containers — список контейнеров. Даже если контейнер один, это всегда список.
  • name: nginx — имя контейнера внутри Pod. Используется в логах и при обращении к конкретному контейнеру.
  • image: nginx:1.27 — образ, из которого создаётся контейнер. Kubernetes скачает его из Docker Hub, если не указан другой registry.
  • ports — список портов, которые слушает контейнер. Это декларация для документации, она не открывает порт наружу.

Применение манифеста

Сохраните манифест в файл pod.yaml, затем выполните:

kubectl apply -f pod.yaml

Команда apply отправляет манифест в Kubernetes. Если Pod с таким именем не существует, он будет создан. Если существует — Kubernetes сравнит текущее состояние с манифестом и применит изменения.

Пример вывода:

pod/nginx created

Pod создан, но «создан» не значит «работает». Kubernetes только начал процесс: выбирает ноду, скачивает образ, запускает контейнер.

Namespace по умолчанию

Все команды kubectl работают в каком-то namespace. Если не указать явно, используется default. Ваш Pod сейчас создан именно там.

Namespace — это логическая изоляция внутри кластера. Разные команды, окружения или проекты могут жить в разных namespace и не мешать друг другу.

Частая ошибка: Pod существует, но kubectl get pods его «не видит». Причина — Pod в одном namespace, а команда выполняется в другом. Чтобы указать namespace явно:

kubectl get pods -n default
kubectl get pods -n kube-system

Пока вы работаете в default и не создавали других namespace, об этом можно не думать. Но когда что-то «пропадает» — первым делом проверяйте namespace.

Проверка статуса

kubectl get pods

READY 1/1 — внутри Pod один контейнер, и он готов. STATUS Running — Pod запущен. RESTARTS 0 — контейнер не перезапускался.

Если статус ContainerCreating — Kubernetes ещё скачивает образ. Подождите и повторите команду.

Если ImagePullBackOff или ErrImagePull — не удалось скачать образ. Проверьте имя и тег.

Подробная информация

Для деталей используйте describe:

kubectl describe pod nginx

Пример секции Events:

Events:
  Normal  Scheduled  1m   default-scheduler  Successfully assigned default/nginx to node-1
  Normal  Pulling    1m   kubelet            Pulling image "nginx:1.27"
  Normal  Pulled     45s  kubelet            Successfully pulled image "nginx:1.27"
  Normal  Created    45s  kubelet            Created container nginx
  Normal  Started    45s  kubelet            Started container nginx

Здесь видно всю историю: на какую ноду попал Pod, когда качался образ, когда запустился контейнер. Если что-то пошло не так, причина почти всегда в Events.

Как обратиться к запущенному nginx

Pod работает, но если вы попробуете открыть nginx в браузере — ничего не произойдёт. containerPort: 80 в манифесте — это декларация, а не открытие порта наружу. Pod по умолчанию доступен только внутри кластера и то только если знать его IP.

Для быстрой проверки используйте port-forward:

kubectl port-forward pod/nginx 8080:80

Теперь localhost:8080 на вашей машине ведёт на порт 80 внутри Pod. Откройте в браузере или выполните:

curl localhost:8080

Увидите стандартную страницу nginx. Port-forward — временное решение для отладки. Для постоянного доступа используется Service, но это тема отдельного урока.

Логи контейнера

kubectl logs nginx

Nginx пишет логи в stdout, Kubernetes их собирает. Пока запросов не было, логов может не быть.

Для нескольких контейнеров в Pod укажите имя:

kubectl logs nginx -c nginx

Стриминг логов в реальном времени:

kubectl logs nginx -f

Выполнение команд внутри контейнера

kubectl exec nginx -- ls /usr/share/nginx/html

Двойной дефис (--) отделяет аргументы kubectl от команды внутри контейнера.

Для интерактивного shell:

kubectl exec -it nginx -- /bin/bash

Флаги -it — interactive + tty. Для выхода введите exit. Если bash отсутствует, попробуйте /bin/sh.

Удаление Pod

kubectl delete pod nginx
kubectl delete -f pod.yaml

Kubernetes отправляет контейнеру SIGTERM. У процесса есть 30 секунд на корректное завершение. Если не успел — SIGKILL. Удаление Pod — это уничтожение объекта: после delete этого Pod больше не существует, и Kubernetes не создаст его заново, потому что никто этого не просит.

Почему Pod нельзя обновить на месте

Измените версию nginx в манифесте на nginx:1.26 и примените:

kubectl apply -f pod.yaml

Вы получите ошибку:

The Pod "nginx" is invalid: spec: Forbidden: pod updates may not change fields other than...

Большинство полей Pod нельзя изменить после создания. Для обновления нужно удалить и создать заново:

kubectl delete pod nginx
kubectl apply -f pod.yaml

Это одна из причин, почему в реальной работе Pod напрямую не создают.

Почему Pod — это ещё не всё

Вы научились создавать Pod, но в реальной работе их почти никогда не создают напрямую. Pod — низкоуровневая сущность. Он не умеет себя восстанавливать, не умеет обновляться на месте, не умеет масштабироваться.

Для всего этого нужен контроллер — объект, который следит за Pod и управляет им. Самый распространённый контроллер — Deployment. Он описывает, сколько экземпляров Pod должно работать, какой образ использовать, и берёт на себя создание, обновление и пересоздание Pod при сбоях.

Если Pod — это «один процесс на одном сервере», то Deployment — это «я хочу, чтобы всегда работало три экземпляра моего приложения, и мне неважно как». Kubernetes делает остальное.

Частые ошибки

  • Pending — нет подходящей ноды или не хватает ресурсов. Смотрите Events в describe.
  • ImagePullBackOff — неправильное имя образа, несуществующий тег или registry недоступен.
  • CrashLoopBackOff — контейнер падает сразу после старта. Смотрите kubectl logs nginx --previous.
  • Pod «не виден» — проверьте namespace. Возможно, Pod создан в другом namespace, а вы смотрите в default.
  • exec не работает — в образе нет shell. Попробуйте /bin/sh вместо /bin/bash.
  • Контекст не тот — kubectl config current-context покажет, к какому кластеру подключён kubectl.

Рекомендуемые программы

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845