← Назад к вопросам
Расскажи как происходил деплой на твоем проекте
1.0 Junior🔥 201 комментариев
#Docker, Kubernetes и DevOps
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Деплой на моем проекте
В последних проектах я работал с микросервисной архитектурой, использовал Docker, Kubernetes и CI/CD пайплайны. Расскажу про наиболее сложный и интересный случай.
Архитектура деплоя
Мы использовали Kubernetes на AWS (EKS) с GitLab CI/CD:
Данные (Git) → GitLab CI → Docker Build → ECR → Kubectl apply → EKS
Этап 1: Коммит и тестирование
При push в main-ветку запускалась сборка в GitLab CI:
# .gitlab-ci.yml
stages:
- test
- build
- deploy
test:
stage: test
image: openjdk:17
script:
- ./mvnw clean test
- ./mvnw jacoco:report
coverage: '/Coverage: \d+\.\d+%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: target/site/jacoco/jacoco.xml
Если тесты падали — пайплайн останавливался, деплой не происходил.
Этап 2: Сборка Docker образа
build_image:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
Dockerfile
# Multi-stage build для оптимизации
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src src
RUN mvn clean package -DskipTests
# Runtime образ
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Этап 3: Деплой в Kubernetes
deploy_staging:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl config use-context $KUBE_CONTEXT_STAGING
- kubectl set image deployment/api-service
api-service=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- kubectl rollout status deployment/api-service -n staging
environment:
name: staging
kubernetes:
namespace: staging
only:
- develop
deploy_production:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl config use-context $KUBE_CONTEXT_PROD
- kubectl set image deployment/api-service
api-service=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- kubectl rollout status deployment/api-service -n production
- kubectl rollout history deployment/api-service -n production
environment:
name: production
kubernetes:
namespace: production
only:
- main
when: manual # Ручное одобрение для продакшена
Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
namespace: production
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api-service
image: registry.gitlab.com/company/api-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
Этап 4: Rolling Update и мониторинг
Rolling Update означал постепенное обновление подов:
- Создаётся новый под с новым образом
- Ждём, пока он пройдёт readiness check
- Трафик переводится на новый под
- Старый под gracefully shutdown (ждём максимум 30 сек)
- Повторяем для остальных подов
# Мониторим деплой
kubectl rollout status deployment/api-service -n production
# Откатываемся если что-то пошло не так
kubectl rollout undo deployment/api-service -n production
# История версий
kubectl rollout history deployment/api-service -n production
Проблемы, которые мы решали
1. Разбитые миграции БД
// Проблема: миграция несовместима с текущей версией приложения
// Решение: всегда откатываем БД миграции перед деплоем новой версии
// 1. Откатываем миграции
flyway migrate
// 2. Деплоим приложение
kubectl set image ...
// 3. Запускаем новые миграции
kubectl run migration-job --image=api-service -- /bin/sh -c "java -jar app.jar --migrate"
2. Утечки памяти при деплое
// Использовали graceful shutdown в Spring Boot
@Configuration
public class GracefulShutdownConfig {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory>
webServerFactoryCustomizer() {
return factory -> factory.setShutdownWaitTime(Duration.ofSeconds(30));
}
}
3. Холодный старт микросервиса
Оптимизировали через:
- GraalVM Native Image (вместо JVM)
- Уменьшение количества beans в Spring
- Lazy initialization
Мониторинг и логирование
// Использовали Prometheus + Grafana
@RestController
@RequestMapping("/api/users")
public class UserController {
private final MeterRegistry meterRegistry;
@GetMapping("/{id}")
public UserDto getUser(@PathVariable Long id) {
Timer.Sample sample = Timer.start(meterRegistry);
try {
UserDto user = userService.findById(id);
meterRegistry.counter("users.fetched").increment();
return user;
} catch (UserNotFoundException e) {
meterRegistry.counter("users.not_found").increment();
throw e;
} finally {
sample.stop(Timer.builder("users.response.time")
.publishPercentiles(0.5, 0.95, 0.99)
.register(meterRegistry));
}
}
}
Время деплоя
Обычно деплой занимал:
- Тесты: 5-7 минут
- Сборка образа: 3-4 минуты
- Rolling update: 2-3 минуты
- Итого: ~12-15 минут от коммита до продакшена