Kubernetes basics (Pod, Deployment, Service)
Цель урока
Сделать полноценный CRUD для задач с правильными HTTP-статусами (201/204/404), обработкой ошибок, и подготовить Task к подключению JPA.
Теория · для собеса
1 Что такое Kubernetes ▸
Kubernetes (K8s) — оркестратор контейнеров. Автоматизирует:
- Деплой
- Масштабирование
- Self-healing (упавший под перезапускается)
- Rolling updates (zero-downtime deploy)
- Service discovery
- Storage management
2 Основные сущности ▸
Pod — минимальная единица. 1+ контейнеров с общим network namespace и storage.
Deployment — декларативное описание «сколько подов с каким образом запустить». Deployment управляет ReplicaSet'ами.
Service — стабильный IP/DNS для группы подов. Load balancer между ними.
ConfigMap — конфигурация (env-vars, файлы), отделена от образа.
Secret — то же что ConfigMap, но для чувствительных данных (зашифрован в etcd).
Ingress — HTTP(S) маршрутизация извне кластера → Service'ам.
Namespace — виртуальный кластер внутри физического.
3 Лейблы и селекторы ▸
metadata:
labels:
app: taskflow
Service ищет поды по лейблам (selector: app: taskflow).
---
Практика: улучшаем CRUD
-
1Подготовка: minikube
# Установка curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube # Запуск minikube start --driver=docker --cpus=4 --memory=4g # Dashboard minikube dashboard -
2Собираем образ внутри minikube
# Используем Docker daemon minikube (чтобы образ был в его кеше) eval $(minikube docker-env) docker build -t taskflow:0.1.0 . # Или пушим в registry (для remote cluster) docker tag taskflow:0.1.0 ghcr.io/YOUR_USER/taskflow:0.1.0 docker push ghcr.io/YOUR_USER/taskflow:0.1.0 -
3
k8s/00-namespace.yamlapiVersion: v1 kind: Namespace metadata: name: taskflow -
4
k8s/10-configmap.yamlapiVersion: v1 kind: ConfigMap metadata: name: taskflow-config namespace: taskflow data: SPRING_PROFILES_ACTIVE: "prod" SPRING_DATASOURCE_URL: "jdbc:postgresql://postgres:5432/taskflow" SPRING_KAFKA_BOOTSTRAP_SERVERS: "kafka:9092" SERVER_PORT: "8080" JAVA_OPTS: "-XX:MaxRAMPercentage=75.0" -
5
k8s/11-secret.yamlapiVersion: v1 kind: Secret metadata: name: taskflow-secret namespace: taskflow type: Opaque stringData: # В проде — sealed-secrets / external-secrets / vault SPRING_DATASOURCE_PASSWORD: "REPLACE_ME" JWT_SECRET: "REPLACE_ME_with_at_least_32_chars_long_random_string" -
6
k8s/20-postgres.yaml(для dev; в prod — managed service)apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-pvc namespace: taskflow spec: accessModes: [ReadWriteOnce] resources: requests: storage: 5Gi -
7
k8s/30-app.yamlapiVersion: apps/v1 kind: Deployment metadata: name: taskflow namespace: taskflow spec: replicas: 2 # для HA selector: matchLabels: app: taskflow strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 # zero-downtime template: metadata: labels: app: taskflow spec: containers: - name: taskflow image: taskflow:0.1.0 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 envFrom: - configMapRef: name: taskflow-config env: - name: SPRING_DATASOURCE_PASSWORD valueFrom: secretKeyRef: name: taskflow-secret key: SPRING_DATASOURCE_PASSWORD - name: JWT_SECRET valueFrom: secretKeyRef: name: taskflow-secret key: JWT_SECRET resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 periodSeconds: 10 startupProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 periodSeconds: 5 failureThreshold: 12 # 60 сек на старт -
8
k8s/40-ingress.yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: taskflow namespace: taskflow annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: taskflow.local http: paths: - path: / pathType: Prefix backend: service: name: taskflow port: number: 80 -
9Деплой
# Применяем всё kubectl apply -f k8s/ # Проверяем kubectl get all -n taskflow # Логи пода kubectl logs -n taskflow -l app=taskflow -f # Port-forward для теста kubectl port-forward -n taskflow svc/taskflow 8080:80 # В другом терминале curl http://localhost:8080/actuator/health -
10Полезные команды
kubectl get pods -n taskflow # все поды kubectl describe pod-n taskflow # детали kubectl exec -it -n taskflow -- sh # войти в контейнер kubectl delete -f k8s/ # удалить всё kubectl rollout status deployment/taskflow -n taskflow # статус обновления kubectl rollout undo deployment/taskflow -n taskflow # откат -
11Rolling update
# Меняем image в deployment kubectl set image deployment/taskflow taskflow=taskflow:0.2.0 -n taskflow # K8s постепенно заменяет поды (maxSurge=1, maxUnavailable=0) # Поды новой версии создаются → readiness проходит → старые удаляются---
Зачем это на собесе
После урока ты должен уметь ответить на:
requests для scheduler, limits для cgroup. JVM не съест больше, чем положено.5 вопросов на углубление
Раскрой вопрос и нажми «🤔 Хочу разобрать подробнее» — он попадёт в страницу ответов.
Разбор внутри: stateless replicas и stateful нагрузки.
Разбор внутри: медленный старт, перезапуск и вывод из трафика.
Разбор внутри: внутренний доступ и внешний балансировщик.
Разбор внутри: endpoints Service-а и прекращение трафика на pod.
Разбор внутри: Always, IfNotPresent и локальная разработка в kind/minikube.
Готов идти дальше?
Выбери вопросы, которые тебе интересны, и изучи их. Потом — к следующему уроку.
🚀 Перейти к Уроку 24Сначала пройди все секции и выбери хотя бы 1 вопрос
⬅️ Назад к Уроку 22