서비스
단일 도커 호스트에 대한 컨테이너 배포는 docker container run 명령으로 컨테이너를 일일히 실행하거나 컴포즈를 사용해 여러 컨테이너를 동시에 실행하는 방법이 있다.
어떤 특정한 문제를 해결하기 위해 만들어진 애플리케이션은 단일 컨테이너 혹은 여러 컨테이너로 구성될 수도 있으며 그것들이 복제된 집합으로 이루어졌을 수도 있다. 이렇게 애플리케이션을 구성하는 일부 컨테이너를 제어하기 위한 단위로 서비스라는 개념이 생겨났다.
$ docker container exec -it manager \
> docker service create --replicas 1 --publish 8000:8000 --name echo registry:5000/example/echo:latest
hbp13rv25bk0yo8em0kufpjpk
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
위와 같이 서비스는 manager 컨테이너에서 docker service create 명령으로 생성한다.
서비스를 제어하는 레플리카를 늘려보자. docker service scale 명령으로 해당 서비스의 컨테이너 수를 늘리거나 줄일 수 있다. 여러 노드에 걸쳐 컨테이너 수를 조정할 수 있으므로 스케일 아웃을 적용할 때 유용하다.
$ docker container exec -it manager docker service scale echo=6
echo scaled to 6
overall progress: 6 out of 6 tasks
1/6: running [==================================================>]
2/6: running [==================================================>]
3/6: running [==================================================>]
4/6: running [==================================================>]
5/6: running [==================================================>]
6/6: running [==================================================>]
verify: Service converged
스웜 클러스터 위에서 동작하는 컨테이너를 확인해 보았을 때, echo 컨테이너 6개가 실행 중이다. NODE 칼럼을 통해서 서비스가 스웜 클러스터의 노드를 분산 배치했음을 알 수 있다.
$ docker container exec -it manager docker service ps echo | grep Running
jk1uln3wxq1b echo.1 registry:5000/example/echo:latest 760fa825ec6b Running Running 3 minutes ago
zsodk5p9pcie echo.2 registry:5000/example/echo:latest 469231dcd4dc Running Running about a minute ago
z5e6wjel4bay echo.3 registry:5000/example/echo:latest ce8f7af60cff Running Running about a minute ago
nmxq3c0y0wtb echo.4 registry:5000/example/echo:latest ce8f7af60cff Running Running about a minute ago
yuvpkt3xt5v4 echo.5 registry:5000/example/echo:latest 760fa825ec6b Running Running about a minute ago
pqoysqluso4r echo.6 registry:5000/example/echo:latest 7e4ff2b8f9d5 Running Running about a minute ago
배포된 서비스는 docker service rm 서비스명 명령으로 삭제할 수 있다.
$ docker container exec -it manager docker service rm echo
echo
$ docker container exec -it manager docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
서비스가 레플리카 수를 늘리라고 지시하면 자동으로 컨테이너를 복제하고 이를 여러 노드에 배치한다.
스택
스택은 하나 이상의 서비스를 그룹으로 묶은 단위로, 애플리케이션 전체 구성을 정의한다. 여러 서비스를 사용하게 되면 여러 이미지를 다룰 수 있어서 다양한 애플리케이션을 구성할 수 있다. 스택은 말하자면 스웜에서 동작하는 스케일 인, 스케일 아웃, 제약 조건 부여가 가능한 컴포즈다.
스택을 사용해 배포된 서비스 그룹은 overlay 네트워크에 속한다. 스택에서 overlay 네트워크를 설정하지 않으면 스택마다 서로 다른 overlay 네트워크를 생성하고 그 안에 서비스 그룹이 속하게 된다. 어떤 서비스가 다른 overloay 네트워크에 속한 다른 서비스를 발견할 수 없으므로 통신도 불가능하다.
*) overlay 네트워크: 여러 도커 호스트에 걸쳐 배포된 컨테이너 그룹을 같은 네트워크에 배치하기 위한 기술
클라이언트와 대상 서비스가 같은 overlay 네트워크에 있으면 통신이 가능하다. 다음과 같이 overlay 네트워크 ch03을 구성한 다음, 스택으로 만든 각 서비스를 소속시킨다. 스택 역시 스웜과 마찬가지로 manager 컨테이너에서 조작한다.
$ docker container exec -it manager docker network create --driver=overlay --attachable ch03
stack 디렉터리에 다음과 같이 ch03-webapi.yml 스택을 생성한다. 이 컨테이너는 환경 변수 BACKEND_HOST에 요청을 전송할 대상을 설정할 수 있는데, 스택으로 배포된 api 의 서비스명인 echo_api의 포트 8080을 설정한다. 스택 역시 서비스를 다루므로 replicas 값으로 레플리카 수를 조정할 수 있다. 또, placement 속성을 이용하면 컨테이너의 배치 전략을 설정할 수 있는데, 아래처럼 manager 이외의 노드에 컨테이너를 배치하도록 제약 부여가 가능하다.
version: "3"
services:
nginx:
image: gihyodocker/nginx-proxy:latest
deploy:
replicas: 3
placement:
constraints: [node.role != manager]
environment:
BACKEND_HOST: echo_api:8080
depends_on:
- api
networks:
- ch03
api:
image: registry:5000/example/echo:latest
deploy:
replicas: 3
placement:
constraints: [node.role != manager]
networks:
- ch03
networks:
ch03:
external: true
스택을 배포하려면 docker stack deploy 명령을 사용한다. 이 때 -c 옵션 값으로 스택 정의 파일 경로를 지정한다. stack 디렉터리는 manager 컨테이너의 /stack 디렉터리에 마운트 되므로 이 파일의 경로는 /stack/ch03-webapi.yml이 된다.
docker container exec -it manager docker stack deploy -c /stack/ch03-webapi.yml echo
아래 명령으로 스택에 배포된 서비스 목록을 확인할 수 있다.
$ docker container exec -it manager docker stack services echo
ID NAME MODE REPLICAS IMAGE PORTS
mgvpcmz8136v echo_api replicated 1/3 registry:5000/example/echo:latest
w80wn8blawab echo_nginx replicated 1/3 gihyodocker/nginx-proxy:latest
스택이 컨테이너 그룹을 어떻게 배포했는지 확인하려면 docker stack ps 명령을 사용한다.
$ docker container exec -it manager docker stack ps echo
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
r3xdw6zvvt77 echo_api.1 registry:5000/example/echo:latest 8083e6f3db89 Running Preparing 53 seconds ago
qy8n2serybqz \_ echo_api.1 registry:5000/example/echo:latest cf22a3cc4104 Shutdown Rejected 53 seconds ago "No such image: registry:5000/…"
fje81vzhpn3c echo_nginx.1 gihyodocker/nginx-proxy:latest cf22a3cc4104 Running Running 43 seconds ago
y0uts8vvbsu7 echo_api.2 registry:5000/example/echo:latest cf22a3cc4104 Running Preparing 53 seconds ago
leq42s8pj4a2 \_ echo_api.2 registry:5000/example/echo:latest 8083e6f3db89 Shutdown Rejected 53 seconds ago "No such image: registry:5000/…"
jdds0qvl2luw echo_nginx.2 gihyodocker/nginx-proxy:latest 8083e6f3db89 Running Running 43 seconds ago
0r1fk3hns1qg echo_api.3 registry:5000/example/echo:latest c963d6dcae06 Running Running about a minute ago
ofukw7lscl73 echo_nginx.3 gihyodocker/nginx-proxy:latest c963d6dcae06 Running Running about a minute ago
스웜 클러스터에 컨테이너 그룹이 어떤 노드에 배치됐는지 시각화해주는 visualizer라는 애플리케이션을 사용하여 컨테이너 배치 시각화를 할 수 있다.
아래 visualizer.yml파일을 stack 디렉토리 하위에 만든다.
version: "3"
services:
app:
image: dockersamples/visualizer
ports:
- "9000:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: global
placement:
constraints: [node.role == manager]
global 설정값은 특정 컨테이너를 클러스터 상의 모든 노드에 배치하라는 의미이다. constraints를 보면 manager노드에만 배치하도록 되어 있다. manager 노드의 포트 9000을 visualizer 컨테이너의 포트 8080으로 포트 포워딩을 설정하였고, 호스트와 manager사이에는 9000:9000 포워딩이 설정돼 있으므로 로컬 머신에서 viaulizer에 접근하려면 http://localhost:9000으로 접근하면 된다. 이제 이 설정대로 스택을 배포한다.
docker container exec -it manager docker stack deploy -c /stack/visualizer.yml visualizer
스택 삭제하기
docker stack rm 명령에 대상 스택명을 지정하면 배포된 서비스를 스택째로 삭제할 수 있다.
$ docker container exec -it manager docker stack rm echo
Removing service echo_api
Removing service echo_nginx
스웜 클러스터 외부에서 서비스 사용하기
visualizer 스웜 클러스터 외부에서 접근할 수 있다. 이것은 contraints 설정에서 visualizer 컨테이너가 반드시 manager에 배치되도록 했기 때문이다. 그러나 echo_nginx 서비스는 여러 컨테이너가 여러 노드에 흩어져 배치돼 있기 때문에 이 방법을 사용할 수 없다. 호스트에서 이런 서비스에 접근하기 위해서는 서비스 클러스터 외부에서 오는 트래픽을 목적하는 서비스로 보내주는 프록시 서버가 있어야 한다.
HAProxy 를 이 프록시 서버로 사용해 스웜 클러스터 외부에서 echo_nginx 서비스에 접근할 수 있게 해보자. HAProxy 이미지는 dockercloud/haproxy 이미지를 사용한다. 이 이미지로 만든 컨테이너는 컨테이너 외부에서 서비스에 접근할 수 있게 해주는 다리 역할 외에도 서비스가 매치된 노드에 로드 밸런싱 기능을 제공한다. stack 디렉터리에 다음과 같은 ch03-ingress.yml 파일을 생성한다.
version: "3"
services:
haproxy:
image: dockercloud/haproxy
networks:
- ch03
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: global
placement:
constraints:
- node.role == manager
ports:
- 80:80
- 1936:1936 # for stats page(basic auth.stats:stats
networks:
ch03:
external: true
HAProxy를 거쳐 서비스에 접근이 되는지 확인하기 위해 ch03-webapi.yml을 다시 이용하여 ngnix 환경 변수에 SERVICE_PORTS를 추가한다.
version: "3"
services:
nginx:
image: gihyodocker/nginx-proxy:latest
deploy:
replicas: 3
placement:
constraints: [node.role != manager]
environment:
SERVICE_PORTS: 80
BACKEND_HOST: echo_api:8080
depends_on:
- api
networks:
- ch03
api:
image: registry:5000/example/echo:latest
deploy:
replicas: 3
placement:
constraints: [node.role != manager]
networks:
- ch03
networks:
ch03:
external: true
ch03-webapi.yml을 스택 echo로 다시 배포한다.
$ docker container exec -it manager docker stack deploy -c /stack/ch03-webapi.yml echo
Creating service echo_nginx
Creating service echo_api
그다음 ch03-ingress.yml을 스택 ingress로 배포한다.
$ docker container exec -it manager docker stack deploy -c /stack/ch03-ingress.yml ingress
Creating service ingress_haproxy
이 때 서비스 배치 현황은 다음과 같다.
$ docker container exec -it manager docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
xgl7v8up1z2i echo_api replicated 3/3 registry:5000/example/echo:latest
fsi5n81krpfs echo_nginx replicated 3/3 gihyodocker/nginx-proxy:latest
l620yltq78y7 ingress_haproxy global 1/1 dockercloud/haproxy:latest *:80->80/tcp, *:1936->1936/tcp
ce80u96xahsr visualizer_app global 1/1 dockersamples/visualizer:latest *:9000->8080/tcp
호스트의 8000은 manager 컨테이너의 포트 80, 다시 말해 ingress의 HAProxy로 포트 포워딩 되므로 localhost:8000이 echo_ngnix:80에 접근할 수 있게 된다.
'클라우드 > 도커' 카테고리의 다른 글
도커 스웜 (0) | 2021.11.28 |
---|---|
컨테이너 실전 구축 및 배포 (0) | 2021.10.31 |
도커 컴포즈로 여러 컨테이너 실행하기 (0) | 2021.10.30 |
도커 컨테이너 (0) | 2021.10.17 |
도커 이미지와 컨테이너 기본 개념과 실행 (0) | 2021.10.17 |