Kubernetes з нуля: Pod, Deployment, Service і як трафік доходить до застосунку
Базові об'єкти Kubernetes на одному прикладі: від маніфесту Deployment до доступу ззовні через Gateway API — з поясненням, навіщо кожен шар.
Kubernetes лякає кількістю абстракцій, але для запуску типового вебсервісу потрібні лише кілька. Розберемо їх на прикладі API, який має працювати у трьох копіях і бути доступним за доменом.
Декларативна модель
У Kubernetes ви не кажете «запусти контейнер». Ви описуєте бажаний стан — «хочу три копії образу api:1.4.2» — а контролери кластера постійно приводять реальний стан до бажаного. Впав вузол — поди перестворяться на іншому. Видалили под руками — з'явиться новий.
Pod — найменша одиниця
Pod — один або кілька контейнерів зі спільною мережею (одна IP-адреса) і томами. Напряму поди майже ніколи не створюють: ними керує Deployment.
Deployment — скільки копій і як оновлювати
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
labels: { app: api }
spec:
replicas: 3
selector:
matchLabels: { app: api }
strategy:
type: RollingUpdate
rollingUpdate: { maxUnavailable: 0, maxSurge: 1 }
template:
metadata:
labels: { app: api }
spec:
containers:
- name: api
image: ghcr.io/acme/api:1.4.2
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef: { name: api-secrets, key: database-url }Що тут відбувається:
replicas: 3— три поди;selector+labels— Deployment знаходить «свої» поди за мітками;RollingUpdateзmaxUnavailable: 0— під час оновлення спочатку піднімається новий под, і лише потім гасне старий. Користувачі не бачать простою.
kubectl apply -f deployment.yaml
kubectl rollout status deployment/api
kubectl get pods -l app=api -o wide
kubectl rollout undo deployment/api # відкотитися на попередню версіюService — стабільна адреса для подів
Поди смертні: їхні IP змінюються після кожного перезапуску. Service дає стабільне ім'я і балансує трафік між усіма подами з потрібними мітками.
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector: { app: api }
ports:
- port: 80 # порт сервісу
targetPort: 8000 # порт контейнераТепер усередині кластера будь-який под звертається до http://api (або api.<namespace>.svc.cluster.local).
| Тип Service | Доступ |
|---|---|
ClusterIP (за замовчуванням) |
Лише всередині кластера |
NodePort |
Порт на кожному вузлі (30000–32767) |
LoadBalancer |
Зовнішній балансувальник хмари |
Доступ ззовні: Ingress і Gateway API
Тримати LoadBalancer на кожен сервіс дорого. Зазвичай є одна точка входу, яка маршрутизує HTTP-запити за доменом і шляхом.
Історично для цього використовували Ingress з контролером ingress-nginx. Але проєкт ingress-nginx у березні 2026 року завершив підтримку, і Kubernetes рекомендує переходити на Gateway API — сучасніший і виразніший стандарт.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api
spec:
parentRefs:
- name: public-gateway # Gateway створює команда платформи
namespace: infra
hostnames: ["api.example.com"]
rules:
- matches:
- path: { type: PathPrefix, value: / }
backendRefs:
- name: api
port: 80ПриміткаGateway API розділяє відповідальність: команда платформи керує
Gateway(сертифікати, адреси, який контролер), а команди застосунків — своїмиHTTPRoute. З Ingress усе це змішувалось в анотаціях конкретного контролера.
ConfigMap і Secret
Конфігурацію тримають окремо від образу:
kubectl create configmap api-config --from-literal=LOG_LEVEL=info
kubectl create secret generic api-secrets --from-literal=database-url='postgres://...'УвагаSecret у Kubernetes за замовчуванням лише закодовано в base64, а не зашифровано. Увімкніть шифрування etcd, обмежте доступ через RBAC і не комітьте секрети в Git — для GitOps використовуйте Sealed Secrets, SOPS або External Secrets Operator.
Namespace
Простори імен ділять кластер на логічні частини: dev, staging, команди чи продукти. RBAC, квоти й мережеві політики зазвичай налаштовують саме на рівні namespace.
Шпаргалка kubectl
kubectl get pods,svc,deploy -n production
kubectl describe pod api-7d9f8-x2kq # події: чому под не стартує
kubectl logs -f deploy/api # логи
kubectl logs api-7d9f8-x2kq --previous # логи попереднього (упалого) контейнера
kubectl exec -it deploy/api -- sh # shell у контейнері
kubectl port-forward svc/api 8080:80 # доступ до сервісу з ноутбука
kubectl get events --sort-by=.lastTimestampЧому застосунки в кластері звертаються до Service, а не напряму до IP подів?
IP подів змінюються при кожному перезапуску, масштабуванні чи оновленні. Service має стабільне ім'я та IP і сам розподіляє запити між актуальними подами з потрібними мітками.
Збережіть статтю собі
Увійдіть, щоб імпортувати її у власні нотатки, відмічати вивчене, ставити лайки й питати спільноту. Реєстрація безкоштовна: вхід через Google займає кілька секунд.
Увійти через Google Інші способи входу