middle
Как задеплоить Java-приложение в Kubernetes?
Процесс деплоя Java-приложения в Kubernetes состоит из четырёх этапов: создание Docker-образа, написание манифестов, применение манифестов, настройка CI/CD.
1. Создание Docker-образа
Dockerfile (multi-stage build)
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /app/target/*.jar app.jar
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Сборка и публикация:
Пример
docker build -t my-registry/my-spring-app:1.0.0 .
docker push my-registry/my-spring-app:1.0.0
2. Создание Kubernetes-манифестов
Файлы Deployment, Service, ConfigMap, Secret, Ingress (примеры приведены в предыдущих вопросах).
3. Применение манифестов
Пример
# Создать namespace
kubectl create namespace production
# Создать секрет для доступа к registry (если приватный)
kubectl create secret docker-registry registry-credentials \
--docker-server=my-registry \
--docker-username=user \
--docker-password=password \
-n production
# Применить все манифесты
kubectl apply -f k8s/ -n production
# Проверить статус
kubectl get pods -n production
kubectl describe deployment my-spring-app -n production
4. Типичный CI/CD Pipeline
Пример GitHub Actions workflow
name: Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Build Docker image
run: docker build -t my-registry/my-app:${{ github.sha }} .
- name: Push Docker image
run: docker push my-registry/my-app:${{ github.sha }}
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/my-spring-app \
app=my-registry/my-app:${{ github.sha }} \
-n production
Чек-лист перед деплоем
- Docker-образ оптимизирован (multi-stage build, JRE вместо JDK, non-root user)
- Настроены Liveness, Readiness и Startup Probes
- Указаны Requests и Limits по CPU и памяти
- JVM настроена для работы в контейнере (
-XX:MaxRAMPercentage,-XX:+UseContainerSupport) - Настроен graceful shutdown (
server.shutdown=graceful) - Конфигурация вынесена в ConfigMap/Secret
- Логи пишутся в stdout/stderr (не в файл)
- Приложение stateless (состояние хранится во внешних хранилищах)
На собеседовании: интервьюер ожидает знание полного пайплайна: код -> Docker-образ -> Registry -> K8s-манифесты -> kubectl apply. Частая ошибка — забыть про imagePullSecrets для приватного registry или не настроить probes.