Через Helm до Kubernetes
Взято пара мікросервісів і для них прописуються Helm конфіги щоб розгорнути їх в Kubernetes
Для кого
Java-розробники, які починають роботу з Kubernetes.
Що ви знайдете в статті
- Покроковий розбір міграції з прикладами коду та посиланнями на коміти
- Як уникнути типових помилок при переході в Kubernetes
- Практичні рішення проблем, що виникають
Частина I: Знайомство з мікросервісами
Вихідна архітектура системи
Перед міграцією система складалася з двох ключових сервісів, що взаємодіють як партнери у музичному дуеті. Посилання на код
1. Resource Service: Зберігач музики
Роль:
- Обробляє та зберігає MP3-файли
- Відповідає за завантаження, скачування та потокову передачу аудіо
Технічні деталі:
- Мова: Java 17 (LTS)
- Фреймворк: Spring Boot 3.4.0
- База даних: PostgreSQL (таблиця resources)
- Збірка: Maven + двоетапний Dockerfile (на основі eclipse-temurin-17-alpine)
Коміт: Dockerfile
# Етап збірки FROM maven:3.9.9-eclipse-temurin-17-alpine AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean package -Dmaven.test.skip=true # Етап запуску FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
2. Song Service: Диригент метаданих
Роль:
- Керує метаданими треків (назва, автор, жанр)
- Кожному запису в PostgreSQL-таблиці songs відповідає MP3-файл у Resource Service
Особливості:
- Зв’язок 1:1: У кожного треку є resource_id, який посилається на файл у Resource Service
- Каскадне видалення: При видаленні файлу в Resource Service метадані автоматично видаляються
Приклад запиту: DELETE /resources?id=1,2
→ (Resource Service видаляє файл) → Song Service видаляє пов’язані метадані
Інфраструктура: Що пов’язує сервіси
Eureka: Диспетчер оркестру
Роль:
- Реєструє всі мікросервіси (як музикантів в оркестрі)
- Дозволяє сервісам знаходити один одного за іменем без жорстких IP-адрес
Налаштування:
# docker-compose.yml Song Service environment: EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: ${EUREKA_CLIENT_SERVICEURL}
Spring Cloud Gateway: Маршрутизатор запитів
Роль:
- Перенаправляє запити до потрібного сервісу (наприклад, /songs/** → Song Service)
- Спрощує безпеку та моніторинг
Приклад маршруту:
spring.cloud.gateway.routes[0].id=song-service_route spring.cloud.gateway.routes[0].uri=lb://song-service spring.cloud.gateway.routes[0].predicates[0]=Path=/songs/**
Чому ці технології?
PostgreSQL:
- Надійність для транзакцій (каскадне видалення)
- Підтримка JSON-полів для гнучкості метаданих
Двоетапний Dockerfile:
- Зменшує розмір фінального образу (видаляються непотрібні залежності після збірки)
- Безпека: У продакшені використовується мінімалістичний alpine-образ
Spring Boot 3.4:
- Вбудована інтеграція з Eureka та Spring Cloud Gateway
- Підтримка Java 17 (патерни запису, покращена продуктивність)
Частина II: Міграція в Kubernetes
Як працювати з цією статтею
🔗 Коміти в репозиторії — кожен етап містить посилання на конкретні коміти
📦 Вихідний код — Репозиторій проекту
💡 Інтерактивність — використовуйте команди та сніппети у формі посилань на коміти зі статті, щоб повторити кроки
Завдання 1: Створити Helm-чарт для resource-service
Створимо Helm-чарт для деплою resource-service в Kubernetes:
- Chart.yaml — метаінформація
- values.yaml — параметри (репліки, образ, порт, змінні оточення)
- templates/deployment.yaml — шаблон Deployment
- templates/service.yaml — шаблон Service
Перевірка працездатності
helm install resource ./helm/resource-service --dry-run --debug
Якщо ви бачите приблизно такий результат, значить Helm-чарт валідний:
NAME: resource LAST DEPLOYED: Thu Apr 24 12:12:00 2025 NAMESPACE: default STATUS: pending-install REVISION: 1 TEST SUITE: None USER-SUPPLIED VALUES: {} COMPUTED VALUES: env: - name: EXAMPLE_ENV value: default-value - name: SPRING_DATASOURCE_URL value: "" ... MANIFEST: --- # Source: resource-service/templates/service.yaml apiVersion: v1 kind: Service metadata: name: resource-resource-service spec: type: ClusterIP ports: - port: 8081 targetPort: 8081 protocol: TCP name: http selector: app: resource-service --- # Source: resource-service/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: resource-resource-service ...
Можливі проблеми
Якщо ви бачите zsh: command not found: helm:
Встановіть Helm: macOS (через Homebrew):
brew install helm
Linux (через скрипт):
curl raw.githubusercontent.com/...m/main/scripts/get-helm-3 | bash
Windows (через Chocolatey):
choco install kubernetes-helm
Після встановлення перевірте:
helm version
Помилка: INSTALLATION FAILED: Kubernetes cluster unreachable
Ця помилка означає, що Helm не може підключитися до Kubernetes-кластера. Можливі рішення:
Варіант 1: Локальний кластер (Minikube)
minikube start kubectl config use-context minikube
Варіант 2: Docker Desktop Увімкніть Kubernetes в налаштуваннях Docker Desktop.
Варіант 3: Azure AKS
az aks get-credentials --resource-group <your-rg> --name <your-aks-name>
Перевірте підключення:
kubectl get nodes
Завдання 2: Docker push + Helm deploy у кластер
Зберіть та запушіть Docker-образ:
docker build -t your-registry/resource-service:latest . docker push your-registry/resource-service:latest
Або для локального Docker Desktop:
docker build -t resource-service:latest -f resource-service/Dockerfile resource-service
Оновіть values.yaml з правильним image.repository
Запустіть деплой:
helm upgrade --install resource ./helm/resource-service
Перевірте деплой:
kubectl get pods kubectl logs <ім'я-пода>
Успішний запуск повинен показати ASCII-арт з котиком в логах:
___ |\__/,| (`\ _.-| | |\__/,| (`\ |o o |__ _) ) { | | |o o |__ _) ) _.( T ) ` / "-.|___| _.( T ) ` / n n._ ((_ `^--' /_< \ .--'-`-. _((_ `^--' /_< \ <" _ }=- `` `-'(((/ (((/ .+|______|__.-||__)`-'(((/ (((/
Оновлений код: Коміт 47bbb51
Можлива проблема: ImagePullBackOff
Якщо ви бачите статус ImagePullBackOff, Kubernetes не може завантажити вказаний образ. Рішення:
- Перевірте ім’я образу в values.yaml
- Встановіть imagePullPolicy: Never для локальних образів:
image: repository: resource-service tag: latest pullPolicy: Never
Оновлений код: Коміт
Завдання 3: Helm-чарт для song-service
Створіть директорію чарту:
helm create helm/song-service
Спростіть структуру (як в resource-service):
- Видаліть непотрібні шаблони (hpa.yaml, tests/*, serviceaccount.yaml)
- Оновіть Chart.yaml, values.yaml, і deployment.yaml
- Ім’я образу: song-service
- Порт: 8082
- Змінні оточення: ті, що потрібні для song-service
Протестуйте чарт:
helm install song ./helm/song-service --dry-run --debug
Зберіть Docker-образ:
docker build -t song-service:latest -f song-service/Dockerfile song-service
Задеплойте чарт:
helm upgrade --install song ./helm/song-service
Перевірте деплой:
kubectl get pods kubectl logs <ім'я-пода>
Успішний запуск повинен показати ASCII-арт з котиком та багом:
\`*-.
) _`-.
. : `. .
: _ ' \
; *` _. `*-._
`-.-' `-.
; ` `.
:. . \
. \ . : .-' .
' `+.; ; ' :
: ' | ; ;-.
; ' : :`-: _.`* ;
[bug] .*' / .*' ; .*`- +' `*'
`*-* `*-* `*-*'
Оновлений код: Коміт
Завдання 4: Відлагодження помилок (Bug-hunt)
При перевірці статусу подів, ви могли помітити CrashLoopBackOff:
kubectl get pods NAME READY STATUS RESTARTS AGE resource-resource-service-5cf85c8b7-gxrnr 0/1 CrashLoopBackOff 9 (31s ago) 23m song-song-service-86c4cc9c5b-8gd8b 0/1 CrashLoopBackOff 4 (46s ago) 3m5s
Аналіз логів показує проблему:
*
************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class
Рішення: Додавання змінних оточення для баз даних
Оновіть values.yaml:
env: - name: SPRING_DATASOURCE_URL value: jdbc:postgresql://postgres-song:5432/song-db - name: POSTGRES_DB_USER value: user - name: POSTGRES_DB_PASSWORD value: password
Створіть чарт для PostgreSQL:
- templates/postgres-resource.yaml (Service + StatefulSet для resource-db)
- templates/postgres-song.yaml (Service + StatefulSet для song-db)
- templates/secret.yaml (для зберігання паролів)
Застосуйте зміни:
helm upgrade --install song ./helm/song-service helm upgrade --install resource ./helm/resource-service
Перевірте стан подів:
kubectl get pods NAME READY STATUS RESTARTS AGE postgres-resource-0 1/1 Running 0 5m50s postgres-song-0 1/1 Running 0 5m50s resource-resource-service-5f864df4bf-n6fgd 1/1 Running 0 41s song-song-service-7774dc448f-pgdf9 1/1 Running 0 54s song-song-service-7774dc448f-rdqxn 1/1 Running 0 52s
Оновлений код: Коміт
Завдання 5: Розгортання discovery-service та gateway-service
Створіть Helm-чарти для discovery та gateway:
- helm/discovery та helm/gateway з Chart.yaml, values.yaml
- templates/deployment.yaml та templates/service.yaml
Налаштуйте конфігурацію:
- discovery: порт 8761
- gateway: порт 8080
Оновіть залежності мікросервісів:
env: - name: EUREKA_CLIENT_SERVICEURL_DEFAULTZONE value: "discovery-discovery:8761/eureka" - name: SONG_SERVICE_URL value: "gateway:8080/songs"
Задеплойте сервіси:
helm install discovery ./helm/discovery helm install gateway ./helm/gateway
Перевірте стан:
kubectl get pods NAME READY STATUS RESTARTS AGE discovery-discovery-8595d87dc4-rx55t 1/1 Running 0 15m gateway-gateway-7dd96958fd-mr7h9 1/1 Running 0 24s postgres-resource-0 1/1 Running 0 95m postgres-song-0 1/1 Running 0 95m resource-resource-service-5f864df4bf-n6fgd 1/1 Running 0 89m song-song-service-7774dc448f-pgdf9 1/1 Running 0 90m song-song-service-7774dc448f-rdqxn 1/1 Running 0 90m
Оновлений код: Коміт
Можливі проблеми:
1. ErrImageNeverPull
kubectl get pods NAME READY STATUS RESTARTS AGE discovery-discovery-8595d87dc4-jndmg 0/1 ErrImageNeverPull 0 38s gateway-discovery-8595d87dc4-bkb8c 0/1 ErrImageNeverPull 0 30s
Рішення: Зберіть локальні образи
docker build -t discovery-service:latest -f discovery/Dockerfile discovery docker build -t gateway-service:latest -f gateway/Dockerfile gateway
2. Сервіси не знаходять discovery та Eureka
Перевірте, що імена сервісів у змінних оточення відповідають іменам сервісів у Kubernetes:
EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: "discovery-discovery:8761/eureka"
3. Доступ до веб-інтерфейсу Eureka
Щоб отримати доступ до веб-інтерфейсу Eureka:
kubectl port-forward svc/discovery-discovery 8761:8761
Потім відкрийте localhost:8761 у браузері.
Після виправлення всіх помилок та перезапуску сервісів:
helm upgrade --install gateway ./helm/gateway helm upgrade --install song ./helm/song-service helm upgrade --install resource ./helm/resource-service
Всі мікросервіси повинні успішно зареєструватися в Eureka.
Оновлений код: Коміт
Висновок
У цій статті я показав повний шлях міграції мікросервісів у Kubernetes з використанням Helm:
- Створили Helm-чарти для двох основних сервісів
- Налаштували бази даних PostgreSQL
- Розгорнули інфраструктурні компоненти (Eureka, Gateway)
- Вирішили типові проблеми, що виникають при міграції
Повний код доступний у репозиторії проекту.
Питання? Задавайте в Issues або коментарях.
Фінальний код: Коміт 30862b0
Плани на майбутнє:
Повний план складається з шести частин:
- Через Helm до Kubernetes.
- TBD Azure Key Vault + CSI
- TBD AKS + PostgreSQL
- TBD Логування & моніторинг
- TBD Terraform & CI/CD
- TBD AI-диригент через Azure ML
2 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів