Docker Swarm

 

지난 Docker : 컨테이너 오케스트레이션 개요 편에서는 한 서비스가 점차 확장되면서 컨테이너 증가에 따른 관리의 필요성과 다수의 컨테이너를 효과적으로 다룰 수 있는 컨테이너 오케스트레이션 툴에 대한 개요를 설명 하였다. 이번 편에서는 도커스웜의 노드 클러스터링 구축과 스웜 로드밸런서의 기능을 확인해보는 실습을 진행하도록 하겠다.

 

 

도커스웜의 노드 클러스터링

 

노드 클러스터링(Node Clustering)의 노드(Node)는 도커스웜에서 물리적 또는 논리적으로 분리 된 독립적인 서버(Server)를 의미하고 클러스터링(Clustering)은 사전적 의미로 뭉치기라는 뜻을 가지고 있다. 즉 노드 클러스터링은 서버의 군집화라고 표현 할 수 있다. 필자는 3개의 노드를 클러스터링 하기 위해 VirtualBox의 Clone기능을 활용하여 아래와 같이 총 3대의 노드를 생성하였다.

 

스웜 클러스터를 구성하기 위해서는 클러스터의 중심이 되는 노드가 필요한데 필자는 manager01을 매니저 노드로 설정 하였고 나머지 노드를 worker노드로 구분하였다. (색상표기가 된 manager와 worker는 각 노드의 hostname이다)

 

자 이제 클러스터를 생성해보자.

는 잠깐!!

 

포.. 포트포워딩이 아직 안 됐....

클러스터를 생성하기 전 도커스웜에서 사용하는 포트와 서비스로 사용할 포트를 모두 열어주어야 한다. VirturalBox의 포트포워딩 설정과 각 노드의 포트별로 방화벽 해제 처리를 해주자

 

VirtualBox 포트포워딩 설정

// 방화벽 해제
$ sudo firewall-cmd --permanent --add-port=2377/tcp
$ sudo firewall-cmd --permanent --add-port=7946/tcp
$ sudo firewall-cmd --permanent --add-port=7946/udp
$ sudo firewall-cmd --permanent --add-port=4789/udp
$ sudo firewall-cmd --permanent --add-port=80/tcp
$ sudo firewall-cmd --reload

 

포트포워딩이 됐...!!

 

포트포워딩 설정과 방화벽 해제가 완료 되었다면 manager01 노드에서 docker swarm init 명령으로 스웜 클러스터를 생성 해보자. init 뒤에 있는 --advertise-addr 옵션에는 해당 주소로 swarm join 할 수 있도록 IP와 포트를 지정 할 수 있다. 현재 VirtualBox에서 생성한 CentOS 7 환경에서는 Guest의 IP가 10.0.2.15로 잡혀 있으므로 VirtualBox에서 생성된 노드들 끼리 접근이 가능하려면 Host IP인 192.168.37.1로 설정 해야 한다.

# docker swarm init --advertise-addr 192.168.37.1
Swarm initialized: current node (0ba2xn5fqkv1047rc5xa77nl0) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-2aai8y68yz8ju664rktqbxlw88if54rqzx9cv49or7ywnzzpz5-b40gsplzlg9ip0o6s4ofdke29 \
    192.168.37.1:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

스웜 클러스터가 생성되면 친절하게도 위와 같이 docker swarm join 명령어 샘플이 자동으로 생성된다. 바로 아랫줄에 있는 토큰은 manager 노드로 접근하기 위한 일종의 비밀 키 이므로 실무에서 사용하는경우 외부에 노출되지 않도록 주의하길 바란다.

 

이제 각각의 worker 노드에서 join 명령어를 통해 스웜 클러스터에 합류 해보자

# docker swarm join \
> --token SWMTKN-1-2aai8y68yz8ju664rktqbxlw88if54rqzx9cv49or7ywnzzpz5-b40gsplzlg9ip0o6s4ofdke29 \
> 192.168.37.1:2377
This node joined a swarm as a worker.

swarm join이 완료되면 'This node joined a swarm as a worker.' 문구와 함께 참여완료 문구가 뜬다. 이제 다시 manager노드로 이동하여 각 worker노드들이 잘 합류했는지 확인해보자.

 

# docker node ls
ID                           HOSTNAME   STATUS  AVAILABILITY  MANAGER STATUS
0ba2xn5fqkv1047rc5xa77nl0 *  manager01  Ready   Active        Leader
jw2kxdt3v7tiqq9etiaxqw1lt    worker01   Ready   Active
x3kxchadl950q934kuctymzmm    worker02   Ready   Active

3개의 노드를 하나로 묶은 클러스터링이 구축 되었다. 현재 상태를 이미지로 표현하면 아래와 같다.

 

이제 스웜 클러스터도 생성 되었고 스웜 로드벨런싱 기능을 확인하기 위해 간단한 실습을 진행 해보도록 하겠다. 먼저 manager 노드에 docker service로 nginx를 설치 해보자.

# docker service create \
--name my-web \
--publish published=80,target=80 \
--replicas 1 \
nginx

# docker service ls
ID            NAME    MODE        REPLICAS  IMAGE
x4njngtukyfk  my-web  replicated  1/1       nginx:latest

# docker service ps my-web
ID            NAME      IMAGE         NODE      DESIRED STATE  CURRENT STATE        ERROR  PORTS
m05xzf46mz8t  my-web.1  nginx:latest  worker01  Running        Running 2 hours ago
  • docker service create 옵션설명
    • --name: 생성할 service의 이름을 지정한다.
    • --replicas: 생성할 컨테이너 갯수
    • --publish: 서비스에서 사용되는 포트를 오픈한다.
      1. published: 도커 컨테이너로 전달할 외부 포트
      2. target: 도커 컨테이너 내부 포트

 

서비스 생성 후 192.168.37.1, 2, 3번 각각 접근 해보자

현재 192.168.37.1 manager 노드 하나에만 nginx 컨테이너가 활성화 되어있는데 어떻게 다른 노드로 접근해도 같은 페이지가 뜨는 것일까? 스웜 클러스터가 구축 되면 ingress network가 생성되는데 이것은 어떤 노드에 접근하더라도 서비스중인 컨테이너에 접근 가능하도록 Routing mesh를 구성하고 있고 스웜 로드밸런서에 서비스가 활성화 되어있는 노드에 라운드 로빈(Round Robin)방식으로 로드 밸런싱 된다.

 

  • Routing mesh: 서비스에서 포트가 오픈되면 모든 노드에도 동일한 포트가 오픈되며 어떤 노드에 요청을 보내더라도 현재 서비스가 실행중인 노드의 컨테이너로 요청을 전달한다.
  • 라운드 로빈(Round Robin): 스케쥴링의 한 방식으로 리스트의 맨 위에서 아래로 가며 하나 씩 순차적으로 진행 하고 끝나면 다시 맨 위로 돌아가는 식으로 진행된다.

 

 

Round Robin 방식의 적절한 예

 

이 ingress network와 스웜 로드벨런서 덕분에 어떤 노드를 호출해도 같은 페이지를 보는것이 가능하다.

만약 현재의 상태로 manager 노드의 컨테이너가 죽는다면 어떤 노드로 접근한다 해도 페이지는 먹통일 것이다. 노드 클러스터링의 목적은 과도한 트래픽이 몰릴 경우를 대비한 트래픽 분산도 있지만 하나의 컨테이너가 죽더라도 다른 컨테이너로 대체 할 수 있도록 위험분산의 목적도 가지고 있다. 이번에는 전체 node에 골고루 분포 되도록 Replica의 갯수를 6개로 늘려보도록 하자.

# docker service scale my-web=6
my-web scaled to 6
# docker service ps my-web
ID            NAME          IMAGE         NODE       DESIRED STATE  CURRENT STATE               ERROR  PORTS
0mouqz0t89nz  my-web.1      nginx:latest  worker01   Running        Running about a minute ago
xx2lsv3uwcrp  my-web.2      nginx:latest  worker02   Running        Running 51 seconds ago
h6kjhoyvfpyl  my-web.3      nginx:latest  worker01   Running        Running 52 seconds ago
nszaz7kkg8wc  my-web.4      nginx:latest  manager01  Running        Running 51 seconds ago
wdgjoyib63ue  my-web.5      nginx:latest  manager01  Running        Running 51 seconds ago
zwqsm1yus5os  my-web.6      nginx:latest  worker02   Running        Running 51 seconds ago

 

NODE항목의 각 노드 갯수를 보면 manager와 worker들의 노드 갯수가 2개씩 배정이 되어 있는것을 확인 할 수 있고 세개의 노드 중 두개가 죽더라도 서비스에는 지장이 없게 되었다.

 

여기까지 도커스웜 클러스터 구축과 manager노드 및 worker노드의 생성, ingress network의 개요와 스웜 로드밸런서를 통한 로드밸런싱 기능을 확인 해보았다.

 

 

Docker : 도커스웜 클러스터 구축 편

끝.

 

'Docker' 카테고리의 다른 글

Docker : 도커스웜 클러스터 구축 편  (0) 2019.05.17
Docker : 컨테이너 오케스트레이션 개요 편  (0) 2019.04.19
Docker : Dockerfile 실습 편  (0) 2019.03.22
Docker : Dockerfile 편  (0) 2019.03.07
Docker : 이미지 편  (0) 2019.02.22
Docker : 컨테이너 편  (1) 2019.02.15
Posted by DevStream

댓글을 달아 주세요

컨테이너 오케스트레이션 개요

 

도커 컨테이너의 갯수가 꾸준히 늘어나면 필요한 자원도 지속적으로 늘어나기 마련이다 때문에 서버 또한 여러대로 늘어날 수 있는데 한대 두대의 수준이 아니라 몇 십 몇 백대의 서버로 늘어났다고 가정 해보자 이 많은 서버들을 일일이 접근하여 명령어 날려주고 컨테이너 올리고 "어? 이건 또 왜 내려갔어?" 하다가 시간은 시간대로 흘러버리고 정신을 차려보면 라꾸라꾸 침대가 본인 의자옆에 있는것을 발견 할 수 있을것이다. 결론적으로 이 많은 서버들과 컨테이너를 소수의 인원으로 관리하기에는 상당히 어렵고 이 문제를 효율적으로 관리하기 위해 컨테이너 오케스트레이션 툴들이 나오게 되었다.

 

 

컨테이너 오케스트레이션 툴 소개

Docker Swarm / Kubernetes / Apache Mesos

 

컨테이너 오케스트레이션 툴의 기능에는 단순 컨테이너의 배포 뿐만이 아닌 하나의 서비스를 관리하고 유지보수 하기 위한 많은 기능들을 포함하고 있고 툴마다 기능에 대한 편차는 있으나 주요 기능은 아래와 같다.

 

 

오케스트레이션 툴의 기능

  • 노드 클러스터링
  • 컨테이너 로드 밸런싱
  • 컨테이너의 배포와 복제 자동화
  • 컨테이너 장애 복구기능
  • 컨테이너 자동 확장 및 축소
  • 컨테이너 스케쥴링
  • 로깅 및 모니터링

 

컨테이너 오케스트레이션 툴의 종류는 여러가지가 있지만 그 중 가장 인지도가 높고 자주 소개되는 Docker Swarm, Kubernetes, Apache Mesos에 대해서 각 툴의 장점과 단점을 간략히 설명 하도록 하겠다.

 

 

Docker Swarm

 

도커 스웜은 도커 컨테이너 플랫폼에 통합 된 컨테이너 오케스트레이션 툴이다. 최초에 도커 스웜은 도커와 별개로 개발 되었으나 도커 1.12 버전부터 도커 스웜 모드라는 이름으로 합쳐졌다.

 

장점

  • 도커 명령어와 도커 컴포즈를 포함한 도커의 모든 기능이 내장되어 있다.
  • 도커 이외의 별도의 툴 설치가 필요하지 않다.
  • 타 오케스트레이션 툴에 비해 복잡하지 않고 다루기 쉽다.

 

단점

  • 타 오케스트레이션 툴에 비해 기능이 단순하여 세부적인 설정이 어려움
  • 초대형 노드 클러스터링에는 무리가 있다.

 

 

Kubernetes

 

쿠버네티스는 구글에서 개발한 2014년 오픈소스화 된 프로젝트이다. 무려 15년에 걸친 구글의 대규모 운영 워크로드 운영 경험과 노하우가 축적된 프로젝트로 컨테이너 중심의 관리환경을 제공한다.

 

장점

  • 현재 가장 인지도가 높고 기능이 많은 오케스트레이션 툴
  • 내장된 기능이 많아 타사 애드온이 불필요함

 

단점

  • 쿠버네티스의 구성과 개념에 대한 이해가 필요하다.
  • 학습해야할 부분이 많고 소규모 프로젝트에서 구축하기 쉽지 않다.

 

 

Apache Mesos

 

아파치 메소스는 Twitter, Apple, Uber, Netflix 등 대형 서비스를 운영하고 있는 기업에서 다수 채택 되었으며 마이크로서비스와 빅데이터, 실시간 분석, 엘라스틱 스케일링 기능 등을 제공하고 있다.

 

장점

  • 대형 서비스를 운영중인 회사에서 많이 채택 되었고 안정성이 검증되었다.
  • 수만대의 물리적 시스템으로 확장 가능하게 설계 되어있다.
  • Zookeeper, Hadoop, Spark와 같은 응용프로그램을 연동하여 노드 클러스터링과 자원 최적화 가능

 

단점

  • 너무 다양한 응용프로그램의 연동으로 인하여 복잡해질 수 있다.
  • 설치 및 관리가 어렵고 컨테이너를 활용하기 위해 Marathon 프레임워크를 추가로 설치해야 한다.

 

 

결론 : 이럴 때 적합!

 

Docker Swarm

  • 중소형 프로젝트일 경우
  • 관리 할 노드가 적고 많은 기능이 필요하지 않을 경우

 

Kubernetes

  • 대형 프로젝트일 경우
  • 세밀하고 다양한 설정 기능이 필요한 경우

 

Apache Mesos

  • 대형 프로젝트일 경우
  • 검증된 오케스트레이션 툴을 찾고있는 경우

 

 

Docker : 컨테이너 오케스트레이션 개요 편

끝.

'Docker' 카테고리의 다른 글

Docker : 도커스웜 클러스터 구축 편  (0) 2019.05.17
Docker : 컨테이너 오케스트레이션 개요 편  (0) 2019.04.19
Docker : Dockerfile 실습 편  (0) 2019.03.22
Docker : Dockerfile 편  (0) 2019.03.07
Docker : 이미지 편  (0) 2019.02.22
Docker : 컨테이너 편  (1) 2019.02.15
Posted by DevStream

댓글을 달아 주세요

지난 Docker : Dockerfile 편에서는 도커파일의 개념 설명과 도커파일의 생성, 그리고 도커파일을 이용하여 이미지를 만들고 컨테이너를 실행하여 아파치에 접근해보는 간단한 실습을 진행 하였다. 이번 시간에는 도커를 이용하여 Jenkins Slave Node를 생성하여 빌드해보는 실습을 진행 해보고 이 과정을 도커파일로 만들어보도록 하겠다.



Jenkins 분산빌드환경


서버의 자원이 한정된가난한 상태에서 다수의 사람들이 Jenkins(이하 젠킨스)를 통해 빌드를 하다보면 점점 빌드가 잦아지고 결국 빌드를 대기하는 일종의 빌드 병목현상이 발생한다. 게다가 몸집이 큰 프로젝트 파일을 빌드하기 위해서 상당한 시간이 소요되는 경우도 있어서 빌드를 기다리기보다 수동빌드를 하는게 더 나은 상황이 발생 할 수 있다.


이를 분산빌드환경(Slave Node 추가)을 통하여 해결 해보도록 하자.



먼저 젠킨스 메인 화면의 좌측 Jenkins 관리를 누르고 아래로 스크롤하여 노드관리 메뉴로 진입한다. 신규 노드를 눌러 노드명을 입력하고 Permanent Agent 선택 후 OK를 누르면 아래 상세정보 입력 화면으로 이동한다. 필자는 Slave Node Name을 m7Docker라고 입력하였다. Credentials 에는 Docker 컨테이너에 접근할 계정을 Add를 눌러 입력해주면 된다. 필자는 ID는 root에 비밀번호는 xptmxm123으로 입력 후 저장하였다. 이후 이미지에는 나와있지 않지만 필자는 SSH 포트를 8890으로 변경해주었다 (고급버튼 누르면 포트변경 가능)




Jenkins Build를 위한 Slave Node용 도커 컨테이너 생성


다음은 Ubuntu 16.04를 이용하여 젠킨스 서버에서 도커 컨테이너로 SSH로 접근 후 maven 빌드를 수행하는 컨테이너 하나를 만들어보도록 하겠다. 이미지 생성과 컨테이너 생성은 이미 한번 다룬 내용이므로 너무 자세한 설명은 생략 하고 명령어 위주로 작성하겠다.


먼저 docker run명령을 통해 컨테이너를 생성하자 포트포워딩은 젠킨스 slave설정에서 지정해둔 8890 포트와 도커 컨테이너에 접근할 22번 포트를 서로 연결하였다.


[root@localhost testuser]# docker run -i -t -p 8890:22 --name jenkins_slave docker.io/ubuntu:16.04
root@8d8eeb87e586:/#


이제 이 아무것도 없는 도커 컨테이너를 젠킨스 Slave Node로 활용하기 위해 무엇을 해야할까 한번 정리 해보자.


1. 패키지 업데이트

2. 컨테이너 접근을 위한 ssh 설치

3. 빌드를 위한 maven 설치

4. 소스변경사항을 가져오기 위한 git 설치

5. jdk11이 적용된 프로젝트의 빌드를 위해 openjdk11 설치

6. root 계정을 사용하기 위해 root 패스워드 설정

7. ssh로 root접근이 가능하도록 sshd_config파일의 옵션 수정

8. Jenkins 전역설정의 JAVA_HOME과 MAVEN_HOME의 경로 동기화


이정도가 되겠다. 먼저 패키지 업데이트부터 차근차근 진행 해보자.



1. 패키지 업데이트


root@8d8eeb87e586:/# apt-get update Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB] Get:2 http://security.ubuntu.com/ubuntu xenial-security InRelease [109 kB] Get:3 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [109 kB] ... ... Fetched 15.7 MB in 1min 3s (248 kB/s) Reading package lists... Done



2. SSH 설치


root@8d8eeb87e586:/# apt-get install -y openssh-server Reading package lists... Done Building dependency tree Reading state information... Done ... ... Setting up ssh-import-id (5.5-0ubuntu1) ... Processing triggers for libc-bin (2.23-0ubuntu11) ... Processing triggers for ca-certificates (20170717~16.04.2) ... Updating certificates in /etc/ssl/certs... 148 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... done. Processing triggers for systemd (229-4ubuntu21.16) ...



3. Maven 설치


root@8d8eeb87e586:/# apt-get install -y maven Reading package lists... Done Building dependency tree Reading state information... Done ... ... After this operation, 156 MB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libjpeg-turbo8 amd64 1.4.2-0ubuntu3.1 [111 kB] Get:2 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 x11-common all 1:7.7+13ubuntu3.1 [22.9 kB] Get:3 http://archive.ubuntu.com/ubuntu xenial/main amd64 libxtst6 amd64 2:1.2.2-1 [14.1 kB] ... ... done.



4. Git 설치


root@8d8eeb87e586:/# apt-get install -y git-core Reading package lists... Done Building dependency tree Reading state information... Done Get:1 http://archive.ubuntu.com/ubuntu xenial/main amd64 libatm1 amd64 1:2.5.1-1.5 [24.2 kB] Get:2 http://archive.ubuntu.com/ubuntu xenial/main amd64 libmnl0 amd64 1.0.3-5 [12.0 kB] Get:3 http://archive.ubuntu.com/ubuntu xenial/main amd64 libpopt0 amd64 1.16-10 [26.0 kB] ... ... update-alternatives: using /usr/bin/file-rename to provide /usr/bin/rename (rename) in auto mode Processing triggers for libc-bin (2.23-0ubuntu11) ... Processing triggers for systemd (229-4ubuntu21.16) ...



5. OpenJdk 11 설치 (필자는 11.0.1 버전을 사용하였다.)


root@8d8eeb87e586:/# wget -P /usr/local https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz --2019-03-22 01:15:09-- https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz Resolving download.java.net (download.java.net)... 23.212.14.196 Connecting to download.java.net (download.java.net)|23.212.14.196|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 187599951 (179M) [application/x-gzip] Saving to: '/usr/local/openjdk-11.0.1_linux-x64_bin.tar.gz' openjdk-11.0.1_linux-x64_bin.tar.gz 100%[===================================================================================================================>] 178.91M 22.2MB/s in 8.7s 2019-03-22 01:15:23 (20.5 MB/s) - '/usr/local/openjdk-11.0.1_linux-x64_bin.tar.gz' saved [187599951/187599951] root@8d8eeb87e586:/# cd /usr/local/ && tar -xzf openjdk-11.0.1_linux-x64_bin.tar.gz && rm openjdk-11.0.1_linux-x64_bin.tar.gz root@8d8eeb87e586:/usr/local# ls bin etc games include jdk-11.0.1 lib man sbin share src root@8d8eeb87e586:/usr/local#



6. root 패스워드 설정


root@8d8eeb87e586:/usr/local# passwd root Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully root@8d8eeb87e586:/usr/local#



7. sshd_config 설정파일 수정 (ssh로 root계정에 접근하기 위한 설정 변경)


root@8d8eeb87e586:/usr/local# vi /etc/ssh/sshd_config bash: vi: command not found



당황하지 말고 vi에디터를 설치 해주도록 한다.


7-1. vi에디터 설치


root@8d8eeb87e586:/usr/local# apt-get install vim Reading package lists... Done Building dependency tree Reading state information... Done ... ... Processing triggers for libc-bin (2.23-0ubuntu11) ...



7-2. sshd_config 파일 수정 (PermitRootLogin의 prohibit-password설정을 yes로 바꾼 후 저장한다.)


root@8d8eeb87e586:~# vi /etc/ssh/sshd_config

... ...

# Authentication: LoginGraceTime 120 PermitRootLogin prohibit-passwordyes ... ... :wq



8. Jenkins 전역 설정에 맞추어 JAVA_HOME과 MAVEN_HOME 경로 설정


필자는 JDK는 /usr/local/jdk-11.0.1에 저장 하였고(다운로드 및 압축해제는 위의 설정과 같으므로 JAVA_HOME은 별 다른 설정이 필요하지 않다.) maven은 /usr/share/maven 폴더에 저장이 되어있는데 /usr/local/apache-maven-3.5.3의 경로로 심볼릭링크를 걸어두었다.


root@8d8eeb87e586:~# ln -s /usr/share/maven /usr/local/apache-maven-3.5.3



이제 모든 준비가 완료 되었다. Jenkins 서버에서 현재 설정해둔 도커 컨테이너로의 접근이 가능한지 확인 해보자. 먼저 Jenkins 서버에서 필자의 컨테이너에 접근하기 위해서는 외부에서 접근이 가능하도록 포트를 열어 주어야 한다. 필자는 윈도우 10을 기준으로 설명하겠다. 먼저 방화벽의 인바운드 설정에서 아까 도커 컨테이너 생성 시 포트포워딩 했었던 8890을 지정해준다.




인바운드설정이 완료되면 8890으로 들어온 포트를 내부의 어떤 IP로 포워딩 할지 지정 해주어야 하는데 윈도우 커멘드를 관리자 권한으로 접근하여 포트 포워딩을 설정 해주도록 한다.


C:\WINDOWS\system32>netsh interface portproxy add v4tov4 listenport=8890 listenaddress=192.168.70.22 connectport=8890 connectaddress=172.17.100.97 C:\WINDOWS\system32>netsh interface portproxy show v4tov4 ipv4 수신 대기: ipv4에 연결: 주소 포트 주소 포트 --------------- ---------- --------------- ---------- 192.168.70.22 8890 172.17.100.97 8890



192.168.70.22:8890으로 들어온 포트를 필자의 컴퓨터 내부 IP인 172.17.100.97:8890으로 보낸다는 의미이다. Jenkins 서버에서 필자의 도커 컨테이너까지의 접근은 아래 이미지를 참고하기 바란다.




이제 젠킨스 Slave Node를 실행하여 도커 컨테이너로 접근해보자. ssh로 접근하기 위해 ssh service를 활성화 시켜준다.


root@8d8eeb87e586:~# service ssh start * Starting OpenBSD Secure Shell server sshd


ssh service 활성화가 완료되면 젠킨스에서 아까 생성한 m7Docker에 진입 후 Launch agent버튼을 눌러 Slave Node를 실행시킨다.



아래와 같은 로그가 올라온다면 ssh접속에 성공한것이다.


[03/22/19 12:21:07] [SSH] Opening SSH connection to 192.168.70.22:8890.

... ...

[03/22/19 12:21:07] [SSH] Starting sftp client. [03/22/19 12:21:07] [SSH] Remote file system root /jenkins does not exist. Will try to create it... [03/22/19 12:21:07] [SSH] Copying latest slave.jar... [03/22/19 12:21:07] [SSH] Copied 771,004 bytes. Expanded the channel window size to 4MB [03/22/19 12:21:07] [SSH] Starting slave process: cd "/jenkins" && java -jar slave.jar <===[JENKINS REMOTING CAPACITY]===>channel started Remoting version: 3.21 This is a Unix agent Evacuated stdout Agent successfully connected and online



이제 젠킨스 빌드 시 이 Slave Node를 활용하겠다는 설정을 해주어야 하는데 프로젝트 진입 → 구성 → Restrict where this project can be run을 체크하고 위에서 생성했던 m7Docker 를 입력하여 저장해준다.



이제 빌드를 진행 해보자.



m7Docker Slave Node에서 빌드가 정상적으로 진행되었다.



지금까지의 과정들은 도커파일을 사용하면 현재 도커 컨테이너와 동일한 설정이 담긴 이미지를 한번에 생성 할 수 있다. 도커파일의 생성방법은 지난 시간에 설명하였으므로 이번 시간에는 도커파일의 스크립트 설명과 직접 도커파일을 빌드하여 이미지를 생성하고 컨테이너에 SSH접근까지만 확인하도록 하겠다.

# Ubuntu 16.04버전을 기반으로 함
FROM ubuntu:16.04

# 다운로드 링크, 파일명, maven 버전 등 변경이 필요한 경우를 대비해 변수로 선언해준다.
ARG jdkFileName=openjdk-11.0.1_linux-x64_bin.tar.gz
ARG jdkDownloadUrl=https://download.java.net/java/GA/jdk11/13/GPL/${jdkFileName}
ARG mavenHome=/usr/local/apache-maven-3.5.3
ARG userName=root
ARG userPassword=xptmxm123

# 패키지 목록 최신화 후 원격 접속을 위한 ssh와 빌드를 위한 maven 및 변경내역을 가져올 git을 설치한다.
RUN apt-get update
RUN apt-get install -y openssh-server
RUN apt-get install -y maven
RUN apt-get install -y git-core

# 현재 jenkins 전역설정에서 maven의 경로는 /usr/local/apache-maven-3.5.3 으로 지정 해두었다.
# ln -s 명령을 사용하여 심볼릭 링크를 걸어준다.
RUN ln -s /usr/share/maven ${mavenHome}

# service 및 api의 빌드는 jdk11이 필요하므로 다운로드 받고 압축을 풀어준다.
RUN wget -P /usr/local ${jdkDownloadUrl}
RUN cd /usr/local/ && tar -xzf ${jdkFileName} && rm ${jdkFileName}

# root 계정을 사용할 것이므로 root계정의 비밀번호 설정 및 root계정으로 ssh접근이 가능하도록 수정한다.
RUN echo "${userName}:${userPassword}" | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# 컨테이너 시작 시 ssh서비스를 Active 시키기 위해 ENTRYPOINT를 지정 해둔다
ENTRYPOINT service ssh restart && /bin/bash

# 외부에서 접근이 가능한 포트를 지정해준다. ssh접속이므로 22번 포트 설정
EXPOSE 22


이제 해당 도커파일을 기반으로 이미지를 생성해보자. 도커파일을 빌드하고 이미지가 잘 생성되었는지 확인해보자.


[root@localhost test2]# docker build -t docker_img ./ ... ... ---> aba77358024b Removing intermediate container 490098d7f585 Step 16/17 : ENTRYPOINT service ssh restart && /bin/bash ---> Running in 22cd10713ee8 ---> 98e07e4fc4b5 Removing intermediate container 22cd10713ee8 Step 17/17 : EXPOSE 22 ---> Running in bcf569c735cc ---> 07f9b213b807 Removing intermediate container bcf569c735cc Successfully built 07f9b213b807 [root@localhost test2]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker_img latest 07f9b213b807 3 minutes ago 939 MB docker.io/ubuntu 16.04 9361ce633ff1 10 days ago 118 MB apache_img first d307433464d8 2 weeks ago 390 MB layer_test second 127ab2a39585 4 weeks ago 188 MB layer_test first 48f47ef8257d 4 weeks ago 188 MB docker.io/ubuntu 14.04 5dbc3f318ea5 8 weeks ago 188 MB


새로만든 이미지로 docker run 명령을 실행하기 전에 이전에 켜두었던 jenkins_slave 컨테이너는 종료 하도록 한다. (포트가 겹치므로)


[root@localhost test2]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d8eeb87e586 docker.io/ubuntu:16.04 "/bin/bash" 19 hours ago Up 4 hours 0.0.0.0:8890->22/tcp jenkins_slave dcc887cf8b0b apache_img:first "apachectl -D FORE..." 2 weeks ago Exited (137) 2 days ago apache_test d33a60d75c45 layer_test:first "/bin/bash" 4 weeks ago Exited (255) 2 weeks ago layer_test2 c73025587f2b ubuntu:14.04 "/bin/bash" 4 weeks ago Exited (0) 4 weeks ago layer_test [root@localhost test2]# docker stop jenkins_slave jenkins_slave [root@localhost test2]#


이제 새로운 이미지로 컨테이너를 생성하도록 한다.
실행이 잘 되었다.


[root@localhost test2]# docker run -i -t -p 8890:22 --name jenkins_slave2 docker_img:latest * Restarting OpenBSD Secure Shell server sshd [ OK ] root@72f83424f1dc:/#


이제 젠킨스에 다시 들어가서 Launch Agent 버튼을 눌러 SSH 접근이 가능한지 확인해보자.

아래 이미지가 출력되면 SSH접속에 성공한것이다.



여기까지 젠킨스 도커 컨테이너를 활용한 Slave Node의 생성과 빌드를 해보고 이 과정을 도커파일로 만들어 이미지를 생성하고 컨테이너 화 하는 실습까지 진행 해보았다. 이미지를 그대로 내려받았을때 세부설정에 대한 변경이 필요한 경우가 있을것이다. 이 때마다 컨테이너를 만들고 설정을 바꿔 다시 commit명령으로 새로운 이미지를 만드는 과정이 생길 수 있는데 도커파일을 활용하면 이러한 낭비를 없앨 수 있다. 또한 도커파일은 설정만 바꾸어 여러대의 서버에 적용하여 사용하는 경우에도 효과적으로 사용할 수 있다.




Docker : Dockerfile 실습 편

끝.



'Docker' 카테고리의 다른 글

Docker : 도커스웜 클러스터 구축 편  (0) 2019.05.17
Docker : 컨테이너 오케스트레이션 개요 편  (0) 2019.04.19
Docker : Dockerfile 실습 편  (0) 2019.03.22
Docker : Dockerfile 편  (0) 2019.03.07
Docker : 이미지 편  (0) 2019.02.22
Docker : 컨테이너 편  (1) 2019.02.15
Posted by DevStream

댓글을 달아 주세요

Docker : Dockerfile 편

Docker 2019. 3. 7. 18:29

Dockerfile 개요



지금까지 도커 이미지를 내려받아 컨테이너를 생성하고 아파치를 설치 후 도커 컨테이너에 접근하는 실습 과정과 아파치가 설치 된 상태까지의 컨테이너를 이미지화하는 내용을 학습하였다.


// 우분투 이미지 다운로드 # docker pull ubuntu:14.04 // 도커 컨테이너 생성 # docker create -i -t --name -p 80:80 ubuntutest docker.io/ubuntu:14:04 b0c51e1ead4b1e4234537ec00394837144ce83f64c2d3c2e1eb7cbabcec8af41 // 컨테이너 활성화 # docker start ubuntutest // 컨테이너 접근 # docker attach ubuntutest // 패키지 업데이트 # apt-get update // 아파치 설치 # apt-get install apache2 -y // 아파치까지 설치 된 상태의 컨테이너를 이미지 화 # docker commit ubuntutest ubuntutest_img



Dockerfile(이하 도커파일)은 위와 같은 일련의 과정들을 기록하고 실행 할 수 있는 일종의 스크립트이다. 도커파일을 실행 할 수 있는 build명령어를 제공하고 있으며 도커파일을 build 할 때 패키지, 콘솔 명령어, Shell Script 등도 함께 포함하여 실행 할 수 있다.


Dockerfile은 콘솔명령어, Shell Script등 기록된 내용을 그대로 실행하는 

일종의 설계도라고 보면 이해하기 쉽다.




Dockerfile 생성



Ubuntu 14.04에 아파치가 설치된 상태의 이미지를 Build 할 수 있는 도커파일을 만들어 보도록 하겠다. 처음부터 도커파일을 작성하기는 쉽지 않으므로 다른사람이 만들어둔 도커파일을 활용하도록 하자. 먼저 다운로드에 앞서 도커허브(https://hub.docker.com/)에 접속 해보자. 도커 허브에 접속하면 바로 검색창이 상단에 보이는데 우리가 찾고자 하는 ubuntu 기반의 아파치 설치를 위해 ubuntu apache라고 검색 해보자.





필자는 업로더 pamtrak06의 ubuntu14.04-apache2 도커파일을 참고하였다. pamtrak06/ubuntu14.04-apache2를 클릭하면 바로 해당 업로더의 페이지로 이동한다.





해당 페이지로 이동하면 pamtrak06 이라는 유저가 업로드한 도커파일뿐만 아니라 이미지도 pull명령어 또는 run명령어를 통해 내려 받을 수 있다. 우리는 도커파일이 필요하므로 Dockerfile 탭을 눌러 스크립트를 확인해보자.





캡쳐된 스크립트의 내용은 아래와 같다.

FROM ubuntu:14.04

MAINTAINER pamtrak06 < pamtrak06@gmail.com >

RUN apt-get update && apt-get install -y apache2 apache2-threaded-dev

# Configure localhost in Apache
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf

# Define default command
CMD ["apachectl", "-D", "FOREGROUND"]

# Expose ports 80/443... : to be override for needs
EXPOSE 80

#USER nobody


해당 텍스트를 복사하여 /home/testuser로 경로이동 후 vi에디터를 통해 Dockerfile을 생성하도록 한다.


여기서 저장하기 전 수정해야 하는 부분이 있는데 아파치를 설치 후 외부에서 접근 가능한 포트를 열어줘야 하므로 'EXPOSE 80'을 추가해준다. 'USER' 구문은 이미 root로 실행하고 있으므로 주석처리 하거나 root로 바꿔준다. -t 옵션을 붙이면 설정한대로 apache_img로 생성 되지만 붙이지 않으면 임의의 16진수로 생성되니 이미지명을 지정하려면 -t 옵션을 꼭 넣기 바란다.


# docker build -t apache_img /home/testuser

Step 1/6 : FROM ubuntu:14.04 Step 2/6 : MAINTAINER pamtrak06 <pamtrak06@gmail.com> ---> Using cache ---> 2c7545bf3112 Step 3/6 : RUN apt-get update && apt-get install -y apache2 apache2-threaded-dev ---> Running in 62fd9a272ce4 Ign http://archive.ubuntu.com trusty InRelease Get:1 http://security.ubuntu.com trusty-security InRelease [65.9 kB] Get:2 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB] Get:3 http://archive.ubuntu.com trusty-backports InRelease [65.9 kB] ... Processing triggers for libc-bin (2.19-0ubuntu6.14) ... Processing triggers for ca-certificates (20170717~14.04.2) ... Updating certificates in /etc/ssl/certs... 148 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d....done. Processing triggers for sgml-base (1.26+nmu4ubuntu1) ... Processing triggers for ureadahead (0.100.0-16) ... ---> 303f9b111bd3 Removing intermediate container 62fd9a272ce4 Step 4/6 : RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf ---> Running in 21b3d68727c2 ---> ff21c8331d36 Removing intermediate container 21b3d68727c2 Step 5/6 : CMD apachectl -D FOREGROUND ---> Running in 93503a25c881 ---> d17b03a01d1f Removing intermediate container 93503a25c881 Step 6/6 : EXPOSE 80 ---> Running in f86591442099 ---> d307433464d8 Removing intermediate container f86591442099

Successfully built 786550292665


빌드가 성공적으로 완료 되었다.




그럼 이제 각 Step별 처리과정에 대해서 알아보도록 하자.


Step 1/6 : FROM ubuntu:14.04 → ubuntu:14.04 이미지를 기반으로 만들겠다는 구문 Step 2/6 : MAINTAINER pamtrak06 <pamtrak06@gmail.com> → 최초 생성자는 pamtrak06이고 email 주소는 pamtrak06@gmail.com 이다. Step 3/6 : RUN apt-get update && apt-get install -y apache2 apache2-threaded-dev → 콘솔명령어 apt-get update로 package 최신화 시킨 후 apache2를 묻지도 따지지도 않고(-y옵션) multi-threaded server 버전으로 다운로드 하라는 뜻

Step 4/6 : RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf → 도커 컨테이너 내부의 apache2.conf에 ServerName을 localhost로 지정 한다는 뜻 (apache2 최초 설치 시 ServerName이 지정 되어있지 않음) Step 5/6 : CMD apachectl -D FOREGROUND → 컨테이너를 올릴때 자동으로 아파치를 기동한다는 명령어 Step 6/6 : EXPOSE 80 → 80번 포트를 외부에서 접근 가능하게 하겠다는 구문



그럼 이제 생성된 이미지를 확인하기 위해 docker images 명령으로 목록을 확인해보자


# docker images REPOSITORY TAG IMAGE ID CREATED SIZE apache_img first d307433464d8 6 minutes ago 390 MB layer_test second 127ab2a39585 13 days ago 188 MB layer_test first 48f47ef8257d 13 days ago 188 MB docker.io/ubuntu 14.04 5dbc3f318ea5 6 weeks ago 188 MB


아까 도커 build명령을 사용하여 빌드할때 설정했던 이름으로 이미지가 잘 생성 되었다. 이제 컨테이너를 생성할 차례인데 이미 도커 파일에서 EXPOSE 80이라는 설정으로 80포트를 오픈 해두었다 이제 해당 포트와 자동으로 매핑 시켜주는 -P 옵션을 추가 해주어야 한다. -d는 detached 옵션으로 백그라운드에서 실행 된다는 뜻이다.



# docker run -d -P --name apache_test apache_img:first 35adceda902976455b18631fe0677d5b3d247700c42ff2791383af40385fe068 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 35adceda9029 apache_img:first "apachectl -D FORE..." 28 seconds ago Up 28 seconds 0.0.0.0:32768->80/tcp apache_test d33a60d75c45 layer_test:first "/bin/bash" 13 days ago Exited (255) 26 hours ago layer_test2 c73025587f2b ubuntu:14.04 "/bin/bash" 13 days ago Exited (0) 13 days ago layer_test 0c18bda4235f ubuntu:14.04 "/bin/bash" 13 days ago Exited (0) 13 days ago nifty_fermat


컨테이너가 잘 생성되었다. 이제 지난 Docker : 컨테이너 편과 마찬가지로 HostOS에서 GuestOS의 아파치로 접근이 가능한지 확인 후 이번 편을 마치도록 하겠다.


는 무언가 잘못 되었다!!


외않되!!


# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 35adceda9029 apache_img:first "apachectl -D FORE..." 28 seconds ago Up 28 seconds 0.0.0.0:32768->80/tcp apache_test d33a60d75c45 layer_test:first "/bin/bash" 13 days ago Exited (255) 26 hours ago layer_test2 c73025587f2b ubuntu:14.04 "/bin/bash" 13 days ago Exited (0) 13 days ago layer_test 0c18bda4235f ubuntu:14.04 "/bin/bash" 13 days ago Exited (0) 13 days ago nifty_fermat


어찌된 영문인지 PORTS 항목을 자세히 보면 포트가 32768로 설정이 되어있다. Dockerfile에서 EXPOSE 80이라는 옵션을 주었기에 -P 옵션은 자동매핑이 가능해서 80은 80포트와 443은 443포트끼리 자동 매핑 되는줄 알았는데 그게 아니었다. 이래서 뇌피셜이 무섭다.

--publish , -pPublish a container’s port(s) to the host
--publish-all , -PPublish all exposed ports to random ports

무려 랜덤 매핑이다.


으응..?


때문에 직접 포트를 지정해주지 않으면 HostOS에서 GuestOS의 동일포트로 넘겨주기 어렵다.

아래와 같이 다시 -p 옵션을 주어 넘겨줄 포트와 넘겨받을 포트를 지정해주도록 하자.


#docker stop 35adceda9029 35adceda9029 # docker rm 35adceda9029 35adceda9029 # docker run -d -p 80:80 --name apache_test apache_img:first b748f27ede243331660ab7ea129a3052b26d416599f85a09ff61cae84efb703f # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b748f27ede24 apache_img:first "apachectl -D FORE..." 18 seconds ago Up 17 seconds 0.0.0.0:80->80/tcp apache_test d33a60d75c45 layer_test:first "/bin/bash" 13 days ago Exited (255) 26 hours ago layer_test2 c73025587f2b ubuntu:14.04 "/bin/bash" 13 days ago Exited (0) 13 days ago layer_test 0c18bda4235f ubuntu:14.04 "/bin/bash" 13 days ago Exited (0) 13 days ago nifty_fermat



설정이 잘 되었다. 이제 HostOS에서 GuestOS 80포트를 다시 호출해보도록 하자. 아래와 같은 화면이 나온다면 접근에 성공한것이다.





여기까지 도커파일을 생성하고 build명령을 통해 이미지 생성 및 컨테이너 생성, 80포트 접근(아파치)까지 진행 해봤다. 도커파일은 고용량 이미지를 보내기 부담스러울 때 텍스트로 대체하여 다른 사람에게 전달 할 수도 있고 이미지를 생성 하기 전 여러가지 옵션으로 설정을 변경 할 수도 있다. 때문에 도커파일은 도커 이미지와는 다르게 여러가지 커스텀한 옵션으로 다양한 환경에서 적절히 사용할 수 있는 아주 유용한 스크립트이다. 다음 편에서는 도커파일을 이용한 실습 및 활용에 대해 설명하겠다.




Docker : Dockerfile 편

끝.

'Docker' 카테고리의 다른 글

Docker : 컨테이너 오케스트레이션 개요 편  (0) 2019.04.19
Docker : Dockerfile 실습 편  (0) 2019.03.22
Docker : Dockerfile 편  (0) 2019.03.07
Docker : 이미지 편  (0) 2019.02.22
Docker : 컨테이너 편  (1) 2019.02.15
Docker : 설치 편  (0) 2019.01.31
Posted by DevStream

댓글을 달아 주세요