Серверы
April 8

Kubernetes для новичков: просто о сложном

Kubernetes — это как операционная система для серверов, на которых работают ваши приложения. Только не для одного сервера, а для целого зоопарка.

Если вы когда-либо:

  • запускали сервер на python manage.py runserver,
  • писали docker run,
  • переносили проекты с одной машины на другую...

...то Kubernetes создан, чтобы всё это делать автоматически, масштабируемо и без боли.


❓ Что такое Kubernetes?

Kubernetes (k8s) — это платформа с открытым исходным кодом для управления контейнерами, которая:

  • запускает приложения в контейнерах (чаще всего — Docker),
  • распределяет их по нескольким серверам (нодам),
  • следит, чтобы всё работало и перезапускало, если что-то падает,
  • масштабирует приложения при росте нагрузки.
📦 Kubernetes не запускает сами приложения — он управляет контейнерами, в которых они работают.

🧠 Ключевые понятия (и как их понять)

🔹 Cluster (кластер)

Это вся ваша "система" — набор серверов, объединённых для запуска контейнеров.

🔹 Node (нода)

Один сервер в кластере. Может быть физическим или виртуальным.
Бывает: Master (Control Plane) — управляет кластером. Worker — запускает приложения.

🔹 Pod (под)

Минимальная "единица" в Kubernetes. Это один или несколько контейнеров, объединённых вместе (чаще — один). K8s не запускает контейнеры напрямую — он всегда запускает Pod'ы.

🔹 Deployment

Шаблон, который описывает, что запускать, сколько копий, как обновлять.
Kubernetes следит за тем, чтобы всё соответствовало этому описанию.

🔹 Service

Постоянный адрес (IP и порт) для доступа к Pod'ам.
Без сервиса — у пода нет «имени», к которому можно подключиться.

🏁 Как всё это работает вместе?

Представим:

  • Вы создали образ своего приложения (Dockerfile).
  • Написали Deployment манифест, сказав: "Запусти 3 копии этого контейнера".
  • Kubernetes сам выберет ноды, на которых запустить эти Pod'ы.
  • Если один под "умрёт" — он его перезапустит.
  • Вы создали Service — и теперь у приложения есть стабильный адрес.
  • Нагрузку можно распределить, масштабировать, обновлять без даунтайма.

📋 Пример: минимальный Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: myuser/myapp:latest
        ports:
        - containerPort: 8000

Этот YAML-файл говорит:
🛠 «Запусти 2 экземпляра контейнера myuser/myapp, слушай порт 8000».


🔌 Как снаружи подключаться?

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8000
  type: LoadBalancer

Kubernetes сам раздаст запросы между подами, обеспечив балансировку нагрузки.

🔄 Обновление без остановки (rolling update)

Kubernetes умеет мягко обновлять приложение:

  • по одной копии,
  • проверяя, что новая работает,
  • удаляя старую только после этого.

Так вы не теряете доступ даже во время деплоя.


🐾 Простой образ кота

Kubernetes — это как кот-менеджер: вы даёте ему инструкцию "надо запустить 3 будки с едой", а он сам решает, где и как. Если одна миска опрокинулась — он ставит новую. Он не кормит сам, но организует кормёжку на уровне продакшена.

✅ Почему это круто?

  • Масштабирование в одну строку (replicas: 10)
  • Само-восстановление: упал под — запустит новый
  • Удобные обновления и откаты
  • Разделение ролей (Dev, Ops)
  • Кроссплатформенность (AWS, GCP, bare metal, локально)

📝 Манифесты Kubernetes — как "написать" кластеру, что делать

В Kubernetes вы не запускаете команды вручную, а описываете желаемое состояние системы в виде YAML-файлов. Это и есть манифесты.

Вы как бы говорите:

🧑‍💻 «Хочу 3 копии этого приложения, с таким образом, доступом и хранилищем».
Kubernetes отвечает:
🤖 «Ок. Я всё сделаю и буду следить, чтобы так всегда и было».

🧠 Что такое манифест?

Манифест в Kubernetes — это YAML-файл, который описывает ресурс, который вы хотите создать:
Pod, Deployment, Service, ConfigMap, Ingress, Volume и т.д.

Манифест:

  • описывает структуру и параметры объекта,
  • передаётся в кластер с помощью kubectl apply,
  • позволяет декларативно управлять инфраструктурой.

🔧 Общая структура манифеста

apiVersion: apps/v1         # версия API
kind: Deployment            # тип ресурса
metadata:                   # метаданные
  name: my-app
spec:                       # спецификация (что должно быть)
  ...

💡 Всегда состоит из четырёх основных блоков:

apiVersion

Версия API, к которой относится ресурс (v1, apps/v1)

kind

Тип ресурса (Pod, Service, Deployment, и т.д.)

metadata

Имя, лейблы, аннотации

spec

Конкретные настройки ресурса (что запускать, как, где)

🛠 Как применить манифест?

  1. Сохраняем YAML-файл, например deployment.yaml
  2. Применяем его в кластер:
kubectl apply -f deployment.yaml

Проверяем:

kubectl get all

🧾 Организация манифестов

В продакшене принято:

  • Разделять манифесты по ресурсам: pod.yaml, service.yaml, ingress.yaml
  • Хранить их в Git (инфраструктура как код)
  • Использовать шаблонизаторы (например, Helm или Kustomize)
  • Использовать kubectl kustomize, kustomization.yaml или helm values.yaml

📌 Полезные команды

kubectl apply -f file.yaml         # применить манифест
kubectl delete -f file.yaml        # удалить объект
kubectl get -f file.yaml           # посмотреть объект
kubectl explain pod                # объяснение структуры манифеста
kubectl diff -f file.yaml          # что изменится при применении

🐾 Кошачий пример

Манифест — это как инструкция по уходу за котом:
сколько мисок, где он спит, какие игрушки и сколько внимания.
Kubernetes — это заботливый автоматизированный котоняня, который всегда следит, чтобы всё соответствовало плану.

✅ Вывод

Манифесты — это язык общения с Kubernetes.
Они:

  • определяют структуру приложения,
  • делают поведение системы предсказуемым,
  • позволяют версионировать инфраструктуру, как код.

💡 Овладев манифестами, вы перестаёте "жать кнопки" и начинаете управлять системой как архитектор.

🛠 kubectl — главный инструмент общения с Kubernetes

kubectl (произносится "куб-кей-тл" или просто "куб-контрол") — это клиентская утилита, с помощью которой вы управляете кластером Kubernetes.
Она позволяет:

  • создавать и изменять ресурсы,
  • просматривать состояние приложений,
  • масштабировать, обновлять, удалять,
  • получать логи и доступ внутрь контейнеров.
🐱 Образно: Kubernetes — это целый кошачий город, а kubectl — это ваш пульт управления: кормить, запускать, лечить, переселять и перезапускать 🐾

🧠 Общая структура команды

kubectl [глагол] [ресурс] [имя] [флаги]

Например:

kubectl get pods
kubectl describe pod my-pod
kubectl delete deployment my-app
kubectl apply -f app.yaml

📚 Команда kubectl explain

Хочешь узнать, какие поля есть у ресурса?

kubectl explain deployment
kubectl explain deployment.spec.template

kubectl — это основной инструмент для взаимодействия с Kubernetes.
Он:

  • даёт полный контроль над кластером,
  • позволяет работать как с манифестами, так и напрямую,
  • делает управление инфраструктурой быстрым, удобным и скриптуемым.

💡 Если вы изучаете Kubernetes — изучайте kubectl первым делом. Он поможет разобраться во всём остальном.

Далее разберем основные виды ресурсов в Kubernetes.

⚙️ Deployment в Kubernetes — сердце управляемого запуска

🧩 Что такое Deployment?

Deployment — это ресурс в Kubernetes, который:

  • описывает, как должно работать ваше приложение (какой контейнер, сколько копий и т.д.),
  • обеспечивает стабильность (следит, чтобы нужное количество копий всегда было в работе),
  • позволяет обновлять приложение без простоя (rolling updates),
  • и даже откатывать неудачные обновления.
📌 В реальности: вы не "запускаете" приложение вручную, вы говорите Kubernetes:
"Я хочу, чтобы это приложение всегда работало в таком виде".
А он сам следит за этим.

🛠 Что включает в себя 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: app
        image: myuser/myapp:1.0
        ports:
        - containerPort: 8000

🔍 Разберём по частям:

  • replicas: сколько копий приложения нужно.
  • selector: как находить связанные Pod'ы.
  • template: шаблон Pod'а, который Kubernetes будет создавать.
  • image: контейнер, который запускать (из Docker Hub, GitLab, ECR и т.д.).

🔄 Rolling Updates — обновление без даунтайма

Допустим, вы поменяли image: myuser/myapp:1.0 на image: myuser/myapp:2.0.

Что делает Kubernetes:

  1. Запускает новую версию по одной.
  2. Ждёт, пока под станет готовым.
  3. Удаляет один старый.
  4. Повторяет, пока все поды не станут новыми.

Вы ничего не выключаете — обновление "на лету" ✈️


🔙 Rollback — откат на предыдущую версию

Что, если что-то пошло не так? Kubernetes хранит историю деплойментов и позволяет откатиться одной командой:

kubectl rollout undo deployment my-app
🐱 Это как кнопка "отмена" в редакторе — но для всего приложения.

📈 Масштабирование

Нужно больше мощности? Меняем количество реплик:

kubectl scale deployment my-app --replicas=10

Или в YAML:

replicas: 10

Kubernetes создаст недостающие поды автоматически.

🐾 Кошачий пример

Deployment — это как список требований к коту в приюте: "Хочу 3 кота, серых, с кормушкой и будкой". Kubernetes как добросовестный волонтёр — найдёт, поселит, проверит, и если один сбежал — сразу привезёт нового.

✅ Вывод

Deployment — это основной способ управлять жизненным циклом приложений в Kubernetes.
С его помощью вы:

  • запускаете приложения,
  • обновляете их безопасно,
  • масштабируете нагрузку,
  • и получаете автоматическое восстановление в случае сбоев.

Это ваш контракт с кластером: вы пишете, как должно быть, Kubernetes делает, чтобы оно так и было.

🌐 Service в Kubernetes — как поды находят друг друга

В Kubernetes вы запускаете поды. Они живут, работают... но как к ним обращаться?
Ведь каждый под — это временная сущность. Он может "умереть", перезапуститься, получить новый IP.
Вот здесь и появляется герой — Service.

🐱 Пример: Под — это кот. Сегодня он спит на диване, завтра — на окне.
А Service — это табличка «здесь живёт Кот Барсик», по которой его всегда можно найти, где бы он ни спал 🐾

❓ Зачем нужен Service?

  • Обеспечить постоянный доступ к подам, даже если они перезапускаются.
  • Распределять трафик между несколькими репликами.
  • Позволить другим подам внутри кластера (или снаружи) обращаться к вашему приложению.

🛠 Виды Service

Kubernetes предлагает несколько типов Service — каждый для своей задачи:

ClusterIP Доступ внутри кластера (по умолчанию)

NodePortОткрывает порт на всех нодах (для отладки/доступа)

LoadBalancerИспользует внешний балансировщик (в облаках)

ExternalNameПрокси на внешний DNS-адрес (например, внешние API)


🔧 Пример Service с ClusterIP

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8000

Разберём:

  • selector — связывает Service с подами (app: my-app),
  • port — внешний порт, по которому обращаются к сервису,
  • targetPort — внутренний порт, который слушает контейнер.
📌 Теперь другие поды в кластере могут обращаться к вашему приложению через http://my-app-service:80

🚪 NodePort — доступ снаружи

spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8000
      nodePort: 30080

Теперь можно обратиться к приложению через IP любой ноды:
http://<node-ip>:30080

⚠️ Не рекомендуется для продакшена — только для тестов и отладки.

☁️ LoadBalancer — для облаков

Если вы используете Kubernetes в облаке (GCP, AWS, Azure), то можно указать:

spec:
  type: LoadBalancer

И Kubernetes создаст внешний балансировщик, направляющий трафик на ваши поды.


🔁 Как всё работает внутри

Service создаёт виртуальный IP (ClusterIP), который:

  • получает DNS-имя,
  • проксирует трафик на нужные поды (по selector),
  • умеет распределять трафик между репликами (round-robin).

🔍 Как посмотреть и протестировать

kubectl get service
kubectl describe service my-app-service

Внутри кластера можно сделать:

curl http://my-app-service

И убедиться, что всё работает!

🐾 Кошачий факт:

Service — это как GPS-ошейник у кота:
коты меняются, бегают и прячутся, но вы всегда можете найти «котика по имени Барсик», и Kubernetes приведёт вас к одному из них.

✅ Вывод

Service — один из самых важных компонентов Kubernetes. Он:

  • даёт стабильный способ обратиться к подам,
  • обеспечивает балансировку,
  • делает возможным общение между сервисами,
  • открывает доступ наружу (если нужно).

В связке с Deployment и Pod это — основа архитектуры любого K8s-приложения.

📦 Pod в Kubernetes — минимальный, но мощный

Если вы только начинаете работать с Kubernetes, слово "Pod" может звучать загадочно. Но на самом деле — это самая простая единица выполнения в кластере.
Под — это обёртка над контейнером, которая знает, как его запустить, где он живёт, и что ему нужно.

🐱 Образно: Контейнер — это кот. А Pod — это его коробка: в ней уютно, в ней миска и подстилка, и она знает, где кот должен спать.

❓ Что такое Pod?

Pod — это объект в Kubernetes, который содержит:

  • один (или несколько) контейнеров,
  • общие ресурсы: файловую систему, сеть, переменные окружения и т.д.
Почти всегда в поде — один контейнер. Под с несколькими контейнерами — редкость (и продвинутая тема).

🔍 Почему Pod, а не сразу контейнер?

Потому что Kubernetes не работает напрямую с контейнерами (например, Docker), а всегда управляет именно Pod’ами.

Так проще:

  • добавлять общие volume,
  • прокидывать переменные окружения,
  • управлять сетью и доступами,
  • наблюдать за состоянием.

🧠 Что есть у Pod'а?

  • IP-адрес — свой собственный внутри кластера.
  • Общий namespace — контейнеры в поде видят друг друга через localhost.
  • Volume’ы — хранилище, которое можно разделить.
  • Метаданные — лейблы, аннотации, имя и т.д.

🛠 Пример Pod-манифеста (YAML)

apiVersion: v1
kind: Pod
metadata:
  name: my-simple-pod
spec:
  containers:
  - name: my-container
    image: python:3.10
    command: ["python", "-m", "http.server", "8000"]
    ports:
    - containerPort: 8000
    
📌 Этот pod запускает python -m http.server внутри контейнера и слушает порт 8000.

🧪 Команды работы с Pod

kubectl get pods             # список подов
kubectl describe pod my-pod # подробная информация
kubectl logs my-pod         # логи контейнера в поде
kubectl exec -it my-pod -- bash  # зайти внутрь (если есть bash)

🔁 Что происходит, если под "умирает"?

  • Если вы запустили под напрямую (kind: Pod), и он завершился — всё, он "умер".
  • Но если вы используете Deployment, ReplicaSet, или Job — Kubernetes сам пересоздаст его.
❗ Под — одноразовый. Его можно пересоздать, но сам он не восстанавливается.

🧱 Множественные контейнеры в поде

Такое бывает редко, но возможно. Например, если нужен sidecar-контейнер для логов или прокси:

spec:
  containers:
  - name: app
    image: myapp
  - name: logger
    image: fluentd

Контейнеры внутри одного пода разделяют IP и volume, но не обязаны быть связаны логически.

🐾 Кошачий пример

Контейнер — это кот. Под — это коробка, в которой кот живёт: с подстилкой, едой, названием и GPS. Контейнер можно вынуть, но под — это его дом.

✅ Вывод

Pod — это основа всех приложений в Kubernetes:

  • это то, что реально запускается,
  • оборачивает контейнеры,
  • даёт им сеть, окружение и хранилище,
  • управляется через более высокоуровневые абстракции (Deployment, Job, DaemonSet и т.д.).

💡 Вы почти никогда не создаёте поды напрямую в реальной жизни — но понимание, как они работают, критично важно.

🌐 Ingress в Kubernetes — входная дверь в ваш кластер

Ваше приложение уже запущено в Kubernetes. Оно работает, его поды живы, сервисы раздают трафик.
Но тут встаёт вопрос:

"А как вообще попасть на мой сайт по адресу вроде https://myapp.com?"

Вот тут и появляется Ingress — контроллер, который управляет входящим HTTP/HTTPS-трафиком и направляет его на нужные сервисы.


❓ Что такое Ingress?

Ingress — это объект в Kubernetes, который:

  • принимает входящие HTTP(S)-запросы,
  • сопоставляет их с доменами, путями и сервисами внутри кластера,
  • маршрутизирует трафик на соответствующие backend-приложения.
🐱 Аналогия: Ingress — это кот-привратник: он сидит у двери с табличкой и говорит: «Ты идёшь на /api — тебе туда → сервис backend. А ты просишь /? Иди во frontend».

🧠 Как работает Ingress?

Ingress состоит из двух компонентов:

  1. Ingress ресурс — YAML-описание правил маршрутизации.
  2. Ingress контроллер — программа, которая эти правила исполняет (чаще всего это NGINX Ingress Controller).
⚠️ Важно: Ingress не работает сам по себе. Нужен установленный контроллер, который будет его обрабатывать.

📦 Пример простого Ingress манифеста

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80

📌 Что это значит:

  • При обращении к http://myapp.example.com трафик пойдёт в my-app-service на порт 80.
  • Ingress свяжет внешний адрес с внутренним сервисом.

🔐 HTTPS и TLS

Ingress умеет работать с HTTPS:

spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: tls-secret

Секрет (tls-secret) должен содержать сертификат и ключ.

Можно использовать cert-manager для автоматического получения TLS от Let’s Encrypt!

🛠 Как установить Ingress-контроллер?

Пример с NGINX Ingress Controller:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/cloud/deploy.yaml

После этого вы сможете использовать Ingress-ресурсы, и трафик будет маршрутизироваться.

Проверка:

kubectl get ingress
kubectl describe ingress my-app-ingress
kubectl logs -n ingress-nginx <ingress-controller-pod>

✅ Вывод

Ingress — ключевой компонент для продакшен-приложений в Kubernetes. Он:

  • обеспечивает доступ к приложениям по HTTP/HTTPS,
  • маршрутизирует трафик на нужные сервисы по правилам,
  • поддерживает TLS (HTTPS),
  • делает ваши сервисы доступными извне, с красивыми доменами и маршрутизацией.

💡 Если Service — это "внутренний адрес", то Ingress — это "внешняя входная дверь" в ваш кластер.


🧠 Часто задаваемые вопросы

Q: Что происходит, если под упал?
A: Kubernetes автоматически запустит новый — он следит за тем, чтобы количество реплик всегда совпадало с тем, что вы указали.

Q: Что если кластер перезагрузился?
A: Deployment «вспомнит» всё, что нужно — и поднимет приложение в нужном количестве.

Q: Зачем нужен Deployment, если есть Pod?
A: Pod — одноразовая сущность. Deployment — это контроллер, который следит, чтобы подов нужного вида всегда было нужное количество.


🧭 Что дальше?

  • Поставить kubectl и попробовать локально с minikube или kind
  • Понять, что такоеConfigMap, Secret, Volume
  • Подключить CI/CD
  • А потом — запустить всё это на облаке и наблюдать, как ваш котик управляет кластером 🐱⚙️