00. Prerequisite
docker : Docker version 1.13.0
docker-compose : docker-compose version 1.10.0
AWS instance Type : r4.large
Elasticsearch : 5.4.0
먼저 작업 디렉토리를 ~/elasticsearch 라고 가정하자.
01. Dockerfile 작성
아래와 같이 Dockerfile 을 작성한다.
FROM docker.elastic.co/elasticsearch/elasticsearch:5.4.0 WORKDIR /usr/share/elasticsearch RUN bin/elasticsearch-plugin install discovery-ec2
베이스 이미지는 'docker.elastic.co/elasticsearch/elasticsearch:5.4.0' 이다.
AWS EC2 인스턴스를 사용해 클러스터를 구성해야 하기 때문에 기존의 zen discovery 는 사용할 수 없다. 따라서 docker 이미지를 구울때 'discovery-ec2' 플러그인을 설치해야 한다.
02. docker build
Dockerfile이 위치하고 있는 디렉토리에서, 아래와 같이 'elasticsearch-aws' 라는 이름으로
docker 이미지를 생성한다.
> build log
위의 Warning은 일단 무시하자.
작업 디렉토리에 'config' 디렉토리를 생성하고,
elasticsearch YAML 설정파일을 작성하여 위치 시키자.
위와 같이 'network.publish_host' 설정을 하게되면 ec2의 private ip 로 호스트가 바인딩 된다. 'discovery.type: ec2' 설정도 빠지면 안된다.
그냥 docker run 명령어로 필요한 옵션을 주어 동작을 하게 할 순 있지만, 옵션을 부여하는게 불편하고, 스크립트로 작성해도 유지보수가 귀찮다.
따라서 YAML 형식의 설정을 지원하는 docker-compose로 컨테이너를 구동하려고 한다.
아래와 같이 작업 디렉토리에 docker-compose.yml 파일을 작성한다.
위에서 중요한 설정은 'volumes' 인데, 일단 해당 설정의 첫번째 라인은, 호스트 서버의 외부 elasticsearch.yml 파일을 컨테이너 내부의 elasticsearch.yml 파일에 덮어 쓰는 것이다.
그리고 두번째 라인은 'named volume' 으로서, 컨테이너 내부 디렉토리에 컨테이너 외부 디렉토리를 마운트시키는데, docker자체에서 'esdata' 라는 볼륨으로 관리된다.
해당 볼륨은 service의 이름과 합쳐져서 'elasticsearch_esdata' 라는 볼륨으로 생성되며,
아래와 같은 명령어로 확인 할 수 있다.
위에 'Mountpoint' 값이 마운트된 컨테이너 외부 호스트 디렉토리를 가르킨다.
아래의 명령어로 구동시킨다. 백그라운드 구동일 경우 '-d' 옵션을 붙인다.
위의 01~04 단계를 거친 동일한 docker 기반 elasticsearch 설정을 가지고,
2대의 AWS 인스턴스에 elasticsearch 노드를 띄워서 클러스터링을 해 보려고 한다.
아래를 순서대로 진행한다.
① 1번 AWS 인스턴스에 'node1' elasticsearch 노드 구동
② 2번 AWS 인스턴스에 'node2' elasticsearch 노드 구동
① ② 를 차례대로 진행하면 node1 쪽 로그에 아래와 같이 출력된다.
로그를 보면 알겠지만 뒤늦게 구동된 node2 가 마스터노드인 node1을 발견했다는 내용을 확인 할 수 있다.
그리고 동시에 node2 쪽 로그에는 아래와 같이 출력된다.
반대로 마스터노드인 node1에서는 node2를 ec2 discovery를 이용해 찾고, 클러스터에 추가했다는 내용을 확인 할 수 있다.
이로서 클러스터 구축 완료!
$ docker build -t elasticsearch-aws .
> build log
Sending build context to Docker daemon 4.096 kB Step 1/4 : FROM docker.elastic.co/elasticsearch/elasticsearch:5.4.0 ---> 4c093701c312 Step 2/4 : WORKDIR /usr/share/elasticsearch ---> c784b97dc1e0 Removing intermediate container a93494f1f6f3 Step 3/4 : RUN bin/elasticsearch-plugin install discovery-ec2 ---> Running in a609bd73f8c7 -> Downloading discovery-ec2 from elastic [=================================================] 100%?? @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: plugin requires additional permissions @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ * java.lang.RuntimePermission accessDeclaredMembers * java.lang.RuntimePermission getClassLoader See http://docs.oracle.com/javase/8/docs/technotes/guides/security /permissions.html for descriptions of what these permissions allow and the associated risks. -> Installed discovery-ec2 ---> 6108494a5131 Removing intermediate container a609bd73f8c7 Step 4/4 : EXPOSE 9200 9300 ---> Running in 78105875f3c7 ---> e6fd47d7d666 Removing intermediate container 78105875f3c7 Successfully built e6fd47d7d666
위의 Warning은 일단 무시하자.
03. elasticsearch.yml 작성
작업 디렉토리에 'config' 디렉토리를 생성하고,
elasticsearch YAML 설정파일을 작성하여 위치 시키자.
cluster.name: my-aws-cluster node.name: my-node2 node.master: true node.data: true network.host: 0.0.0.0 network.publish_host: _ec2:privateIp_ discovery.type: ec2 discovery.zen.minimum_master_nodes: 1 discovery.zen.ping.unicast.hosts: - [this host ip] - [host ip 1] - [host ip 2] xpack.security.enabled: false
위와 같이 'network.publish_host' 설정을 하게되면 ec2의 private ip 로 호스트가 바인딩 된다. 'discovery.type: ec2' 설정도 빠지면 안된다.
04. docker-compose.yml 작성
그냥 docker run 명령어로 필요한 옵션을 주어 동작을 하게 할 순 있지만, 옵션을 부여하는게 불편하고, 스크립트로 작성해도 유지보수가 귀찮다.
따라서 YAML 형식의 설정을 지원하는 docker-compose로 컨테이너를 구동하려고 한다.
아래와 같이 작업 디렉토리에 docker-compose.yml 파일을 작성한다.
version: '2' services: elasticsearch: image: elasticsearch-aws container_name: elasticsearch volumes: - ./config/elasticsearch.yml:/usr/share/elasticsearch/config /elasticsearch.yml - esdata:/usr/share/elasticsearch/data ports: - 9200:9200 - 9300:9300 environment: ES_JAVA_OPTS: "-Xmx2048m -Xms2048m" volumes: esdata: driver: local
위에서 중요한 설정은 'volumes' 인데, 일단 해당 설정의 첫번째 라인은, 호스트 서버의 외부 elasticsearch.yml 파일을 컨테이너 내부의 elasticsearch.yml 파일에 덮어 쓰는 것이다.
그리고 두번째 라인은 'named volume' 으로서, 컨테이너 내부 디렉토리에 컨테이너 외부 디렉토리를 마운트시키는데, docker자체에서 'esdata' 라는 볼륨으로 관리된다.
해당 볼륨은 service의 이름과 합쳐져서 'elasticsearch_esdata' 라는 볼륨으로 생성되며,
아래와 같은 명령어로 확인 할 수 있다.
$ docker volume inspect elasticsearch_esdata [ { "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/elasticsearch_esdata/_data", "Name": "elasticsearch_esdata", "Options": {}, "Scope": "local" } ]
위에 'Mountpoint' 값이 마운트된 컨테이너 외부 호스트 디렉토리를 가르킨다.
05. 구동
아래의 명령어로 구동시킨다. 백그라운드 구동일 경우 '-d' 옵션을 붙인다.
$ docker-compose up
06. 클러스터링
위의 01~04 단계를 거친 동일한 docker 기반 elasticsearch 설정을 가지고,
2대의 AWS 인스턴스에 elasticsearch 노드를 띄워서 클러스터링을 해 보려고 한다.
아래를 순서대로 진행한다.
① 1번 AWS 인스턴스에 'node1' elasticsearch 노드 구동
② 2번 AWS 인스턴스에 'node2' elasticsearch 노드 구동
① ② 를 차례대로 진행하면 node1 쪽 로그에 아래와 같이 출력된다.
로그를 보면 알겠지만 뒤늦게 구동된 node2 가 마스터노드인 node1을 발견했다는 내용을 확인 할 수 있다.
그리고 동시에 node2 쪽 로그에는 아래와 같이 출력된다.
반대로 마스터노드인 node1에서는 node2를 ec2 discovery를 이용해 찾고, 클러스터에 추가했다는 내용을 확인 할 수 있다.
이로서 클러스터 구축 완료!