Framework and Tool/Docker

Swarm mode tutorial

ocwokocw 2023. 10. 2. 12:03

- 출처: https://docs.docker.com/engine/swarm/swarm-tutorial/

- 출처: https://linux.how2shout.com/how-to-install-docker-on-amazon-linux-2023/

 

Getting started with swarm mode

Getting Started tutorial for Docker Engine swarm mode

docs.docker.com

 

- Create Amazon EC2 instances

Swarm mode tutorial 에서는 실습에서는 통신가능한 3대의 host 가 있다고 가정한다. 기본적인 실습은 1대의 host로도 가능하지만 일부 실습(ex - node 관련 부분)은 확인할 수 없다. 하지만 3대의 기기를 준비하기란 여간 귀찮은 것이 아니다. Amazon EC2 를 이용하면 이런 귀찮음을 상당부분 해소할 수 있다. Amazon EC2에서 3대의 linux machine을 생성하고 실습을 진행해보자.

Amazon 프리티어는 일정 기간동안 일정 사용량은 무료로 이용할 수 있다. 이번 실습에서 사용하기에는 충분하다. Amazon EC2 instance 시작을 클릭하고 아래 사항에 유의하여 3대를 생성해준다. (ver. Amazon Linux 2023)

  • 키 페어(로그인)을 설정 후 pem을 보관한다. 설정없이 진행하면 ssh 연결이 불가하다.
  • IP가 유동적인 환경이면 0.0.0.0 에서 ssh 트래픽을 허용한다.

설정을 완료하고 ssh 접속시 "Permissions xxxx for {pem file명} are too open error"과 같은 문구가 나오는 경우가 있다. 이럴 경우 chmod("chmod 400 {pem 파일명}")를 통해 pem 파일의 권한을 설정해주자.


- Install docker engine and configuration

Amazon Linux 2023 version에 docker engine을 설치해보자. 아래 단계를 통해 차근차근 진행해보자.

  • "sudo dnf update": 설치된 package update
  • "sudo dnf install docker": docker engine package 설치
  • "sudo systemctl start docker":시작 및 service 활성화
  • "sudo usermod -aG docker ec2-user": "ec2-user" 를 docker group에 추가하여 sudo 없이 docker 명령어 수행
  • "newgrp docker": 현재 session의 사용자 group을 변경
  • "docker run hello-world": test 이미지로 docker 설치 확인

위의 과정을 완료하면 기본적인 docker engine 설치가 끝난것이다. 하지만 docker swarm 을 실습해보려면 tutorial 문서에도 나와있듯이 network 관련해서 해주어야할 작업이 있는데 Amazon EC2 에서 보안 관련 탭에서 inbound port를 열어준다.

  • TCP 2377: manager node간 통신을 위한 port
  • TCP, UDP 7946: node 발견에 사용할 overlay network
  • UDP 4789: overlay network traffic

- Create docker swarm, Join to swarm

위의 과정을 모두 완료했다면 어떤 것을 배우는데 있어 가장 지루한 환경 설정을 완료한것이다. Manager node(아직 manager node는 아니지만 manager node로 지정할 EC2 node) 로 접속하여 "docker swarm init" 명령어를 수행한다.

[ec2-user@ip-172-31-36-249 ~]$ docker swarm init --advertise-addr 172.31.36.249
Swarm initialized: current node (mngf06jxen3uztf1ipxwbdd4k) is now a manager.

To add a worker to this swarm, run the following command:

	docker swarm join --token {Token} 172.31.36.249:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
  • "docker swarm init --advertise-addr 172.31.36.249"에서 --advertise-addr flag는 swarm의 다른 member들이 network로 접근할 때 어떤 주소로 접근해야하는를 지정한다.
  • 명령어의 결과로 나온 "docker swarm join --token {Token} 172.31.36.249:2377"에서 {Token}은 실제로는 임의의 문자열이 출력된다. 이 명령어를 복사하여 worker node에서 수행하면 manager node의 member로 join 하는데, {Token}이 노출되면 network에 접근 가능한 아무 member나 join 가능하므로 노출되면 안된다.

새성을 완료했다면 "docker node ls"를 통해 확인해보자.

[ec2-user@ip-172-31-36-249 ~]$ docker node ls
ID                            HOSTNAME                                           STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
mngf06jxen3uztf1ipxwbdd4k *   ip-172-31-36-249.ap-northeast-2.compute.internal   Ready     Active         Leader           24.0.5
  • ID 값 옆에 * 표시는 현재 접속한 node를 가리킨다.

Manager node를 생성했으니 2개의 node가 swarm에 참여하도록 명령어를 수행해주자.

[ec2-user@ip-172-31-46-128 ~]$ docker swarm join --token {Token} 172.31.36.249:2377
This node joined a swarm as a worker.

[ec2-user@ip-172-31-36-249 ~]$ docker node ls
ID                            HOSTNAME                                           STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
mngf06jxen3uztf1ipxwbdd4k *   ip-172-31-36-249.ap-northeast-2.compute.internal   Ready     Active         Leader           24.0.5
w9qqp173ppn90vo7erjnychaj     ip-172-31-45-73.ap-northeast-2.compute.internal    Ready     Active                          24.0.5
37ji937z46g8y154o594c7dhu     ip-172-31-46-128.ap-northeast-2.compute.internal   Ready     Active                          24.0.5

- Deploy a service to the swarm

3개의 node로 구성된 Swarm이 생성되었다. 이제 service를 배포해보자.

[ec2-user@ip-172-31-36-249 ~]$ docker service create --replicas 1 --name helloworld alpine ping docker.com
wwykti8gjkhss5bnazydb132c
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

[ec2-user@ip-172-31-36-249 ~]$ docker service ls
ID             NAME         MODE         REPLICAS   IMAGE           PORTS
wwykti8gjkhs   helloworld   replicated   1/1        alpine:latest

- Inspect a service on the swarm

"docker service inspect" 명령어를 이용하면 배포한 service의 상세 정보를 조회할 수 있다.

[ec2-user@ip-172-31-36-249 ~]$ docker service inspect --pretty wwykti8gjkhs

ID:		wwykti8gjkhss5bnazydb132c
Name:		helloworld
Service Mode:	Replicated
 Replicas:	1
Placement:
UpdateConfig:
 Parallelism:	1
 On failure:	pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Update order:      stop-first
RollbackConfig:
 Parallelism:	1
 On failure:	pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Rollback order:    stop-first
ContainerSpec:
 Image:		alpine:latest@sha256:eece025e432126ce23f223450a0326fbebde39cdf496a85d8c016293fc851978
 Args:		ping docker.com
 Init:		false
Resources:
Endpoint Mode:	vip

swarm이 3개의 node로 구성되어 있으므로 어떤 Node가 service를 실행하고 있는지 조회하는 방법도 알아보자.

[ec2-user@ip-172-31-36-249 ~]$ docker service ps helloworld
ID             NAME           IMAGE           NODE                                               DESIRED STATE   CURRENT STATE           ERROR     PORTS
8dr7ue4lx7ov   helloworld.1   alpine:latest   ip-172-31-36-249.ap-northeast-2.compute.internal   Running         Running 4 minutes ago

위 예제에서는 manager node에서 service가 수행되었다. manager node는 기본적으로 worker node의 역할도 하기 때문이다. service가 배포한 것도 결국 container이기 때문에 service가 수행되고 있는 node에서 docker ps로 조회하면 관련 정보가 조회된다.

[ec2-user@ip-172-31-36-249 ~]$ docker ps
CONTAINER ID   IMAGE           COMMAND             CREATED         STATUS         PORTS     NAMES
38dde37dcd58   alpine:latest   "ping docker.com"   6 minutes ago   Up 6 minutes             helloworld.1.8dr7ue4lx7ovak7clppe6xge2

- Scale the service in the swarm

이제 배포한 service가 수행할 container 수를 선언해본다. docker swarm 이 없다면 container가 각 Node들의 자원 상황을 고려하여 어떤 Node로 몇대가 배포되어야 하는지를 고려해야하는데, 내가 원하는 상태를 선언하기만 하면 docker swarm이 알아서 관리해주기 때문에 이 부분이 swarm을 사용하는 가장 주된 이유이기도 하다. 

service에서 수행되고 있는 container를 별도로 "task"라고 지칭한다. "docker service scale" 명령어를 통해 task의 수를 조절한다.

[ec2-user@ip-172-31-36-249 ~]$ docker service scale helloworld=5
helloworld scaled to 5
overall progress: 5 out of 5 tasks
1/5: running   [==================================================>]
2/5: running   [==================================================>]
3/5: running   [==================================================>]
4/5: running   [==================================================>]
5/5: running   [==================================================>]
verify: Service converged

[ec2-user@ip-172-31-36-249 ~]$ docker service ps helloworld
ID             NAME           IMAGE           NODE                                               DESIRED STATE   CURRENT STATE            ERROR     PORTS
8dr7ue4lx7ov   helloworld.1   alpine:latest   ip-172-31-36-249.ap-northeast-2.compute.internal   Running         Running 12 minutes ago
ladkm7p3ugim   helloworld.2   alpine:latest   ip-172-31-45-73.ap-northeast-2.compute.internal    Running         Running 51 seconds ago
b4j9n40zd6l3   helloworld.3   alpine:latest   ip-172-31-36-249.ap-northeast-2.compute.internal   Running         Running 54 seconds ago
4x1qkcyy3q5w   helloworld.4   alpine:latest   ip-172-31-46-128.ap-northeast-2.compute.internal   Running         Running 51 seconds ago
dcozcxp2mx0d   helloworld.5   alpine:latest   ip-172-31-45-73.ap-northeast-2.compute.internal    Running         Running 50 seconds ago

위는 기존에 생성한 helloworld를 5대의 task로 scale-out 하였다.


- Delete the service

마지막으로 helloworld service를 삭제하는 명령어를 통해 기본적인 실습을 마쳐보도록 하자.

[ec2-user@ip-172-31-36-249 ~]$ docker service rm helloworld
helloworld