티스토리 뷰
도커 스웜으로 서비스를 배포해봅시다. 우선 registry에 올리기 위해 dockerfile을 먼저 작성해줘야겠죠? 회사에선 사설 registry를 구축하여 image를 관리했지만 여기선 실제로 구축하기보단 Dockerhub라는 도커에서 제공해주는 registry를 사용해보겠습니다.
dockerhub는 이미지를 저장할 수 있게 docker에서 무료로 제공해줍니다.
해당 사이트에서 가입 후 사용하시면 됩니다.
또한 사전에 docker swarm에 참여한 서버간 Port를 열어줘야합니다. docker swarm은 ingress network로 각각의 트래픽을 조절하고 각 노드를 관리하는데 이 때 필요한 Port들이 있습니다.
TCP | 2377 | 클러스터 관리 통신용 |
TCP/UDP | 7946 | 노드 간 통신 |
UDP | 4789 | 오버레이 네트워크 트래픽용 |
자 준비가 완료되었다면 Dockerfile을 세팅합시다.
Dockerfile
우선 dockerfile openjdk official 이미지를 골라야 합니다. official image는 공식적으로 hub에서 지원하는 이미지이기 때문에 대부분의 경우 official image를 쓰는걸 추천합니다.
또한, official image에 여러 종류가 존재합니다. 대표적으로 slim, alpine이 있는데 특성은 다음과 같습니다.
- slim
slim image는 사용 가능한 가장 작은 openJDK 이미지이며 jdk 17 기준으로 405MB의 크기를 갖고 있습니다. 또한 Debian linx 기반의 이미지입니다.
docker pull openjdk:17-jdk-slim
17-jdk-slim: Pulling from library/openjdk
6d4a449ac69c: Pull complete
a59f13dc084e: Pull complete
1d5035d2d5c6: Pull complete
Digest: sha256:aaa3b3cb27e3e520b8f116863d0580c438ed55ecfa0bc126b41f68c3f62f9774
Status: Downloaded newer image for openjdk:17-jdk-slim
docker images openjdk:17-jdk-slim
REPOSITORY TAG IMAGE ID CREATED SIZE
openjdk 17-jdk-slim 8a3a2ffec52a 15 months ago 402MB
- alpine
alpine image는 alpine linux 기반의 가장 압축된 openjdk image 입니다. jdk 17기준으로 181MB의 크기를 갖고 있습니다.
(alpine은 arm 아키텍처 지원이 안되서 m1에서 볼 수가 없다..... 용량은 공식 이미지 사이트에서 확인)
상황에 따라 다르겠지만 호환성은 slim이 더 좋고 alpine은 매우 경량화된 이미지이기 때문에 빌드 시간이나 네트워크 대역폭등에서 큰 장점이 됩니다. (필자는 호환이 안되서 slim을 쓰겠다... 만약 m1이 아니라면 alpine도 괜찮은 선택이다.)
그러면 완성된 dockefile을 봅시다.
## Dockerfile
FROM openjdk:11-jre-slim
ARG JAR_FILE=/build/libs/kotlin.jar
RUN apt-get update && apt-get install -y curl
ADD ${JAR_FILE} app.jar
dockerfile에 대한 자세한 설명은 다음 글을 읽어봅시다.
https://golf-dev.tistory.com/55
docker image를 registry에 올리기 위해서 script를 짜면 다음과 같습니다.
buildscript.sh
# Docker build
version=$1
echo "build jar file ..."
./gradlew clean bootJar
# m1 아키텍처일 경우 linux 또는 ubuntu에 배포하기 위해 platform에 호환되게 빌드해야함
echo "build docker image ..."
docker build --platform linux/amd64 -t ilgolf/bank:version .
echo "push docker image ..."
docker push ilgolf/bank:version
echo "remove docker image ..."
docker rmi -f ilgolf/bank:version
현재는 빠르게 테스트 하기 위해 간단하게 작성했지만 실제로는 더 많은 스크립트를 짜야합니다. (version, profile 설정 외에도 사설 registry 접속을 위한 다양한 정보가 들어감)
자 그럼 세팅이 완료 됐습니다. Docker-compose 세팅을 해봅시다.
Docker-compose 파일 작성
docker-compose는 배포를 위한 파일이라고 생각하면 좋습니다. 해당 파일은 무중단 롤링 업데이트와 최대한 안전한 운영을 위한 설정입니다.
bank:
image: ilgolf/bank:latest
hostname: kotlin-bank
networks:
- golf
environment:
TZ: Asia/Seoul
ports:
- "8091"
stop_grace_period: 50s
stop_signal: SIGTERM
entrypoint:
- java
- -Dspring.profiles.active=dev
- -jar
- app.jar
healthcheck:
test: ["CMD", "curl", "-l", "http://localhost:8090/ping"]
timeout: 5s
deploy:
mode: replicated
replicas: 3
resources:
limits:
memory: '1g'
cpus: '1'
update_config:
order: start-first
delay: 5s
failure_action: rollback
rollback_config:
order: stop-first
parallelism: 0
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
networks:
golf:
external: true
주요 세팅을 설명해드리자면
- stop_grace_period : graceful한 종료 시 최대 timeout 시간을 설정합니다.
- stop_signal : 컨테이너를 종료하기 전 signal을 설정합니다. SIGKILL은 바로 컨테이너를 종료하는데 반면 SIGTERM은 프로세스에게 종료를 맡기기 때문에 graceful shutdown이 가능합니다.
- health-check : test에 포함된 명령어가 정상적으로 수행되어야 healthy 상태가 될 수 있고 트래픽 요청을 처리할 수 있게 설정합니다. timeout은 5s입니다.
- deploy 세팅
- mode : 배포 상태를 설정합니다. global에 경우 각 node마다 한 개의 replica를 만들어냅니다. 반면에 replicated는 replica를 무작위로 배포 가능합니다.
- replicas : replica 개수를 설정합니다. 이 개수만큼 docker swarm이 replica 개수를 유지해줍니다.
- resources: 자원 관리 관련 설정입니다. limit으로 제한을 걸고 memory 1GB, cpu 1 core로 사용에 제한을 둡니다.
- update_config : 롤링 업데이트를 세팅합니다. 현재 순서는 새로운 컨테이너를 먼저 띄우고 배포 성공 후 5s의 지연 후 새 컨테이너를 이어서 배포합니다. 또한 실패 시 이전 컨테이너로 rollback합니다.
- rollback_config : 배포 실패 시 rollback설정을 합니다. 실패 시 손상된 컨테이너를 바로 종료하여 손상된 컨테이너에 트래픽이 몰리지 않게 합니다. 또한 모든 실패한 컨테이너를 병렬로 rollback하여 최대한 배포 실패로 인한 문제가 없게 합니다.
- restart_policy : 배포 실패 시 재시도 횟수와 지연시간을 설정합니다.
여기서 핵심은 health-check와 deploy 세팅입니다. health-check가 성공해야지만 트래픽이 들어가기 때문에 안정적으로 새로운 컨테이너 배포가 가능하고 update 시 start_first로 세팅이 되어있기 때문에 health-check가 성공해야만 기존 컨테이너의 트래픽이 끊기게 됩니다.
만약 배포에 실패한다면 기존 컨테이너는 종료되지 않을 것이고 계속 운영될 것입니다. 또한 배포 실패 시 빠르게 손상된 컨테이너를 제외시켜주기 때문에 무중단 운영이 가능해집니다.
자 그럼 배포해봅시다.
배포는 docker stack deploy -c 명령어로 가능합니다.
server1 $ docker stack deploy -c {docker-compose-file.yml} --with-registry-auth stack_name
다음 명령어로 배포할 수 있으며 --with-registry-auth는 docker login 명령어를 통해 해당 서버에서 docker에 로그인 하면 login된 정보를 바탕으로 image를 자동으로 pull 해올 수 있게 도와줍니다.
실제로 docker service ps {service_name} 으로 swarm의 배포 현황을 파악할 수 있습니다.
이어서 rolling update는 간단합니다.
image의 태그를 변경하여 이미지를 다시 배포해준 뒤 service만 업데이트 해줍니다.
server1 $ docker service update --image ilgolf/bank:0.0.2
이 후 docker ps 명령어로 배포 현황을 보면 docker가 rolling update 되는 것을 볼 수 있을 겁니다.
자 이렇게 docker swarm으로 배포하는 작업은 끝났습니다. 과연 모든게 끝났을 까요? 아니죠 이제 요청을 외부로 부터 받아와야합니다. LB에서 요청을 받아와 서버에서 요청이 들어오면 서비스 포트로 바로 들어오는게 아니라 보안을 위해 reverse proxy로 요청을 받을 겁니다. 그리고 해당 proxy를 80으로 띄울 것이고 모든 도메인은 이 proxy를 거쳐야합니다. 그렇게 되면 도메인이 추가됨에 따라 포트를 새로 뚫을 이유도 없을 뿐더러 외부에 포트를 노출시키지 않으니 더욱 안전한 서비스 운영이 가능하겠죠
그럼 다음시간에는 traefik을 이용한 reverse proxy 구축하기로 돌아오겠습니다. 감사합니다.
Reference.
https://www.baeldung.com/ops/java-openjdk-docker-images-slim-vs-slim-stretch-vs-stretch-vs-alpine
'docker' 카테고리의 다른 글
[Docker Swarm으로 고가용성 서버 구축하기 - 4] 편리한 운영을 위한 다양한 Tool 도입하기 (0) | 2023.08.15 |
---|---|
[Docker Swarm으로 고가용성 서버 구축하기 - 3] 무중단으로 운영 가능한 Reverse Proxy 도입기 (5) | 2023.08.12 |
[Docker swarm으로 고가용성 서버 구축하기 - 1] 클러스터와 부하분산 (0) | 2023.07.30 |
[Docker 4주차] Docker Swarm (2) | 2023.02.18 |
[Docker 3주차] Docker Engine 2부 (1) | 2023.02.18 |
- Total
- Today
- Yesterday
- Spring
- 개발자
- thread
- 면접 준비
- 면접
- 코딩
- Redis
- 개발
- 취업
- 프로젝트
- 게시판
- Kotlin
- 코드
- 면접준비
- 취업준비
- MySQL
- swarm
- 동시성
- 자바
- 프로그래밍
- 취준
- IT
- DB
- 인터뷰
- docker
- java
- JPA
- CS
- DevOps
- 백엔드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |