관리 메뉴

KorSA

Docker Swarm을 띄워보았다 본문

Development Experience/*Ops

Docker Swarm을 띄워보았다

Praiv. 2022. 3. 18. 16:07
320x100

회사에서 Kubernetes 대신 Docker Swarm으로 Orchestration을 하기로 결정되었다.

상대적으로 시간이 여유로운 내가 Docker Swarm을 담당하게 되었다.

여러개의 프로젝트를 Docker Swarm 환경에 띄우면서 겪은 삽질을 기록겸 공유겸 남겨둔다..

 

 

#00. 순서

1. docker-compose.yaml 파일로 Docker Image를 BUILD

2. Docker Swarm Manager, Worker 등록

3. Docker Swarm Manager Node에서 Private Repository 구동

4. docker stack deploy 명령을 통해 Docker Swarm 상에 Docker Image들을 구동

 

 

#01. docker-compose.yaml 파일로 Docker Image를 BUILD

Spring Boot 프로젝트를 빌드하면 JAR 파일이 나온다.

이 JAR 파일을 Docker에서 실행시키려면 우선 Docker Image 형태로 바꿔주어야 한다.

우리 팀은 여러개의 프로젝트를 Docker에 띄워야 했기 때문에 관리의 편의성을 위해

각 프로젝트의 root 경로에 Dockerfile을 작성하였다.

 

[ Dockerfile ]

FROM openjdk:17

RUN mkdir -p /app
RUN mkdir -p /var/log

WORKDIR /app
ADD /target/my-product.jar app.jar

VOLUME ["/var/log"]

EXPOSE 9090

ENTRYPOINT ["java", "-jar", "app.jar"]

 

그리고 Docker Compose 기능으로 각 프로젝트를 한번에 Build하여 Docker Image를 생성하였다.

 

 

[ 여러 프로젝트를 한번에 Build하기 위한 Docker Compose 파일 (docker-compose.yaml) ]

version: "3"

services:
  my-product:
    build: ./my-product/.
    image: my_product
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
    networks:
      - my_net
      
  my-product-2:
    build: ./my-product-2/.
    image: my_product_2
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
    networks:
      - my_net
	  
networks:
  my_net:

※ 여기서 services > my-product > build 경로는 각 프로젝트의 Dockerfile이 위치한 경로이다.

 

 

[ Dockerfile을 이용한 Docker Image 빌드 명령 ]

docker-compose build

# 이전 build에서 cache된 내용들을 무시하고 새로 빌드하고 싶다면 --no-cache 옵션을 주어야 한다
docker-compose build --no-cache

※ 이 명령어는 docker-compose.yaml 파일이 위치한 경로에서 실행되어야 한다.

    만일 다른 명령을 실행하는 위치와 파일의 위치가 다를 경우 -f 옵션을 주어서 직접 파일을 지정해야 한다.

 

 

Docker Image 빌드가 완료되면 Image 목록을 출력해서 잘 생성되었는지 확인해볼 수 있다.

docker images

 

빌드된 Image를 실행해보아도 좋다.

docker-compose up -d

# 만약 최신 Docker Image로 빌드되어 있지 않다면 --build 옵션을 주어야 최신 작업이 적용된다
# 이거 몰라서 이틀정도 삽질..
docker-compose up -d --build

 

#02. Docker Swarm Manager, Worker 등록

Docker Swarm을 사용하려면 여러 대의 host 중 방장을 뽑아야 한다.

이 방장을 Manager라고 부르고 나머지를 Worker라고 부른다. 

그리고 Manager와 Worker를 Node라고 부른다.

 

게임을 할 때 방장이 방을 파는 것처럼,

Manager는 Swarm 방을 파서 다른 Worker들이 접속할 수 있는 공간을 제공한다.

# (Manager Node) Docker Swarm 방 파기
docker swarm init --advertise-addr 192.168.10.10

 

이 방에 다른 Node들이 접근할 수 있도록 Docker Swarm에서 사용하는 포트들의 방화벽을 풀어주는 것도 잊지말자.

# (Manager Node) 방화벽 해제
sudo firewall-cmd --permanent --add-port=2377/tcp
sudo firewall-cmd --permanent --add-port=7946/tcp
sudo firewall-cmd --permanent --add-port=7946/udp
sudo firewall-cmd --permanent --add-port=4789/udp
sudo firewall-cmd --reload

 

 

위에서 "docker swarm init" 명령을 실행하면 콘솔창에 "docker swarm join 어쩌구" 하는 문구가 나온다.

이 문구를 Worker Node에서 그대로 실행하면 Manager가 파 놓은 방에 참여하게 되고

Swarm 클러스터의 기본 형태가 갖추어진다.

# (Worker Node) Manager의 Swarm 방에 참여
docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 192.168.10.10:2377

 

Manager는 Worker들이 방에 잘 참여했는지 확인해볼 수 있다.

docker node ls

 

 

#03. Swarm Manager Node의 Private Repository

자, 이제 예상대로라면 Manager에서 Docker Image를 Container 형태로 띄우면

이 Container들이 Manager Node 뿐만 아니라 Worker Node에서도 구동이 되어야 한다.

 

But..!!

 

이 상태에서 Manager node의 Docker Image를 구동시키면 Worker node 에서는 "no such image" 라는 에러가 뿜뿜한다. 이 현상을 해결하기 위해 Manager node에서 Private Registry라는 걸 운용해줘야 한다.

 

Worker Node 입장에서는 모든 Docker Image가 Manager Node에 있기 때문에 어디선가 Image를 가져와야 한다.

 

이 통로 역할을 Manager Node의 Private Registry가 해주는데 꼭 Private Registry를 사용할 필요는 없다.

 

Manager Node가 Docker Hub같은 Public Registry에 Docker Image를 PUSH하고

Worker Node가 Public Registry에서 PULL 받아도 된다.

 

하지만 우리 프로젝트는 추후 사업화되면 폐쇄망에서 동작할 예정이기 때문에 Private Registry를 사용했다.

 

어떤 친절한 개발자분이 Private Registry Image를 Docker Hub에 올려주셨기 때문에 우리는 그냥 가져다가 구동만 시켜주면 된다.

 

# Docker Hub에서 registry 이미지 다운로드
docker image pull registry

# registry 실행
docker run -dit --name registry -p 5000:5000 registry

# Worker Node에서 사용할 image를 tagging 및 PUSH
docker image tag my-product localhost:5000/my-product
docker image push localhost:5000/my-product

 

이렇게 Manager Node의 Private Registry에 이미지가 올라가면 Worker Node는 추후 이 이미지를 다운로드받을 수 있다. 이 때 Worker Node에서 Private Registry의 이미지를 받으려면 /etc/docker/daemon.json 파일에서 Manager Node를 보안 예외처리 해주어야 한다.

 

# (Worker Node) /etc/docker/daemon.json
{
        "insecure-registries": ["192.168.10.10:5000"]
}

 

이렇게 파일을 바꿔주고 docker를 재시작하자.

systemctl stop docker
systemctl restart docker

 

 

#04. docker stack deploy 명령을 통해 Docker Swarm에서 Docker Container 구동

자, 이제 정말로 Docker Swarm 구동을 위한 준비가 끝이 났다.

#01에서 보았던 docker-compose.yaml을 다시 사용할 것이다.

 

하지만 이번엔 build 명령이 아닌 deploy 명령을 쓰자.

# (Manager Node) docker stack deploy -c {Compose 파일} {Stack 이름}
# --with-registry-auth > Worker Node가 Manage Node에 접근할 수 있도록 권한을 부여하는 옵션
docker stack deploy --with-registry-auth -c docker-compose.yaml my-stack

 

이제 Container들이 잘 떴는지 확인해보자.

# (Manager Node) 생성된 stack 확인
docker stack ls

# (Manager Node) docker-compose.yaml에서 설정한 각 service들의 상태 확인
docker service ls

# (Manager Node) docker container들의 상태 확인
docker ps -a
# (Worker Node) docker container 상태 확인
docker ps -a

 

명령어를 계속 치기 귀찮다면 watch 명령어를 쓰면 좀 더 편하게 볼 수 있다.

# 1초마다 화면 clear 및 docker ps -a 명령 실행
watch -n 1 docker ps -a

 

 

 

 

728x90
728x90
Comments