top bar

글 목록

2017년 5월 10일 수요일

[Elasticsearch] AWS + Docker 기반 Elasticsearch 클러스터 구성

회사 업무 관계로, AWS + Docker 기반의 Elasticsearch 클러스터를 구성하게 되었다. 그냥 지나가면 까먹을 것 같아 정리 한다.

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 이미지를 생성한다.

$ 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를 이용해 찾고, 클러스터에 추가했다는 내용을 확인 할 수 있다.

이로서 클러스터 구축 완료!

댓글 없음:

댓글 쓰기