IT/기초 지식

[Docker] Docker 기초(3)

개발자 두더지 2021. 5. 7. 15:20
728x90

 일본의 블로그 글을 번역한 포스팅입니다. 오역과 직역이 있을 수 있으며 내용 오류가 있다면 지적해주시면 감사합니다.

 

 

이 포스팅을 통해서 알 수 있는 것


 이미지나 컨테이너등의 기본부터 docker-compose, docker-machine, docker swarm 등 Docker과 관계된 다양한 개념의 전체 관계도를 정리하고, Dcoker의 구조를 이해하기 위한 포스팅이다.

 

 

Docker Machine


 Docker Machine는 Docker Engine을 탑재한 가상 머신의 관리(작성, 실행, 정지, 재실행 등)를 커맨드라인을 통해서 실행할 수 있는 툴이다.

 Mac OS의 경우는 가상 소프트웨어(Virtual Box)를 드라이브로 사용하여 Docker Engine을 탑재한 가상 머신을 관리하는 것이 Docker Machine이다. 

 아래의 그림은 PC내의 여러 개의 docker-machine을 실행하여, 그 중에 한 컨테이너를 실행하는 등의 docker 기능이 이용할 수 있게 되어 있는 이미지가 된다.

 또한 docker-machine에 의해 실행된 Docker Engine이 동작하고 있는 가상 머신을 Docker 호스트라고 부른다.

 위 그림은 Local 머신 안에 여러 개의 Docker 호스트가 세워져 있는 이미지처럼되어 있지만, 물론 리모트 서버에 Docker 호스트를 세울 수 있다.

 

Docker Machine의 관리 커맨드

docker 호스트의 목록 확인

$ docker-machine ls

Docker 호스트를 생성

$ docker-machine create —driver virtualbox 호스트머신에붙일이름

지정한 이름으로 새로운 Docker 호스트를 생성한다. -driver옵션은 가상 소프트웨어를 지정하기 위해서 사용한다.

Docker 호스트 실행

$ docker-machine start 호스트머신명

Docker 호스트 정지

$ docker-machine stop 호스트명

지정한 Docker호스트를 조작 대상으로 하기 위한 환경 변수의 목록을 표시

$ docker-machine env 호스트머신명

이 환경변수를 설정하는 것으로, 조작대상의 docker호스트를 변경할 수 있다.

Docker호스트를 Active하기

$ eval $(docker-machine env 호스트가상머신명)

지정한 Docker 호스트에 가상변수를 설정한다. 

환경변수를 설정하면 지정한 호스트 가상 머신이 Active가 된다.

반대로 docker호스트의 액티브 선택을 해제하기 위해서는 설정한 환경 변수를 삭제할 필요가 있다.

Docker호스트를 비(非)액티브하기

$ docker-machine env -u

위 커맨드로 환경변수를 삭제하기 위한 커맨드가 표시된다.

-u는 unset이라는 옵션이다.

$ eval $(docker-machine env -u)

이 커맨드로 현재 Active인 Docker 호스트를 비(非)액티브로 할 수 있다.

Docker 호스트에 ssh를 접속

$ docker-machine ssh Docker호스트명

Docker 호스트의 IP확인

$ docker-machine ip Docker호스트명

Docker 호스트상에서 컨테이너를 실행

Docker 호스트가 액티브인 상태에서 아래의 커맨드를 실행시켜먼 Active한 Docker 호스트 위에서 컨테이너가 실행된다.

$ docker run 이미지명

 

 

클라우드 서비스에서의 Docker 호스트 프로비저닝


Docker Machine을 사용하여 local의 커맨드라인으로부터 AWS나 GCE등에 Docker Machine을 탑재한 가상머신(Docker호스트)를 작성하거나 관리할 수 있게 된다.

아래는 하나의 예로 Docker Machine을 사용하여 AWS EC2상에 Docker호스트를 세우는 순서를 간단하게 기재하였다.

1. AWS의 IAM로부터 docker-tset혹은 적당한 이름을 붙여서 액세스 인증 키를 취득

액세스 키ID : -----------------
시크릿 액세스 키: ----------------------

2. 그 인증키를 홈 템플릿의 ~/.aws 템플릿에 생성한 credentials파일에 기재한 뒤

$ docker-machine create --driver amazonec2 --amazonec2-open-port 8000 --amazonec2-region ap-northeast-1 가상머신명

이 커맨드로 driver를 amazonec2로 지정한 가상머신에 가상머신을 세운다.

3. 아래의 커맨드로 AWS에 세운 가상머신(docker호스트)를 액티브한 상태로 변경

 

$ docker-machine env AWS상에 세운 가상머신명
$ eval $(docker-machine env AWS가상머신명)

4. 이미지로부터 컨테이너를 세운다.

$ docker run 이미지명

5. 가상 머신IP를 확인한다.

$ docker-machine ip Docker호스트명

참고로 아래의 커맨드는 가상 머신을 정지시키는 것이고,

$ docker-machine stop Docker호스트명

그 다음은 가상 머신을 삭제하는 것이다. 물론 그 외 다른 조작도 가능하다.

$ docker-machine rm Docker호스트명

 

 

Docker Swarm


Docker Swarm은 여러 대의 Docker호스트머신 사이에서의 컨테이너간 통신을 설정 혹은 관리를 자동화해주는 방법 중 하나 이다 (컨테이너 오케스트레이션 엔진).

컨테이너 오케스트레이션 엔진에는 Docker Swarm외에 Kubernetes나 DC/OS등이 있지만, 여기서는 Docker Swarm에 대해서 살펴보자.

Docker Engine의 동작 모드 중 하나로 Swarm Mode가 있다.

Swarm Mode는 아래와 같이 두 가지 기능이 존재한다.

클러스트 관리 기능 : 여러 대의 머신을 네트워크 연결하여 하나의 시스템으로써 관리하는 기능

오케스트레이션 기능: 여러 대의 머신을 자동적으로 관리해주는 기능(부하분산, 컨테이너 실행 등)

보다 알기 쉽게 설명하자면,

Docker Swarm은

1. Docker호스트머신 사이에 네트워크를 연결한다.

2. 그 다음 "여러 개의 호스트 머신"과 "그 안에 동작하는 컨테이너들"을 관리, 운영하기 위해 다양한 기능을 제공한다.

(이전 포스팅에서 등장했던 Docker Network는 하나의 Docker호스트 안에서의 컨테이너들을 연결하는 네트워크이다)

1, 2의 내용에 대해서 조금 더 구체적으로 살펴보도록 하자.

 

1. Docker호스트머신들을 네트워크로 연결하기

Docker Swarm가 먼저하는 부분이 "여러 개의 Docker호스트 머신을 네트워크로 연결하여, Swarm이라는 하나의 시스템으로 만드는 것"이다.

구체적으로는 생성된 Swarm에 Docker호스트머신을 소속시켜, Swarm내의 노드가 된 Docker호스트는 Ingress 오버레이네트워크라는 네트워크로 상호 연결된다.

노드에는 다음과 같이 두 가지 노드가 있다.

1. 컨테이너를 실행하는 역할을 가진 worker노드

2. 컨테이너를 실행하는 역할 + 다른 노드를 관리하는 역할을 하는 manager노드

 

Swarm의 관리 커맨드

Swarm클러스터의 생성

$ docker-machine ip [Docker호스트명]
$ docker swarm init --advertise-addr 다른 노드와 통신이 가능한IP(위에서 확인한IP)

manager노드가 되는 호스트머신이 Active한 상태로 실행하여 Swarm클러스터를 작성한다.

Swarm클러스터에 소속되어 있는 노드 목록을 표시

manager노드로 아래의 커맨드로 확인할 수 있다.

$ docker node ls

Swarm클러스터에 worker노드를 추가

manager노드가 Active한 상태에서 아래의 커맨드를 실행시키면,

$ docker swarm join-token worker

아래와 같은 커맨드가 표시된다.

$ docker swarm join --token [토큰] [IP]

이 상태에서 다음과 같은 커맨드를 실행시키면 worker노드할 Docker호스트를 Active로 한 후에 실행된다.

$ eval $(docker-machine env [worker노드로 할docker 호스트명])

Swarm클러스터에 manager노드 추가하기

위에서 본 worker노드의 추가했던 맨 처음의 커맨드를 아래와 같이 살짝 수정한다.

$ docker swarm join-token manager

나머지는 위와 동일하다.

<주의점>

Swarm에서 사용되는 포트번호는 아래와 같다.

- 클러스터 관리 통신용:TCP 2377

- 노드간 통신용:TCP/UDP 7946

- 오버레이 네트워크 트래픽용 : UDP 4789

Swarm에 소속되는 Docker호스트(노드)는 반드시 위의 포트를 열어두어야한다는 점을 주의해야한다.

 

2. 다양한 관리 기능

Docker호스트를 연결하는 네트워크를 Swarm이라는 형식으로 구축하게 됨으로써 다양한 관리 기능을 사용할 수 있게 된다.

보통, Web시스템의 실제 환경 서버는 1대의 머신이 아닌, 여러 개의 머신을 합쳐서 인터넷을 통해 User가 보낸 리퀘스트를 처리하고 있다.

이 여러 대의 머신을 Docker machine이라는 툴으로 실행, 관리하고 더욱이 Docker호스트 머신을 상호 연결하여, 하나로 엮어 관리해 시스템의 실제환경에서 외부로 부터 들어온 리퀘스트를 부하를 분산하거나 운영에 알맞은 다양한 기능을 제공하는 것이 Docker Swarm이다.

 

1) Serivce와 Task에 의한 Docker호스트를 거친 컨테이너의 실행

먼저 Docker Swarm에서는 Service와 Task를 사용하여 Docker호스트를 통한 컨테이너의 실행, 관리를 할 수 있다. 

Service이란 "어떤 노드에 어떤 이미지로부터 몇 개의 컨테이너를 실행시킬 것인가"를 정의한 것이며, 한편 Task는 "Service를 바탕으로 실제 컨테이너를 실행하는 1개 1개의 지시"를 의미한다.

서비스는 manager노드에서 생성된다.

예를 들어 

$ docker service create --replicas 3 nginx

이 커맨드로 manager노드가 "nginx이미지로부터 컨테이너를 3개 실행하는" 서비스를 작성한 경우에, "nginx이미지로부터 컨테이너를 실행"이라는 Task가 3개 존재하는 것이 된다.

ㄴService를 사용하여 컨테이너를 각각의 Docker호스트머신에서 실행하는 것이 아닌, 한 번에 실행하는 것이 가능하며, 어떤 컨테이너를 어떤 노드에서 실행하는가(Task의 분산)을 자동적으로 결정해준다.

이로 인해 서비스를 통해 작성된 태스트를 각 노드에 나누는 기능을 스케줄링이라고 부른다.

별도의 지정이 없는 경우에는, CPU나 메모리의 빈 공간 상황에 따라 스케줄링되므로, 유저는 어떤 Docker호스트에 배치할 것인가를 관리할 필요가 없다.

노드의 Availability

 Swarm클러스터에 소속되어 있는 노드 목록은 아래의 커맨드로 확인이 가능하다.

$ docker node ls

 각 노드는 Availability이라는 상태를 가지고 있고, Availability는 다시 Active, Pause, Drain이라는 세 종류로 나뉜다.

 Active는 "스케줄러가 노드에 태스크를 할당하는 것이 가능한 상태"이고 Pause는 "스케줄러가 노드에 태스크를 할당할 수는 없지만, 기존의 태스크는 그대로 계속 실행할 수 있는 상태", 마지막으로 Drain은 "스케줄러가 노드에 태스크를 할당할 수 없고, 기존의 태스크도 종료된 상태"이다. 

 이러한 상태에 따라 스케줄러는 Task를 할당할지 말지를 결정한다. 또한, 아래의 커맨드로 지정된 node의 Availability를 변경하는 것이 가능하다.

$ docker node update --availability [변경하고 싶은 상태] [노드명]

글로벌 모드와 replica모드

 replica모드는 지금까지 보아왔듯, --replicas3과 같이 서비스 작성시에 실행하고 싶은 업무를 지정할 수 있는 모드이다. 한편, 글로벌 모드는 반드시 1개에 노드에 1개의 Task를 실행하고 replica수의 지정을 실시하지 않는 모드이다.

$ docker service create --name web3 --mode global nginx

 위의 커맨드와 같이 글로벌 모드에서는 replica갯수를 지정하지 않아도, 모든 노드에 1개씩 Task가 실행된다.

 기본적으로는 replica mode가 실행된다.

Service관리 커맨드

서비스의 생성

$ docker service create --name [작성할 서비스명] --replicas [레플리카 갯수] [실행할 이미지명]
$ docker service create --name [생성할 서비스명] --constraint 'node.role==[manager혹은worker]' --replicas [레플리카 갯수] --detach=true [실행할 이미지]

이러한 커맨드와 같이 --constraint플래그를 붙여서, 서비스를 작성, 실행하는 것으로 Task분담처인 노드를 지정할 수 있다.

서비스 목록 확인

$ docker service ls

서비스의 상세를 표시

$ docker service inspect [서비스명]

$ docker service inspect —pretty [서비스명]

pretty플러그를 붙이면 읽기 쉬운 형태로 표시해준다.

이미 생성된 서비스의 설정을 변경할 수 있도록 하기

$ docker service update —publish-add 8000:80 —detach=true [서비스명]

지정한 서비스를 한 단계전의 상태로 복원하기

$ docker service ps [서비스명]

서비스의 삭제

$ docker service remove [서비스명]

 

2) 롤링 업데이트

Web시스템을 운영하고 있으면, 시스템에 사용하고 있는 소프트웨어의 version을 반드시 update해줘야 하는 경우가 생긴다.

Swarm으로 여러 개의 Docker호스트를 관리하고 있는 시스템 운영을 하고 있는 경우, 서비스의 태스크를 모아서 갱신하는 것이 아닌, 연장 기간을 설정하여 1개의 태스크씩 update할 수 있도록 하는 것이 "롤링 업데이트"라는 기능이다.

이 기능을 통해, 실행중의 컨테이너를 남겨두고, 해당 컨테이너에서 리퀘스트를 받으면서 순서대로 다른 컨테이너를 update해나갈 수 있다. 

아래의 커맨드는 redis의 업데이트의 예이다.

$ docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6

이와 같이 서비스를 생성할 때에, update-delay플러그로 update의 시간차를 설정할 수 있다. 병렬갱신하는 태스크의 최대수를 설정하는 플래그도 있다.

업데이트를 할 경우에는 아래의 커맨드로 롤링 업데이트를 실시할 수 있다.

$ docker service update —image redis:3.0.7 redis 

 

3) Service scale / Resource management / Auto Scaling

Swarm으로 운영하고 있는 시스템 전체의 부하가 커지게 되면, 서비스 전체로써 실행하는 컨테이너의 수를 늘리는 것이 가능하다. 

$ docker service scale [서비스명]=[레플리카 갯수]

또한 위 커맨드로 지정한 서비스의 레플리카 갯수를 변경할 수 있다. 물론 오토 스케일링을 설정하는 것도 가능하다. 

애당초 머신 리소스 자체가 부족해진 경우에는, 머신(AWS에 있어서는 인스턴스)자체를 추가하고 실행하면 된다.

 

4) Auto Healing

대량의 리퀘스트로 인한 과도한 부담이 있는 등으로, Swarm내의 노드가 다운되어버린 경우네는 그 머신에서 실행되고 있던 컨테이너를 다른 머신으로 대체되어 자동적으로 컨테이너가 실행되도록 Auto Healing이라는 기능이 있다.

Manager노드가 다운되어 버린 경우에도 여러 개의 manager노드를 준비하는 것과 같은 대응이 가능하다.

 

 

Docker compose에 의한 Service의 생성


$ docker service create 커맨드로 서비스를 작성해왔지만, 서비스의 생성 조차도 docker-compose.yml  에 기재하여 파일에 정의한 여러 개의 서비스를 자동적으로 생성할 수 있다.

docker-compose.yml에는 아래와 같이 작성한다.

version: '3.4' # docker-compose의 기재 형식의 version지정

services: # 실행할 컨테이너를 기재해나간다
  wordpress: #wordpress컨테이너
   image: wordpress # wordpress:latest이미지의 사용
   ports:
    - 8080:80 # 포트의 머신의 8080번을 외부에 공개하여, 그것을 컨테이너의 80번 포트에 연결한다.
   environment:
    WORDPRESS_DB_PASSWORD: ----- # mysql컨테이너의 PW와 일치시킨다.
   deploy: # 여기에서 부터 Docker Swarm의 Service설정한다.
    replicas: 2 #레플리카 갯수
    placement:
      constraints: 
       - node.role == worker # worker노드만으로 실행
   depends_on:
     - mysql # mysql으로 부터 아까 실행한 설정

  mysql: #mysql컨테이너
   image: mysql:5.7 # 사용할 이미지 지정
   environment:
    MYSQL_ROOT_PASSWORD: ----- # 패스워드 설정
   volumes:
    - mysql_vol:/var/lib/mysql # mysql_vol이라는 volume을 생성하여, 컨테이너 상의 지정한 디렉토리에 마운트
   deploy: # 여기에 Docker Swarm의 Service를 설정한다.
    replicas: 1
    placement:
     constraints:
      - node.role == manager # manager노드의 실행

volumes:
  mysql_vol: #volume의 설정

 그 다음, 아래와 같이 $ docker stack deploy 커맨드를 사용하여, docker-compose.yml파일로부터 Swarm에 있어서의서비스를 생성할 수 있다.

$ docker stack deploy --compose-file docker-compose.yml(compose파일의 지정) [작성할 스택명]

스택명은 생성될 서비스명의 접두사가 된다.

stack의 관리 커맨드

스택 생성

$ docker stack deploy --compose-file [compose파일명] [작성할 스택명]

스택의 목록 표시

$ docker stack ls

스택의 삭제

$ docker stack remove 스택명

참고자료
qiita.com/etaroid/items/40106f13d47bfcbc2572

728x90

'IT > 기초 지식' 카테고리의 다른 글

[Singularity] Singularity란?  (0) 2021.05.21
[Docker] Docker 이미지 튜토리얼  (0) 2021.05.10
[Docker] 자주 사용하는 Docker 커맨드 모음  (0) 2021.04.21
[Docker] Docker 기초(2)  (0) 2021.04.05
[Docker] Docker 기초(1)  (0) 2021.04.04