[Docker] Swarm stack for compose Develop Tip

현재 컨테이너의 de facto 표준은 Kubernetes 라고 누구나 이야기를 합니다.
그런데 몇년 전만 하더라도 Swarm, Mesos 등과 같이 어떤 것이 표준이 될지
잘 모르는 상화이었죠.

그런데 말입니다, docker로 개발을 할때 다음과 같은 수순을 밟습니다.

2) 큰 부분을 다시 작은 MSA 구성을 나눕니다.
3) 일반적으로 하나의 MSA 구성의 결과는 하나의 Docker Image 로 나뉩니다.
3.1) DB 저장소는 다음과 같은 것들을 이용합니다.
 - 일반적인 설정 정보 (설정 정보는 저장공간을 크게 차지하지는 않지만 해당 내용은 자주 변경됨) => MongoDB
 - 로그 이벤트 등의 정보 (수정되는 것은 적으나 지속적으로 늘어나고 검색해야하는 데이터) => MySQL
 - 특정 시각에 어떤 값을 가지는 시계열 정보 => InfluxDB
4) 여러 팀으로 나뉘어 작업할 경우 각자 원하는 프로그래밍 언어로 (polyglot) 해당 개발을 하고 단위테스트를 진행합니다.
4.1) VM (linux, Windows) 등에서 우선 MSA 단일 개발을 하고 잘 동작하는지 확인합니다.
4.2) 단일 작업에 대한 단위테스트를 꼭 진행합니다.
4.3) API 로 외부에 노출된다면 해당 API 단위 테스트를 꼭 진행합니다.
4.4) 해당 작업을 Dockerfile을 만들어 Docker Image 로 만듦니다.
      (기본 Base image로 Ubuntu, Debian, Fedora, alpine 등 적절히 선택합니다. 필요 시 기존에 쌓아 올린 많은 
       Docker image 가 존재하므로 docker hub 에서 잘 검색합니다. 기본 제공하는 이미지가 아닌 경우에는,
       꼭 해당 Dockerfile을 확보하여 이후에 DockerHub에사 사라지는 경우가 있어도 대비해야 합니다)
5) Docker Compose로 단일 개발 환경에서 여러 MSA 구조를 모두 합쳐 잘 동작하는지 확인합니다.
5.1) 대부분 외부에 노출되는 것은 Frontend 접속 port 등 이므로 해당 포트를 잘 확인합니다.
5.2) DB 저장소 서비스는 포트는 테스트 목적으로 외부에 노출 시킬 수 있지만 실제 운영 시 제외
5.3) API 테스트 같은 경우에는 특정 테스트 container를 두어 정상적으로 테스트하고 종료되는지 확인
5.4) UI 테스트 등도 자동으로? 


위와 같은 방식으로 지금까지 여러 프로젝트 등을 잘 동작시켰지만, 문제는 그 다음에 실제로 
Deploy 시키고 동작시키는 과정입니다.

위에 5까지 잘 했다면 이미 1대의 Docker Host에서 잘 동작하는 docker-compose.yml 이 
생성된 상황입니다.
이제부터는 어떤 것이 가장 docker-compose.yml 에서 쉽게 오케스트레이션 되는지 확인해 봐야 하는데,
아주 깊게는 아니고 살펴본 결과 kube는 kompose 등이 있어 kube에 맞는 service가 생성된다고 하는데
조금 살펴본 결과 버전 문제도 존재하고 쉽지 않다고 생각이 들어, 
docker swarm을 확인해 보았습니다.

결론은 docker 에서 공식적으로 지원하는 swarm을 이용해도 웬만한 것은 충분하다는 것입니다.
다음과 같은 장단점이 있을 수 있겠네요.

장점:
- docker 에서 기본으로 지원하므로 아주 쉽게 동작가능
- Kube 보다는 상대적으로 적은 사이즈의 오케스트레이션 (하지만 5000 개의 노드를 붙여서 서비스 한다는 것이 있으니 이 정도면...)
- docker compose 와 아주 gracefully 오케스트레이션 가능
- 쉽게 멀티 클라우드 적용 가능

단점:
- kube 보다는 상대적으로 적은 레퍼런스
- 최대 동작하는 컨테이너 사이즈가 kube 등에 비해서 적음 (그러나 수천개 까지는 가능)
- kube 등의 활발히 이루어지는 add-in 솔루션 등이 적음 (하지만 직접 연결 가능)
- 최근에는 극복하는 게 나왔을 지 모르겠으나 마스터 노드의 Single point failure 문제 가능

이 정도일 것 같습니다.

작업 환경 구성을 위해서 작업할 것인데 kube 등에 비하면 정말로 심플합니다.

0) swarm 설치
예전에는 별도 설치를 해야 했었던 것으로 기억하지만, 최근 (2019년6월현재) 에는 docker 안에 기본적으로 포함되어 있습니다.
설치할 필요 없습니다.

1) 노드 구성
1.1) 마스터 노드 생성
docker swarm init --advertise-addr 192.168.100.110
(위에서 마스터 노드의 IP 주소가 192.168.100.110 인 경우 입니다)

1.2) 작업 노드 추가
docker swarm join \
    --token tokey_key_... \
    192.168.100.110:2377
(위에서 token_key... 는 swarm init 시에 나오는 key 입니다)

재미난 것은 join 할 노드가 VM이건, 빠르건 느리건 상관없이 모두 가능하다는 것입니다.
이것의 장점은 AWS EC2 이건 다른 public 클라우드 이건 상관없이 IaaS에서 노드를 만들어 
멀티 클라우드에도 쉽게 오케스트레이션 할 수 있다는 장점이 됩니다.
(kube 도 있을 텐데 쉽게 하는 방법이 있으면 알려주십시오)

1.3) 노드 확인
마스터 노드에서 다음 명령어로 가능합니다.

docker node ls
ID                           HOSTNAME              STATUS  AVAILABILITY  MANAGER STATUS
y8ul9r3jq0rgt9k3vbvrayeyg *  dh-u110  Ready   Active        Leader
lrt89xwkugty162qk8c2av5ek    dh-u120  Ready   Active        Reachable
yqerq5ujds38t0izzlp03dbhd    dh-u130  Ready   Active        Reachable


다음은 직접 docker-compose.yml 파일을 수정해 가면서 기억해 두어야 만할 것을 기록해 봅니다.

우선 yaml 파일의 마지막에 network를 다음과 같이 기술했습니다.

networks:
  default:
   ipam:
     driver: default
     config:
     - subnet: 172.18.0.0/16
  backend:
    ipam:
      #driver: overlay
      #attachable: true
      config:
      - subnet: 172.20.0.0/16
  toa:
    ipam:
      driver: default
      #driver: overlay
      #attachable: true
      config:
      - subnet: 172.19.0.0/16

각각 필요한 네트워크를 정의하고 해당 네트워크 주소 대역을 지정했습니다.
시작할 때마다 네트워크 대역이 변하면 곤란한 경우도 때론 있습니다.

  my_tftp:
    image: mcchae/tftp-server
    container_name: my_tftp
    ports:
    - "69:69/udp"
    volumes:
    - /home/toor/work/dhv/tftp:/data
    networks:
    - toa

위와 같은 정상 서비스에 다음과 같은 내용이 추가 되면 됩니다.

    deploy:
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.role == manager]
      resources:
        limits:
          cpus: '0.10'
          memory: 50M
        reservations:
          cpus: '0.05'
          memory: 20M

deploy 라는 항목은 "docker stack deploy" 명령을 내릴 때 비로소 반영되는 것입니다.
(왜 resource 제한이 안될까 의아해 했었는데요..)

- replicas 에 개수를 지정해 줌으로써 초기 컨테이너가 몇개까지 뜨고 관리되는 가를 나타냅니다.
- 재미난 것은 placement에 [node.role == manager] 라고 지정하는 것인데, 이렇게 하면 마스터 노드에만 deploy 되고,
  [node.role != manager] 라고 하면 마스터를 제외한 곳에 deploy 됩니다.

위와 같은 식으로 다른 모든 서비스도 손을 봐 줍니다.

그리고,

docker stack deploy -c docker-compose.yml d

와 같이 실행시키면, 자동으로 알아서 d 라고 prefix가 붙어 각각의 서비스가 실행되고,
복제되고 배포됩니다.

외부에 노출되는 포트는 자동으로 모든 노드에 export 되며, 어느 노드에서 접근해도 자동으로 내부적으로 
모든 노드에 분배되어 서비스 됩니다. (물론 해당 노드개수 만큼 충분하게 export 시킨 서비스가 replica 되어 있다는
가정에서 입니다.)

처음에는 잘 될까? 의심을 하며 차근 차근 조심스럽게 deploy를 하다가, 잘 되는 것을 확인하고는,
단일 Docker Host에서 작업하던 docker-compose 를 쉽게 분배시킨 것에 불과하다고 깨닫고는
어느곳에던 배포할 수 있겠다는 자신감을 얻었습니다.


어느 분께는 도움이 되셨기를 ...

핑백

덧글

댓글 입력 영역

구글애드텍스트