Gymterview
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.