클라우드를 사용한 Docker 실행 환경 구축
Post에 앞서 이번 Post의 내용과 실습은subicura 블로그의 내용과 개념을 그대로 따라해본 것 입니다.
분산 환경에서의 컨테이너 운용 관리
이전 Post에서는 멀티호스트 환경과 클러스터링에 대해서 얘기하였다.
이제 더 나아가서 멀티호스트로 구성된 실제 환경을 클러스터 구성으로 가동시키려면 컨테이너의 시작 및 정지와 같은 조작뿐만 아니라 호스트 간의 네트워크 연결이나 스토리지 관리, 컨테이너를 어떤 호스트에서 가동할지와 같은 스케줄링, 컨테이너가 정상적으로 작동하고 있는지 아닌지를 감시할 장치도 필요하다.
이러한 기능을 갖추고 컨테이너를 통합 관리할 수 있는 툴을 컨테이너 오케스트레이션 툴 이라고 한다.
컨테이너 오케스트레이션 툴 종류
- Kubenetes: Google의 엔지니어를 중심으로 하는 커뮤니티에서 개발 진행
제공하는 기능도 풍부하고 개발 속도도 빠르며, 대규모 시스템에서의 도입 실적도 풍부하다.
컨테이너 오케스트레이션 툴의 실질적 스탠드라고 할 수 있다.
(Kubernete에 관련되서는 따로 공부해서 하나의 Category로서 Post할 생각입니다.) - Docker Engine(Swarm): Docker에서 클러스터링 기능을 제공하는 Swarm모드 이다.
여러개의 컨테이너를 멀티호스트 환경에서 작동시키고, 그 컨테이너들을 모아서 하나의 명령으로 조작할 수 있다.
(현재 Post에서는 Swarm을 오케스트레이션 툴로서 선정하고 실습한다.) - Apache Mesos, Marathon: 여서 호스트의CPU나 메모리, 디스크를 추상화하여 하나의 리소스 풀로서 다룰 수 있는 것이 특징이다.
단, Mesos를 사용하여 컨테이너 오케스트레이션을 가동시키려면 별도의 컨테이너 고나리용 프레임워크가 필요하다.
이러한 대표적인 프레임워크로는 Marathon이 있고, 이름 그대로 장기간에 걸쳐 계속 작동하는 애플리케이션의 실행이나 모니터링이 가능하다.
참고사항: 용어 정리
컨테이너 오케스트레이션의 기능에 대해서 정확한 개념과 용어의 의미가 부족해서 찾아본 결과이다.
스케줄링: 컨테이너를 적당한 서버에 배포해 주는 작업입니다. 툴에 따라서 지원하는 전략이 조금씩 다른데 여러 대의 서버 중 가장 할일 없는 서버에 배포하거나 그냥 차례대로 배포 또는 아예 랜덤하게 배포할 수도 있습니다. 컨테이너 개수를 여러 개로 늘리면 적당히 나눠서 배포하고 서버가 죽으면 실행 중이던 컨테이너를 다른 서버에 띄워주기도 합니다.
클러스터링: 여러 개의 서버를 하나의 서버처럼 사용할 수 있습니다. 클러스터에 새로운 서버를 추가할 수도 있고 제거할 수도 있습니다. 작게는 몇 개 안 되는 서버부터 많게는 수천 대의 서버를 하나의 클러스터로 만들 수 있습니다. 여기저기 흩어져 있는 컨테이너도 가상 네트워크를 이용하여 마치 같은 서버에 있는 것처럼 쉽게 통신할 수 있습니다.
서비스 디스커버리: 말 그대로 서비스를 찾아주는 기능입니다. 클러스터 환경에서 컨테이너는 어느 서버에 생성될지 알 수 없고 다른 서버로 이동할 수도 있습니다. 따라서 컨테이너와 통신을 하기 위해서 어느 서버에서 실행중인지 알아야 하고 컨테이너가 생성되고 중지될 때 어딘가에 IP와 Port같은 정보를 업데이트해줘야 합니다. 키-벨류 스토리지에 정보를 저장할 수도 있고 내부 DNS 서버를 이용할 수도 있습니다.
로깅, 모니터링: 여러 대의 서버를 관리하는 경우 로그와 서버 상태를 한곳에서 관리하는게 편합니다. 툴에서 직접 지원하는 경우도 있고 따로 프로그램을 설치해야 하는 경우도 있습니다. ELK와 prometheus등 다양한 툴이 있습니다.
Docker Swarm 용어 정리
Docker Swarm에 들어가기 앞서 Docker Swarm에서 사용하는 용어에 대해 정리하고 실습을 하자.
용어 | 설명 |
스웜(Swarm) | 군중이라는 의미로서 스웜 클러스터 자체를 스웜이라 한다.(스웜을 만들다 = 클러스터를 만들다, 스웜에 가입하다 = 클러스테어 가입하다.) |
노드(Node) | 스웜 클러스터에 속한 도커 서버의 단위이다. 보통 한 서버에 하나의 도커데몬만 실행하므로 서버가 곧 노드이다. 노드의 종류는 매니저 노드와 워커 노드가 있다. |
매니저노드(Manage Node) | 스웜 클러스터 상태를 관리하는 노드. 매니저 노드는 곧 워커노드가 될 수 있으나, 워커노드와의 차이점은 스웜 명령어는 매니저 노드에서만 실행된다. |
워커노드(Worker Node) | 매니저 노드의 명령을 받아 컨테이너를 생성하고 상태를 체크하는 노드 |
서비스(Service) | 기본적인 배포 단위, 하나의 서비스는 하나의 이미지를 기반으로 생성하고 동일한 컨테이너를 한개 이상 실행할 수 있다. |
테스크(Task) | 컨테이너 배포 단위, 하나의 서비스는 여러개의 테스크를 실행할 수 있고 각각의 테스크가 컨테이너를 관리 |
Docker Swarm 기능 정리
위에서 컨테이너 오케스트레이션의 기능으로서 크게 스케줄링, 클러스터링, 서비스 디스커버리, 로깅, 모니터링 으로서 나누었다.
이러한 기능이 Docker Swarm에서는 어떻게 적용되는지 알아보고 추가적으로 다른 기능에 대해서도 알아보자.
스케줄링(Scheduling): 서비스를 만들면 컨테이너를 워커노드에 배포한다. 노드에 라벨을 지정하면 특정 노드에만 배포할 수 있고 모든 서버에 한 대씩 배포하는 기능도 제공한다. 서비스별로 CPU, Memory사용량을 미리 정의할 수 있다.
고가용성(High Available): 여러개의 매니저 노드를 운영할 수 있다. 만약 3대의 매니저 노드를 사용하면 1대가 죽어도 클러스터는 정상적으로 동작하며 매니저 노드를 지정하는 방법은 간단하므로 쉽게 관리할 수 있다.
멀티 호스트 네트워크(Multi Host Network): Overlay network로 불리는 SDN(Software Defined Network)를 지원하며 여러 노드에 분산된 컨테이너를 하나의 네트워크로 묶을 수 있다. 컨테이너마다 독립된 IP가 생기고 서로 다른 노드에 있어도 할당된 IP로 통신할 수 있다.
서비스 디스커버리(Service Discovery): 자체 DNS 서버를 가지고 컨테이너를 생성하면 서비스명과 동일한 도메인을 등록하고 컨테이너가 멈추면 도메인을 제거한다. 여러 노드에 분산된 컨테이너가 멀티호스트 네트워크로 묶이기 때문에 DNS를 가지고 바로 접근할 수 있다.
순차적 업데이트(Rolling Update): 서비스를 새로운 이미지로 업데이트 하는 경우 하나하나 차례대로 업데이트 한다. 동시에 업데이트하는 작업의 개수와 업데이트 간격 시간을 조정 가능하다.
상태체크(Health Check): 서비스가 정상적으로 실행되었는지 확인하기 위해 컨테이너 실행 여부 뿐 특정 쉘 스크립트가 정상적으로 실행됐는지 여부를 추가로 체크 가능. 컨테이너 실행 여부로만 체크한 경우 아직 서버가 실행 되지 않아 접속시 오류가 날 수 있는 미묘한 타이밍을 잡는데 효과적이다.
비밀값 저장(Secret Management): 비밀번호를 스웜 어딘가에 생성하고 컨테이너에서 읽을 수 있다. 비밀 값을 관리하기 위한 외부 서비스를 설치하지 않고 쉽게 이용 가능하다.
로깅(Logging): 같은 노드에서 실행 중인 컨테이너뿐 아니라 다른 노드에서 실행 중인 서비스의 로그를 한곳에서 볼 수 있다. 특정 서비스의 로그를 보려면 어느 노드에서 실행 중인지 알 필요도 없고 일일이 접속하지 않아도 된다.
모니터링(Monitoring): 리소스 모니터링 기능은 제공하지 않는다. 3rd party 서비스(prometheus, grafana)를 사용해야 한다
Docker Swarm 준비
현재 Linux기반의 Ubuntu(CLI)에서 실습 환경을 구축하였습니다.
1. VritualBox 설치
#VirtualBox 설치
apt-get install virtual box
#VirtualBox 설치 확인
vboxmanage --version
5.2.32_Ubuntur132056
2. Vagrant 설치
Vagrant 는 VirtualBox, VMWare, Parallels같은 가상머신을 쉽게 만들고 관리해주는 툴 이다.
#Vagrant 설치
wget -c https://releases.hashicorp.com/vagrant/2.2.4/vagrant_2.2.4_x86_64.deb
sudo dpkg -i vagrant_2.2.4_x86_64.deb
#Vagrant 설치 확인
vagrant -v
Vagrant 2.2.4
3. vargrant-hostsupdater 설치
vargrant-hostsupdater는 vargrant up
할때 yml파일에 정의된 ip와 host명을 자동으로 hosts파일에 추가하고, vargrant halt
하면 자동으로 삭제 해주는 플러그인 이다.
#vargrant-hostsupdater 설치
vagrant plugin install vagrant-hostsupdater
Installing the 'vagrant-hostsupdater' plugin. This can take a few minutes...
Fetching: vagrant-hostsupdater-1.1.1.160.gem (100%)
4. 데모 파일 다운로드
subicura Git에 접속하여 Docker swarm demo파일 다운로드
git clone https://github.com/subicura/docker-swarm-demo.git
cd docker-swarm-demo
5. 가상 Machine 생성
vargrant-hostsupdater로 인하여 DockerFile에 정의된 ip와 host명을 자동으로 할당하여 Dockerfile에 정의된 Machine을 만들게 된다.
#Dockerfile을 기반으로 Machine 생성
vagrant up
Bringing machine 'core-01' up with 'virtualbox' provider...
Bringing machine 'core-02' up with 'virtualbox' provider...
Bringing machine 'core-03' up with 'virtualbox' provider...
==> core-01: Box 'coreos-alpha' could not be found. Attempting to find and install...
core-01: Box Provider: virtualbox
core-01: Box Version: >= 0
...
#상태 확인
vagrant status
Current machine states:
core-01 running (virtualbox)
core-02 running (virtualbox)
core-03 running (virtualbox)
This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.
Docker Swarm 클러스터
현재 core-01 ~ core-03까지의 3개의 가상머신이 생성되었다.
하나의 매니저 노드와 매니저 노드가 생성한 토큰을 가지고 워커 노드에서 매니저 노드로 접속하면 된다.
1. 매니저 노드 ip address알아오기
현재 core-01을 매니저 노드로 지정하기 위하여 ip address를 알아야 한다.
vagrant ssh core-01
을 통하여 core-01에 접속한 뒤 ifconfig를 통하여 ip address를 알아온다.
core@core-01 ~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255
...
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.8.101 netmask 255.255.255.0 broadcast 172.17.8.255
...
2. core-01 서버를 매니저 노드로 설정
swarm init
명령어를 사용하여 core-01 서버를 매니저 노드로 설정
core@core-01 ~ $ docker swarm init --advertise-addr 172.17.8.101
Swarm initialized: current node (mgf0nk5ez63v5eltq08q0h1kr) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-11b1y84rzrw6ceaw0kwuq9r2aule3pge3jn1d60zsm8lul7bfl-cldzdrz4sjilc4uqsfkd3irum 172.17.8.101:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
3. core-02,core-03 서버를 워크 노드로 설정
core-02, core-03에 ssh로 접속하여 docker swarm join --tocken [토큰] [IP Address]
을 통하여 매니저 노드에 join한다. 이러한 join과정을 통하여 각각의 서버는 워크 노드가 된다.
#core-02접속 후 실행
core@core-02 ~ $ docker swarm join --token SWMTKN-1-11b1y84rzrw6ceaw0kwuq9r2aule3pge3jn1d60zsm8lul7bfl-cldzdrz4sjilc4uqsfkd3irum 172.17.8.101:2377
This node joined a swarm as a worker.
#core-03접속 후 실행
core@core-03 ~ $ docker swarm join --token SWMTKN-1-11b1y84rzrw6ceaw0kwuq9r2aule3pge3jn1d60zsm8lul7bfl-cldzdrz4sjilc4uqsfkd3irum 172.17.8.101:2377
This node joined a swarm as a worker.
This node joined a swarm as as worker.
4. 클러스터 상태 확인
docker node ls
명령어를 토애 워커노드와 매니저 노드가 정상적으로 만들어 졌는지 확인 가능하다.
core@core-01 ~ $ docker node ls
ID | HOSTNAME | STATUS | AVAILBILITY | MANAGER STATUS | ENGINE VERSION |
mgf0nk5ez63v5eltq08q0h1kr * | core-01 | Ready | Active | Leader | 18.06.3-ce |
meq50fs2ab6vitw7xiaz7begu | core-02 | Ready | Active | 18.06.3-ce | |
kyjx0pfd5n62yoijec66ei6lm | core-03 | Ready | Active | 18.06.3-ce |
참고사항
매니저 Node가 관리하는 config files는 /var/lib/docker/swarm에 저장된다.
위와 같은 구성이 끝나면 아래와 같은 사진으로서 표현할 수 있는 Cluster가 설정된 것 이다.
그림출처: subicura 블로그
기본 웹 애플리케이션
서비스 생성
간단한 웹 애플리케이션 서비스를 생성한다.
서비스를 생성하려면 docker service create
로서 생성한다.
core@core-01 ~ $ docker service create --name whoami \
> -p 4567:4567 \
> subicura/whoami:1
l0ffrznqid7n58junwfmfzrtp
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
subicurawhoami는 hostname을 출력하는 단순한 웹 애플리케이션 이다.
Port는 4567로서 Open하였다.
서비스 확인
docker service ls
core@core-01 ~ $ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
l0ffrznqid7n whoami replicated 1/1 subicura/whoami:1 *:4567->4567/tcp
상세한 정보 확인
docker service pswhoami
core@core-01 ~ $ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ok5hp0p7yr0b whoami.1 subicura/whoami:1 core-02 Running Running 2 minutes ago
core-01에서 실행하였지만 Cluster로 구성하여서 자동으로 core-02에서 서비스가 실행되는 것을 알 수 있다.
HTTP 요청으로 Test
curl 명령어를 통하여 HTTP요청을 보낸뒤 확인
#core-01에 요청
core@core-01 ~ $ curl core-01:4567
d3b0456933b3
#core-02에 요청
core@core-01 ~ $ curl core-02:4567
d3b0456933b3
#core-0d에 요청
core@core-01 ~ $ curl core-03:4567
d3b0456933b3
요청 결과를 확인하면 Service는 core-02에서 실행되고 있지만 core-01 ~ core-03까지 모든 노드에서 응답하는 것을 알 수 있다.
Ingress Network
도커 스웜은 서비스를 외부에서 쉽게 노출하기 위하여 모든 노드가 ingress라는 가상 네트워크에 속해 있다.
ingress는 routung mesh라는 서비스가 포트를 오픈할 경우 모든 노드에 포트가 오픈되고 어떤 노드에 요청을 보내도 실행 중인 컨테이너에 자동으로 전달해 준다.
그림출처: subicura 블로그
위의 예제에서 subicura/whoami라는 Service를 실행할 때 Port 4567을 Open하였기 때문에 어디에서 테스트를 하던간에 core-02노드에 실행된 컨테이너로 요청이 전달된다.
만약 컨테이너가 여러개라면 내부 로드밸런스를 이용하여 여러개의 컨테이너로 분산처리된다.
서비스 복제 replication
웹 애플리케이션에 부하가 발생했다고 가정하고 컨테이너를 5개로 늘린본다.
노드는 3개인데 컨테이너를 5개를 늘리면 2개의 서버에는 컨테이너2개, 1개의 서버에는 컨테이너1개가 생성된다.
각각의 컨테이너는 독립되어 있으므로 여러개를 생성해도 상관없고 ingress네트워크를 통해 요청을 분산 처리한다.
그림출처: subicura 블로그
서비스의 개수 증가
docker service scale [서비스 명]=[서비스 개수]
#서비스의 개수 5개로 증가
core@core-01 ~ $ docker service scale whoami=5
whoami 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
#서비스 상태 확인
core@core-01 ~ $ docker service ps whoami
ID | NAME | IMAGE | NODE | DESIRED STATE | CURRENT STATE |
ok5hp0p7yr0b | cwhoami.1 | subicura/whoami:1 | core-02 | Running | Running about an hour ago |
baztiqbws22p | cwhoami.2 | subicura/whoami:1 | core-01 | Running | Running about a minute ago |
kg9gm18xt2vn | cwhoami.3 | subicura/whoami:1 | core-01 | Running | Running about a minute ago |
ufn3g86114q8 | cwhoami.4 | subicura/whoami:1 | core-01 | Running | Running about a minute ago |
plhb8hi9x9tj | cwhoami.5 | subicura/whoami:1 | core-01 | Running | Running about a minute ago |
서비스 상태 확인
core@core-01 ~ $ curl core-01:4567
1dc273d198d2
core@core-01 ~ $ curl core-01:4567
fcc31bae1093
core@core-01 ~ $ curl core-01:4567
0b66ae7d26f3
core@core-01 ~ $ curl core-01:4567
2103d6c1434d
core@core-01 ~ $ curl core-01:4567
d3b0456933b3
5개의 컨테이너에게 요청이 분산된 것을 알 수 있다.
아무런 설정 없이 ingress 네트워크가 알아서 로드 밸런서 역할을 해주고 있다.
참고사항: 로드밸런서
Loab Balacer란여러 대의 Server에게 균등하게 Traffic을 분산시켜주는 역할을 하는 것 이다.
HEALTHCHECK
그림출처: subicura 블로그
Docker Swarm은 컨테이너가 실행되면 ingress에서 해당 컨테이너로 요청을 보내기 시작하는데 웹 서버가 부팅되는 동안 문제가 발생한다.
ingress는 컨테이너가 실행되면 요청을 보내기 때문에 문제가 없을 것이라고 판단하지만 컨테이너가 실행되고 웹 서버가 완전히 실행되기 전에 요청을 보내면 서버를 찾을 수 없다는 메세지를 볼 수 있고 이러한 문제를 해결하기 위해 좀 더 자세한 상태 체크 방식이 필요하다.
위에서 사용한 subicura/whoami:1과 subicura/whoami:2의 차이점은 HEALTHCHECK의 유무이다.
다음 subicura/whoami:2 Image를 Dockerfile로 정의한 내용이다.
FROM ruby:2.3-alpine
MAINTAINER subicura@subicura.com
COPY Gemfile* /usr/src/app/
WORKDIR /usr/src/app
RUN bundle install
COPY . /usr/src/app
EXPOSE 4567
HEALTHCHECK --interval=10s CMD wget -qO- localhost:4567
CMD bundle exec ruby app.rb -o 0.0.0.0
위의 과정을 Dockerfile로서 얻을 수 있는 정보는 10초마다 wget을 요청하여 정상적인 응답이 있을때마다 Update를 진행하게 된다.
즉, 하나의 서버씩 Update하는 Rolling Update가 이루워 진다.
이러한 방식은 단순하게 한 대씩 재시작한다.
다만, 코드 변경에 따른 side effect가 발생할 수 있다.
이러한 side effect를 해결하기 위해서는 블루 그린 배포를 사용한다.
(참고로 블루 그린 배포는 Kubernetes에서 지원한다.)
배포방식 자세한 내용
위와같은 Service의 업데이트는 docker service update
를 통하여 이루워 질 수 있다.
core@core-01 ~ $ docker service update \
--image subicura/whoami:2 \
whoami
Update후 상태 확인
core@core-01 ~ $ docker service ps whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ri4d8ujsid9r whoami.1 subicura/whoami:2 core-02 Running Running 6 minutes ago
ok5hp0p7yr0b \_ whoami.1 subicura/whoami:1 core-02 Shutdown Shutdown 6 minutes ago
6jjiv19istjr whoami.2 subicura/whoami:2 core-01 Running Running 7 minutes ago
baztiqbws22p \_ whoami.2 subicura/whoami:1 core-01 Shutdown Shutdown 7 minutes ago
9y2f2yqsjjea whoami.3 subicura/whoami:2 core-01 Running Running 7 minutes ago
kg9gm18xt2vn \_ whoami.3 subicura/whoami:1 core-03 Shutdown Shutdown 7 minutes ago
nsmbnffpdotv whoami.4 subicura/whoami:2 core-03 Running Running 5 minutes ago
ufn3g86114q8 \_ whoami.4 subicura/whoami:1 core-03 Shutdown Shutdown 6 minutes ago
du5bpwago2k3 whoami.5 subicura/whoami:2 core-02 Running Running 6 minutes ago
plhb8hi9x9tj \_ whoami.5 subicura/whoami:1 core-02 Shutdown Shutdown 6 minutes ago
방문자수 체크 웹 애플리케이션
redis와 함께 웹 애플리케이션을 실행하고 서버에 접속할 때마다 카운트 +1하는 서비스를 생성
먼저 웹 애플리케이션과 redis가 통신할 수 있는 오버레이 네트워크를 생성한다.
오버레이 네트워크를 사용하면 redis는 외부에 포트를 오픈하지 않아도 되고 웹 애플리케이션과 다른 노드에 있어도 같은 서버에 있는 것처럼 통신할 수 있다.
그림출처: subicura 블로그
네트워크 생성
docker network create
를 통하여 오버레이 네트워크를 생성한다.
core@core-01 ~ $ docker network create --attachable \
--driver overlay \
backend
urjb325chpg1hr7lvcgu1kjex
네트워크 확인
docker network ls
core@core-01 ~ $ docker network ls
NETWORK ID NAME DRIVER SCOPE
urjb325chpg1 backend overlay swarm
82fb3510c698 bridge bridge local
e6e2de224b77 docker_gwbridge bridge local
7ade34d33f04 host host local
ppymzsz9uejx ingress overlay swarm
bf03ff81e303 none null local
기본적인 Network + 생성한 urjb325chpg1 overlay network를 살펴볼 수 있다.
redis 생성
그림출처: subicura 블로그
생성한 네트워크와 연결하는 redis Service를 생성한다.
core@core-01 ~ $ docker service create --name redis \
--network=backend \
redis
l0rak05zjtgesih4x76xmina5
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
redis 확인
현재 redis의 네트워크는 외부 네트워크에서는 접속할 수 없고 backend 네트워크 상에서 원래 포트인 6379로 접속할 수 있다.
core@core-01 ~ $ docker run --rm -it \
--network=backend \
alpine \
telnet redis 6379
참고사항
–rm은 일시적으로 컨테이너를 생성하는 방법이다.
-i은 interactive라는 뜻으로 컨테이너와 상호적으로 주고받고 하겠다는 뜻
-t은 tty를 사용하겠다는 의미이다.
애플리케이션 설정
그림출처: subicura 블로그
다음과 같은 명령어로서 Redis와 Counter라는 Service가 Backend Overlay Network를 통하여 통신하도록 설정
core@core-01 ~ $ docker service create --name counter \
--network=backend \
--replicas 3 \
-e REDIS_HOST=redis \
-p 4568:4567 \
subicura/counter
ikl1t03e521i65ru2ap09bfff
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
위의 명령어를 통하여 counter라는 Service를 --replicas 3
을 통하여 3개를 설정하였다.
이러한 Service3개는 스웜에 의하여 각각의 Node에 한개의 Service를 자동 할당하였다.
외부의 포트 4568을 개방하였으며 Network는 이전에 정의한 backend를 사용한다.
테스트
core@core-01 ~ $ curl core-01:4568
abd752828052 > 1
core@core-01 ~ $ curl core-01:4568
abd752828052 > 1
4bc21a61f18c > 1
core@core-01 ~ $ curl core-01:4568
514ed14e7d5e > 1
abd752828052 > 1
4bc21a61f18c > 1
core@core-01 ~ $ curl core-01:4568
514ed14e7d5e > 1
abd752828052 > 2
4bc21a61f18c > 1
core@core-01 ~ $ curl core-01:4568
514ed14e7d5e > 1
abd752828052 > 2
4bc21a61f18c > 2
core@core-01 ~ $ curl core-01:4568
514ed14e7d5e > 2
abd752828052 > 2
4bc21a61f18c > 2
위의 결과로서 웹 애플리케이션 서버와 redis가 backend 오버레이 네트워크를 통해 연결되었고 ingress 네트워크가 3개의 웹 컨테이너에 작업을 분산하였다.
즉, 스웹은 서로 통신이 필요한 서비스를 같은 이름의 오버레이 네트워크로 묶고 네부 DNS서버를 이용하여 접근할 수 있다. 여러 개의 네트워크를 쉽게 만들 수 있고 하나의 서비스는 여러 개의 네트워크에 속할 수 있다. 모든 것은 스웜이 알아서 하고 관리자는 네트워크와 서비스만 잘 만들면 된다.
Docker의 기밀정보로 민감한 데이터 관리
Docker Swarm 서비스와 관련하여 암호, SSH 개인 키, SSL 인증서 또는 네트워크를 통해 전송되거나 Dockerfile이나 응용프로그램에 암호화되지 않은 다른 데이터 조각과 같은 데이터 묶음이다.
Docker 1.13이상에서는 Docker secret를 사용하여 이 데이터를 중앙에서 관리하고 엑세스 권한이 필요한 컨테이너에게만 안전하게 전송할 수 있다.
Docker secret예제
1. Docker에게 비밀키 생성: docker secret create
명령은 파일을 나타내는 마지막 인수가 - 로 설정되어 있기 때문에 표준 입력을 읽는다.
core@core-01 ~ $ echo "this is my password!" | docker secret create my-password -
2d2lgydukbe0q93g0kfmmo9n8
위의 Code의 결과로 인하여 my-passward라는 이름의 비밀키에 this is my password!라는 내용을 저장하게 되었다.
2. secret 서비스 생성: 서비스를 생성하고 --secret
옵션을 활용하여 비밀키에 대한 엑세스 권한 부여
core@core-01 ~ $ docker service create --name secret \
--secret my-password \
-p 4569:4567 \
-e SECRET_PATH=/run/secrets/my-password \
subicura/secret
p0ncqotfh3754jrmk5mj7dk2c
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
--secret
옵션을 활용하여 service를 생성하게 되면 run/secrest디렉토리 밑에 키 이름의 파일로 마운트 된다.
3. secret service 생성 확인: docker service ps
를 통하여 생성된 secret service를 확인한다.
core@core-01 ~ $ docker service ps secret
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
zpurg7z73gza secret.1 subicura/secret:latest core-01 Running Running 2 minutes ago
4. 실제 디렉토리 에서 내용 읽어오기
docker ps
를 사용하여 container의 ID를 가져온다.
core@core-01 ~ $ docker ps --filter name=secret -q
a9889d17676c
docker exec
를 사용하여 외부에서 컨테이너 안의 명령을 실행한다. 실제 /run/secrets디렉토리 안에 비밀키가 생성되었는지 확인한다.
core@core-01 ~ $ docker exec $(docker ps --filter name=secret -q) ls -l /run/secrets
total 4
-r--r--r-- 1 root root 21 Oct 16 06:58 my-password
docker exec
를 사용하여 외부에서 컨테이너 안의 명령을 실행한다. 실제 /run/secrets디렉토리 안에 my-passward라는 파일의 내용을 읽어온다.
core@core-01 ~ $ docker exec $(docker ps --filter name=secret -q) cat /run/secrets/my-password
this is my password!
참고사항
현재 생성한 subicura/secret라는 Service는 외부 포트 4569를 통하여 위의 과정과 같은 결과를 알 수 있다.
core@core-01 ~ $ curl core-01:4569
this is my password!
5. 컨테이너의 변경 사항을 새로운 이미지로 저장뒤 비밀키에 접근: docker commit
으로 새로운 이미지를 생성 후 /run/secrets/my-password에 접근하여 파일을 읽어 온다.
- 새로운 이미지 생성
core@core-01 ~ $ docker commit $(docker ps --filter name=secret -q) committed_secret
sha256:f8fc38021d238f006d13f76b0af232f79be3a7c4efaaec417e5f52457ecb9445
- 서비스 컨테이너 생성 후 /run/secrets/my-password에 접근하여 비밀 키 내용 읽어오기
#비밀 키 파일 확인
core@core-01 ~ $ docker run --rm -it committed_secret ls /run/secrets/
my-password
#비밀 키 내용 읽어오기
core@core-01 ~ $ docker run --rm -it committed_secret cat /run/secrets/my-password
#실행 결과 아무것도 안나오는 것을 알 수 있다.
6. 비밀 키 제거: 비밀 키 목록 확인 후 비밀키 제거
#비밀키 목록 확인
core@core-01 ~ $ docker secret ls
ID NAME DRIVER CREATED UPDATED
2d2lgydukbe0q93g0kfmmo9n8 my-password 44 minutes ago 44 minutes ago
#비밀키 제거
core@core-01 ~ $ docker secret rm my-password
Error response from daemon: rpc error: code = InvalidArgument desc = secret 'my-password' is in use by the following service: secret
현재 secret에서 my-password 비밀키를 사용중이므로 삭제할 수 없다.
7. Service에서 비밀 키 제거: my-password비밀키를 사용중인 Service에서 비밀키 사용 해제
#Service(Secret)에서 my-passward 비밀 키 삭제
core@core-01 ~ $ docker service update --secret-rm my-password secret
secret
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
#삭제 확인
core@core-01 ~ $ docker exec $(docker ps --filter name=secret -q) ls /run/secrets/
my-password
core@core-01 ~ $ docker exec $(docker ps --filter name=secret -q) cat /run/secrets/my-password
#확인 결과 비밀키 파일은 존재하나 읽을 수 없는 것을 확인할 수 있다.
8. 비밀키 제거: 비밀키를 사용중인 Service와 비밀키의 관계를 없앴음으로 비밀키 제거 가능
#비밀키 제거
core@core-01 ~ $ docker secret rm my-password
my-password
#제거 확인
core@core-01 ~ $ docker secret ls
ID NAME DRIVER CREATED UPDATED
참조: 완벽한 IT 인프라 구축을 위한 Docker
참조:subicura 블로그
참조:sauru 블로그
참조:code-examples
코드에 문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.
Leave a comment