1. Java 애플리케이션 컨테이너화
컨테이너화는 애플리케이션과 그 의존성을 하나의 실행 가능한 패키지로 묶는 과정입니다.
1.1 Dockerfile 작성
# openJDK 활용해서 런타임
FROM openjdk:11-jre-slim
# 콘테이너 내부에서 워킹 디렉토리 설정
WORKDIR /app
# 컨테이너에 어플리케이션 jar파일 복사
COPY target/myapp.jar /app/myapp.jar
# 컨테이너 실행을 위한 명령어 작성
CMD ["java", "-jar", "myapp.jar"]
팁: 멀티 스테이지 빌드를 사용하여 빌드 환경과 런타임 환경을 분리하세요. 이는 최종 이미지의 크기를 줄이고 보안을 향상시킵니다.
1.2 Docker 이미지 빌드 및 푸시
# 도커이미지 빌드
docker build -t myapp:v1 .
# Tag the image for your container registry 도커 이미지에 태그
docker tag myapp:v1 your-registry.com/myapp:v1
# 이미지 등록
docker push your-registry.com/myapp:v1
팁: 버전 관리를 위해 의미 있는 태그를 사용하세요. 예를 들어, Git 커밋 해시나 빌드 번호를 태그에 포함시킬 수 있습니다.
2. Kubernetes 배포
Kubernetes는 컨테이너화된 애플리케이션의 배포, 스케일링, 관리를 자동화합니다.
2.1 Deployment YAML 작성
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: your-registry.com/myapp:v1
ports:
- containerPort: 8080
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
팁: 리소스 제한과 요청을 명시적으로 설정하세요. 이는 클러스터 리소스를 효율적으로 사용하고 애플리케이션의 안정성을 높이는 데 도움이 됩니다.
2.2 Service YAML 작성
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
팁: 내부 통신에는 ClusterIP 서비스를, 외부 노출이 필요한 경우에만 LoadBalancer나 NodePort를 사용하세요.
3. Kubernetes 배포 전략
효과적인 배포 전략은 다운타임을 최소화하고 롤백을 용이하게 합니다.
3.1 롤링 업데이트
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
팁: maxSurge와 maxUnavailable 값을 조정하여 업데이트 속도와 리소스 사용량의 균형을 맞추세요.
3.2 블루/그린 배포
블루/그린 배포는 새 버전(그린)을 완전히 배포한 후 트래픽을 전환하는 방식입니다.
# Deploy new version (green)
kubectl apply -f myapp-green.yaml
# Switch traffic to green version
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"green"}}}'
# If needed, rollback to blue version
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"blue"}}}'
팁: 블루/그린 배포는 빠른 롤백이 가능하지만, 리소스 사용량이 일시적으로 두 배가 될 수 있음을 유의하세요.
4. 모니터링 및 로깅
효과적인 모니터링과 로깅은 운영 중인 애플리케이션의 건강 상태를 파악하는 데 필수적입니다.
4.1 Prometheus와 Grafana 설정
# Prometheus configuration for Java application
- job_name: 'myapp'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['myapp-service:80']
팁: Spring Boot Actuator와 micrometer-registry-prometheus를 사용하여 Java 애플리케이션의 메트릭을 쉽게 노출할 수 있습니다.
4.2 ELK 스택을 이용한 로그 수집
# Filebeat configuration
filebeat.inputs:
- type: container
paths:
- /var/lib/docker/containers/*/*.log
output.elasticsearch:
hosts: ["elasticsearch:9200"]
팁: 구조화된 로깅을 사용하고, 로그 레벨을 적절히 조정하여 중요한 정보만 수집하세요. 이는 로그 분석의 효율성을 높이고 스토리지 비용을 절감하는 데 도움이 됩니다.
결론
Java 애플리케이션의 컨테이너화와 Kubernetes 배포는 현대적인 DevOps 환경에서 필수적인 기술입니다. 이러한 접근 방식은 애플리케이션의 확장성, 이식성, 그리고 관리 용이성을 크게 향상시킵니다. 컨테이너화, 효과적인 배포 전략, 그리고 강력한 모니터링 및 로깅 시스템을 구축함으로써, 개발 팀은 더 빠르고 안정적으로 애플리케이션을 제공할 수 있습니다.