[ 살펴보기 ] Docker - Swarm 구성을 위한 Compose
![[ 살펴보기 ] Docker - Swarm 구성을 위한 Compose](https://cdn.hashnode.com/res/hashnode/image/upload/v1722329363572/29b9f938-29f5-44d4-a7da-804a46eed59d.jpeg)
Compose를 소개했던 포스트에서 Container로 application을 실행하기 위한 여러 환경과 조건을 YAML compose 파일로 관리를 했듯이 Swarm 또한 compose 문법과 동일하게 YAML파일을 통해 관리가 가능하다.
Swarm을 YAML파일에 지정하여 실행하는 간단한 예제를 살펴보자.
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs
ports:
- 4000:4000
위의 파일은 app-front-nextjs 이미지를 기준으로 app-front-container라는 service를 생성하기 위한 설정이다. 이제 다음 명령어를 통해 위의 설정파일을 기준으로 replica를 생성하여 실행해보자 ( yaml 파일명이 front-stack.yml이라고 가정한다 )
docker stack deploy -c ./stack-front.yml app-front
위의 명령어를 실행하면 위의 설정 파일에 따라 replica가 생성되어 실행되며 자동으로 overlay network 또한 새롭게 생성된 것을 확인할 수 있을 것이다.
다음 명령어를 통해 방금 생성한 stack 또한 확인할 수 있다.
docker stack ls
다음과 같이 Swarm 설정 파일에 deploy시 운영할 replica의 개수 지정 역시 가능하다.
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs
ports:
- 4000:4000
deploy:
replicas: 2
위의 설정 파일 기준으로 다시 swarm service를 생성하면 replica가 2개 생성되어 실행되는 것을 확인할 수 있을 것이다.
Deploy.resource property를 통해 한 개의 replica가 해당 node의 자원을 최대 얼마나 차지할 수 있는지 제한이 가능하다
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs
ports:
- 4000:4000
deploy:
replicas: 2
resources:
limits:
cpus: "0.60"
memory: 300m
위와 같이 설정하면 한 개의 replica는 cpu 한 개 core의 60%, 메모리는 300mb까지 점유할 수 있다.
만약 위와 같이 stack deploy 명령을 통해 이미 replica를 생성하고 운영 중에 새로운 사항이 추가 되거나 수정된다면 수정한 내용을 기준으로 stack deploy 명령을 한번 더 실행해준다
docker stack deploy -c ./stack-front.yml app-front
그러면 기존에 실행 중이던 replica가 하나씩 새로운 설정이 적용된 새로운 replica로 교체되며 기존 replica는 실행이 종료된다.
그리고 생성했던 stack을 삭제하려면 다음 명령어를 통해 삭제할 수 있다 ( 아래 명령어에서 app-front는 위에서 stack을 deploy할 때 사용했던 stack name이다 )
docker stack rm app-front
Config를 통한 설정값 관리
swarm service에 의해 실행되는 컨테이너들의 설정값 관리를 위해 config object를 사용할 수 있다. 예를 들어 config-front.json라는 json 파일을 통해 config object를 생성하고자 한다면 다음 명령어를 통해 생성할 수 있다 ( JSON 외에도 다른 데이터 포맷을 담을 수도 있다 )
docker config create config-front ./config-front.json
위의 명령어를 실행 후 docker config ls 명령어를 통해 생성된 config object를 확인할 수 있다. 이제 위에서 살펴본 YAML 설정 파일에 config 정보를 추가하여 replica가 실행될 때 우리가 생성한 config object의 내용이 실제 replica의 파일 시스템으로 옮겨 질수 있도록 해야 한다.
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs
ports:
- 4000:4000
configs:
- source: config-front
target: /app/config/config-front.json
deploy:
replicas: 2
configs:
config-front:
name: config-front
external: true
설정 값을 하나씩 살펴보자
configs:
config-front:
name: config-front
external: true
우리는 상단에서 여러 설정 정보를 가지고 있는 config-front.json 파일을 통해 config-front라는 이름의 config object를 생성했다. 위의 설정은 앞서 생성한 config-front라는 config object를 사용하겠다는 의미이다.
services:
front-nextjs:
image: app-front-nextjs
ports:
- 4000:4000
configs:
- source: config-front
target: /app/config/config-front.json
deploy:
replicas: 2
그리고 위에서 configs property를 통해 replica가 실행되는 컨테이너 파일 시스템에서 /app/config/config-front.json라는 파일을 만들어 config-front라는 config-object 설정파일의 내용을 전달한다.
위의 설정 파일을 기준으로 다시 replica를 생성하고 container에 접속해 /app/config 경로를 확인해보면 config-front.json 파일에 전달한 config object 내용이 있는 것을 확인할 수 있다.
위의 같은 방법으로 다수의 replica가 실행되어도 동일한 config object를 공유하며 사용할 수 있다. 주의할 점은 config object는 민감한 정보를 보관할 수단은 아니다. 다음 명령어를 통해 config obejct를 조회해보면 내용을 그대로 확인할 수 있기 때문이다.
docker config inspect --pretty config-front
그렇기에 민감한 정보는 비밀값을 생성하여 config object와는 별개로 관리해야 한다
비밀값 관리하기
비밀값을 생성하는 방법은 config object와 유사한 점이 있지만 비밀값은 실제 비밀값을 사용하는 컨테이너 안에서만 복화화 되어 확인할 수 있으며 그 전까지는 암호화되어 관리된다.
다음 명령어를 통해 비밀값을 생성해 보자
docker secret create secret-front ./secret-front.json
위의 예제에서는 비밀 값의 정보를 가진 secret-front.json 파일을 기반으로 secret-front라는 이름의 비밀 값을 생성했다. 그리고 생성한 비밀 값을 docker secret inspect --pretty secret-front 명령어로 조회해 봐도 비밀값에 대한 메타데이터만 나올 뿐 실제 데이터는 확인할 수 없다.
이제 생성한 비밀값을 사용할 수 있도록 YAML파일을 다시 수정해보자
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs
ports:
- 4000:4000
configs:
- source: config-front
target: /app/config/config-front.json
secrets:
- source: secret-front
target: /app/config/secret-front.json
deploy:
replicas: 2
configs:
config-front:
name: config-front
external: true
secrets:
secret-front:
name: secret-front
external: true
위에서 생성한 secrets을 위의 설정과 같이 추가하였다. 위의 설정 파일을 기준으로 다시 replica를 생성하여 실행하면 secret 정보 역시 실행되는 container의 파일 시스템 중 target property로 설정한 위치에 secret-front.json 파일이 생성되어 확인할 수 있다. ( 컨테이너에선 다시 암호가 복호화 되어 정상적으로 값을 확인할 수 있다 )
config 또는 비밀값을 사용할 때 주의할 점은 swarm에선 기존에 있는 config 또는 비밀값을 수정하진 못한다. 만약 config 또는 비밀값을 수정하고자 한다면 새로운 config 혹은 비밀값을 만들고 YAML 파일도 새로운 config, 비밀값으로 업데이트하여 servcie stack을 다시 배포하여 적용해야 한다.
Application 업데이트
만약 yaml 파일로 구성된 swarm replica application을 업데이트 해야 할 때는 어떻게 할까? 방법은 아래와 같이 단순하다. 새로운 yaml 파일을 기준으로 기존 stack을 override하는 형식으로 업데이트한다
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs:v2
ports:
- 4000:4000
deploy:
replicas: 2
...
...
예를들어 frontend applicaton이 업데이트 되어 version 2 image로 새로 배포해야 한다면 swarm yaml 파일은 위와 같이 version 2의 image를 기반으로 수정되었을 것이다.
그리고 수정된 yaml 파일로 기존의 stack을 다시 배포한다
docker stack deploy -c ./stack-front.yml app-front
stack이 다시 배포되면 기존의 replica가 종료되면서 version 2의 image 기반의 replica가 생성되어 실행되는 것을 확인할 수 있을 것이다. 하지만 실제 application을 배포하는 상황에선 새로 만든 image에 버그가 있어 container가 정상적으로 작동되지 않을 수도 있다. 만약 새로 배포하는 stack replica에 문제가 있으면 rollback할 수 있는 옵션 역시 swarm yaml 파일에 지정해 줄 수 있다.
업데이트 실패시 rollback 설정
아래의 예제를 살펴보자
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs:v2
ports:
- 4000:4000
deploy:
replicas: 2
update_config:
parallelism: 1
monitor: 30s
failure_action: rollback
order: start-first
위의 예제에서 볼 수 있듯이 update_config의 property를 통해 롤링 업데이트의 세부 과정을 설정할 수 있다.
parallelism : replica 교체 시 한 번에 교체되는 replica 숫자
monitor : 교체할 새로운 컨테이너의 이상 여부를 검사하는 시간
failure_action : monitor에 설정한 시간 내에 새로 실행되는 replica에 문제가 발생하면 어떤 후속 조치를 취할 것인지 설정. 위 처럼 rollback으로 설정하면 stack을 새로 배포하기 전의 version으로 rollback 된다.
order : replica를 교체하는 순서를 설정. stop-first가 default 값이며 기존 replica를 중지하고 새로운 replica를 생성 및 실행하는 반면 위처럼 start-first로 지정하면 새로운 replica를 먼저 생성 및 실행하고 기존 replica를 중지한다.
위의 예제와 같이 update_config를 설정해주고 다시 stack deploy를 실행하는 과정 중에 새로운 image가 문제가 있어 replica가 정상적으로 실행되지 않는다면 swarm은 자동으로 rollback을 진행하고 수정하기 이전 image로 replica를 다시 생성하여 실행한다.
여기서 주의할 점은 만약 rollback이 되어 다시 replica가 실행되면 해당 replica는 container에 사용된 image 뿐만 아니라 이전 deploy에 사용된 yaml 설정파일 기준으로 생성된다. 예를 들어서 처음 swarm stack yaml 파일이 다음과 같고
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs:v1
ports:
- 4000:4000
deploy:
replicas: 2
update_config:
parallelism: 1
monitor: 10s
failure_action: rollback
order: stop-first
새로운 swarm stack yaml 파일이 다음과 같다.
version: "3.7"
services:
front-nextjs:
image: app-front-nextjs:v2
ports:
- 4000:4000
deploy:
replicas: 2
update_config:
parallelism: 1
monitor: 30s
failure_action: rollback
order: start-first
이때 새로운 swarm stack의 기준 image가 되는 app-front-nextjs:v2에 문제가 있어 replica 실행해 실패하면 rollback이 되고 rollback이 되어 새롭게 생기는 replica는 image만 v1로 rollback되는 것이 아니라 deploy, update_config등 yaml 파일 전체의 내용이 rollback되고 이전 yaml 파일의 내용을 기반으로 새로운 replica가 생성된다.
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)