УРОК 23 / 30 0%

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. 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. 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. 3
    k8s/00-namespace.yaml
    
    apiVersion: v1
    kind: Namespace
    metadata:
      name: taskflow
    
  4. 4
    k8s/10-configmap.yaml
    
    apiVersion: 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. 5
    k8s/11-secret.yaml
    
    apiVersion: 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. 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. 7
    k8s/30-app.yaml
    
    apiVersion: 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. 8
    k8s/40-ingress.yaml
    
    apiVersion: 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. 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. 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    # откат
    
  11. 11
    Rolling update
    
    # Меняем image в deployment
    kubectl set image deployment/taskflow taskflow=taskflow:0.2.0 -n taskflow
    
    # K8s постепенно заменяет поды (maxSurge=1, maxUnavailable=0)
    # Поды новой версии создаются → readiness проходит → старые удаляются
    

    ---

🎯

Зачем это на собесе

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

HA: 2+ реплики + Service = если один под умер, второй принимает трафик.
Auto-healing: liveness probe → K8s перезапускает упавший контейнер.
Zero-downtime deploy: rolling update + readiness probe = новые поды готовы → старые удаляются.
Resource limits: requests для scheduler, limits для cgroup. JVM не съест больше, чем положено.

5 вопросов на углубление

Раскрой вопрос и нажми «🤔 Хочу разобрать подробнее» — он попадёт в страницу ответов.

1
Deployment vs StatefulSet — что выбрать для Spring Boot?

Разбор внутри: stateless replicas и stateful нагрузки.

2
startupProbe vs livenessProbe vs readinessProbe

Разбор внутри: медленный старт, перезапуск и вывод из трафика.

3
ClusterIP vs LoadBalancer — как открыть сервис?

Разбор внутри: внутренний доступ и внешний балансировщик.

4
Что происходит, когда readiness probe падает?

Разбор внутри: endpoints Service-а и прекращение трафика на pod.

5
Как выбрать imagePullPolicy?

Разбор внутри: Always, IfNotPresent и локальная разработка в kind/minikube.

Готов идти дальше?

Выбери вопросы, которые тебе интересны, и изучи их. Потом — к следующему уроку.

🚀 Перейти к Уроку 24

Сначала пройди все секции и выбери хотя бы 1 вопрос

⬅️ Назад к Уроку 22
🎉
Новый тир
Новый тир достигнут!