Gom3rye 2025. 6. 26. 17:52

Docker-Compose : 하나의 머신에서만 동작 (따라서 scale up이 의미가 없다.)

scale up이 이루어지려면 머신이 2개 이상은 있어야 한다.

  • 네트워크 확인 → Ingress와 bridge가 추가됨
docker node ls
docker network ls
  • 새로운 토큰 발급
docker swarm join-token --rotate worker # 다 보이고
docker swarm join-token -q worker # 토큰만 보이고
  • 다음 에러를 만나면 방화벽이나 네트워크 연결을 확인하기
Error response from daemon; rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 매니저IP주소:2377: connect: no route to host
*RPC(Remote Procedure Call) eroor 로 원격으로 일을 시키고 있는데 연결이 잘 안되고 있다는 뜻
  • worker 제거
    • manager에서 수행
    docker swarm leave 워커이름
    
    • worker에서 수행 (이름 쓸 필요 없다.)
    docker swarm leave
    

모니터링 도구

dockersamples/visualizer

  • 설치
docker service create --name=viz_swarm --publish=7070:8080 --constraint=node.role==manager --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock dockersamples/visualizer

8080 포트를 개방하면 대부분 아파치 톰캣 서버를 사용 -> 자바 사용

grid 데이터를 분산해서 엮어놓는 것

rdbms는 분산된 데이터를 가져와서 join이나 set을 한다.

  • 포트 쓰고 있는지 확인
sudo netstat -nlp | grep 7070
  • 서버 확인
포트포워딩 해서 192.168.202.9:7070 으로 접속
# GUI를 설치한 경우는 자신의 브라우저에서 localhost:7070을 이용
  • swarmpit
    • 설치
    docker run -it --rm --name swarm-installer --volume /var/run/docker.sock:/var/run/docker.sock swarmpit/install:1.9
    

서비스 생성과 삭제

3초마다 콘솔에 메시지를 출력하는 서비스를 생성

docker service create --name swarm-start alpine:3 /bin/ash -c "whlie true; do echo 'Docker Swarm mode Start.'; sleep 3; done"
  • 제대로 안 깔려서 지우고 싶으면
docker stack rm swarmpit
# docker stack ls, docker service ls, docker ps -a로 확인 가능
docker rmi swarmpit/install:1.9 # 태그도 써줘야 한다.
  • 서비스 목록 조회
docker service ls
  • 실행 중인 컨테이너 조회
docker service ps swarm-start
  • 로그 확인
docker service ls
docker service ps swarm-start
docker service logs -f {serviceID}

만약 잘 안 만들어진다면 docker login 으로 로그인하고 난 후에 다시 해보자!

nignx를 이용한 서비스 컨테이너 배포와 관리

  • nginx를 2개의 replic(복제본)로 배포
    • 혹시 모르니까 docker pull nginx 해놓고
    docker service create --name web-alb --constraint node.role==worker --replicas 2 --publish 8081:80 nginx
    
    • nginx 이미지를 가지고 컨테이너를 생성하는데 worker 노드에 2개 생성을 하고 이 서비스 이름은 web-alb가 된다.
      • replicas 1로 했을 때 worker2로 간다고 치면 worker1, 2모두에서 curl이 되는데 worker1에서는 docker ps 했을 때 없다.
      • 컨테이너가 여기 없더라도 돌아들어가서 얘한테 간다. (가지고 있다 없다는 큰 의미가 없다.)
      • 서비스가 만들어질 때 포트포워딩한 8081번 포트가 매니저와 노드 모두에서 개방이 된다.
    • 외부에서 접근할 때는 manager를 통해서 접근한다. (worker를 이용해서 접근이 안되는 것은 아니지만 이렇게 하면 Load Balancing이나 Proxy의 의미가 없어지며 worker의 개수가 여러 개일 때 어떤 worker에 컨테이너가 만들어지는 지 알 수 없기 때문이다.)
    • node.role=worker : worker에만 생성된다.
    • 이미지 다운로드가 안되면 worker1과 worker2에서 docker pull nginx를 수행하고 실행
  • 서비스를 조회 & 컨테이너 확인
  • docker service ls docker service ps web-alb
  • 모든 컴퓨터에서 8081이 열려있는지 확인
  • sudo netstat -nlp | grep 8081

→ docker service 명령으로 서비스를 생성할 때 여러 개의 컨테이너를 생성하면 컨테이너가 배치된 모든 노드의 포트가 동시에 개방이 된다.

  • 매니저 노드에서 docker service rm web-alb를 하면 worker1, worker2에 떠있던 컨테이너 다 자동으로 소멸된다.

이미지

Image: disk에 저장되기 때문에 자동 소멸되지 않는다.

  • Container: 메모리에 존재하기 때문에 자동 소멸 된다.

Volume: docker-engine이나 hard disk에 데이터를 보관하려고 사용하는 것 → 자동 소멸 x

  • Network: container를 묶기 위해서 쓰는 것 → 자동 소멸 가능

실제로 load balancing을 해주는지 확인해보기

  • 2개의 컨테이너를 생성
docker service create --name web-alb --constraint node.role==worker --replicas 2 --publish 8081:80 nginx

  • worker1에서 수행 (코드를 수정해보면 로드밸런싱이 되는지 안되는지 알 수 있다.)
    • vi index.html
    <h1>Hello - Docker Swarm worker1</h1>
    
    • docker ps로 컨테이너 이름 확인
      • web-alb.1.kt64fwu0qra90fu8il1o5odx3
    docker cp index.html web-alb.1.kt64fwu0qra90fu8il1o5odx3:/usr/share/nginx/html/index.html
    #
    Successfully copied 2.05kB to web-alb.1.kt64fwu0qra90fu8il1o5odx3:/usr/share/nginx/html/index.html
    
  • worker2에서 수행 (코드 수정)
    • vi index.html
    <h1>Hello - Docker Swarm worker2</h1>
    
    • docker ps로 컨테이너 이름 확인
      • web-alb.2.zs0lah6j3lekwf0209fvp5dqc
    docker cp index.html web-alb.2.zs0lah6j3lekwf0209fvp5dqc:/usr/share/nginx/html/index.html
    ##
    Successfully copied 2.05kB to web-alb.2.zs0lah6j3lekwf0209fvp5dqc:/usr/share/nginx/html/index.html
    

동적으로 scale을 변경하는 것이 가능하다.

docker service scale 서비스이름=replicas 숫자

  • docker service ps web-alb 로 확인 가능

If 축소하고 싶다면

docker service scale web-alb=replicas

docker service rm 후

모든 애들에게 배치하고 싶다면 replicas 대신에 --mode global을 선택해서 생성

docker service create --name global_nginx --mode global nginx

서비스 유지 관리를 위한 기능 (롤링 업데이트)

  • 기본적으로 대부분의 오케스트레이션 도구는 장애 복구 기능을 내장하고 있다.
  • 도커 스웜 모드 클러스터에서는 장애 대비를 할 수 있는 --replicas 기능을 제공하고 배포된 서비스 장애 및 노드의 장애가 발생하면 자동으로 복제 수만큼의 서비스를 맞추어 장애에 대한 자동 복구를 수행한다.
  • 패키지 버전 변경 수행 시 서비스를 중단하지 않고 롤링 업데이트 기능을 사용하면 새 버전 서비스 컨테이너는 하나씩 늘려가고 이전 버전 서비스 컨테이너는 하나씩 줄여가는 방식으로 버전 업데이트를 수행할 수 있다. → 롤링 업데이트
  • 업데이트가 실패하면 다양한 기능을 통해 재시도 및 업데이트 중지 등을 선택 수행할 수 있고 잘못된 업데이트를 취소하기 위해 롤백 기능도 제공한다.

실습

  • 서비스 배포
docker service create --name web-alb --replicas 3 --publish 8001:80 nginx
  • 서비스 확인
docker service ls
  • 실제 컨테이너 확인
docker service ps web-alb

  • worker1(컨테이너가 배치된 노드에서 수행)에서 배포된 컨테이너를 삭제
    • docker rm -f 컨테이너이름 또는 아이디
    • manager에서 docker service ps web-alb 해보면 하나의 컨테이너가 shutdown으로 되어 있고 이와 동시에 새로운 컨테이너가 만들어지는 걸 확인할 수 있다. (자동 → 우리가 할 필요 없음)

Redis로 Rolling Update 실현

  • 서비스 생성
docker service create --name my-database --with-registry-auth --replicas 3 redis:6.0-alpine
  • 확인
docker service ps my-database
  • 롤링 업데이트가 되는지 업데이트 해보기
    • 이미지 버전 업데이트로 변경하면서 체크
docker service update --image redis:6.2.5-alpine my-database

→ 예전 거가 shutdown 되어 있고 새로운 것들로 대체되어 있다.

→ worker1에 보면 이전 꺼 지워진 것은 아니다.

  • 롤링 업데이트 옵션
--update-failure-action
--update-max-failure-ratio
--update-monitor
--update-order
--update-parallelism
  • 서비스의 상세 정보 확인
docker service inspect --pretty my-database

→ rollback 관련, container 스펙 나온다.

  • 업데이트 옵션을 추가한 서비스 생성
docker service create --name my-database2 --with-registry-auth --replicas 4 --update-delay 10s --update-parallelism 2 redis:6.0-alpine

→ 업데이트 할 때 10초 대기하고 한 꺼번에 2개씩 업데이트

  • 이미지를 바꿔보기
docker service update --image redis:6.2.5-alpine my-database2

(롤백을 하기 위해서 남아 있다.)

→ 내 서비스가 구동되는 데 오래 걸린다면 옵션을 적절히 잘 사용해야 한다.

  • 롤백하기 (이미지를 변경하는 업데이트 수행)
docker service rollback my-database2

  • 몇 개의 버전을 저장하고 있는지 확인
    • docker info 명령을 수행하고 Task History 부분을 확인
    • 만약 변경이 자주 일어난다면 Task History의 개수를 늘릴 필요가 있다.
docker swarm update --task-history-limit 개수

특정 노드를 업데이트에서 제외

  • 특정 노드의 계획된 유지관리(대부분 하드웨어 교체 작업 및 정기 점검 등)를 수행하기 위해 업데이트 등의 작업에서 제외하는 경우가 있는데 이러한 작업을 drain이라고 한다.
  • nginx로 서비스를 생성
docker service create --name my-web --with-registry-auth --replicas 3 nginx:1.19

→ 인증 정보 넘어가도록 --with-registry-auth 붙여주기

→ 항상 만들고 난 이후에는 docker service ps my-web으로 확인해보기

  • worker2를 drain
docker node update --availability drain swarm-worker2
  • 노드 확인
docker node ls

  • 업데이트 수행
docker service update --image nginx:1.21 my-web
  • worker2를 다시 활성 모드로 변경
docker node update --availability active swarm-worker2

→ 다시 활성 모드로 돌아오더라도 기존 컨테이너는 재배치 되지 않는다.

  • scale 조정으로 재배치
docker service scale my-web=1
docker service scale my-web=3
docker service ps my-web

Stack 배포

도커 스웜 스택은 클러스터 환경에 여러 서비스를 묶어서 하나의 스택 공간을 생성하는 것

  • Docker Stack은 분산 애플리케이션의 최상위 계층
  • 3 Tier Model
    • Front End
    • Back End
    • Database

실습

  • 스택에서 사용할 클러스터 네트워크인 오버레이를 생성 (dailylog-net)
docker network create --driver overlay 이름
docker network create --driver overlay dailylog-net
  • 스택 작업을 위한 디렉토리 생성
mkdir dailylog && cd $_ # 만들고 바로 이동
  • 스택 배포를 위한 yaml 파일을 생성하고 작성
version: "3.9"
services:
  mongodb:
    image: dbgurum/dailylog:Db_1.0
    ports:
      - 17017:27017

    networks:
      - dailylog-net
    deploy:
      placement:
        constraints: [node.role != manager]
      restart_policy:
        condition: on-failure # 정상 종료가 아닌 장애 발생시 재시작 조건
        max_attempts: 3 # 재시작 시도 최대 횟수
        delay: 10s # 재시작 시도 사이의 지연시간
        window: 120s # 재시작 정책을 평가하는데 사용되는 시간

  ㅑ frontend:
    image: dbgurum/dailylog:front_1.0
    ports:
      - 3000:8000
    networks:
      - dailylog-net
    environment:
      - PORT=8000
      - DAILYLOG_API_ADDR=backend:8000
    deploy:
      replicas: 2
      placement:
        constraints: [node.role != manager]
      restart_policy:
        condition: on-failure
        max_attempts: 3
        delay: 10s
        window: 120s
    depends_on:
      - backend

  backend:
    image: dbgurum/dailylog:backend_1.0
    networks:
      - dailylog-net
    environment:
      - PORT=8000
      - DAILYLOG_DB_ADDR=mongodb:27027
    deploy:
      replicas: 2
      placement:
        constraints: [node.role != manager]
      restart_policy:
        condition: on-failure
        max_attempts: 3
        delay: 10s
        window: 120s
    depends_on:
      - mongodb

networks:
  dailylog-net:
    external: True
  • 배포
docker stack deploy --compose-file 파일경로 스택이름
docker stack deploy --compose-file daily-log.yml dailylog

중요! backend와 frontend는 replicas 가 있지만 db는 없음!

728x90
반응형