brunch

You can make anything
by writing

C.S.Lewis

by 강진우 Apr 07. 2019

Terraform을 이용한 ES 클러스터 구축

AWS

이번 글에서는 AWS와 연동되는 자동화 툴 중에서도 단연 돋보이는 Terraform을 이용해서 ES 클러스터를 구축하는 방법에 대해서 살펴보겠습니다. Terraform은 이미 너무나도 유명한 툴이기 때문에 툴에 대한 소개나 기본적인 사용방법에 대해서는 넘어가고 바로 본론으로 들어가 보겠습니다.


시스템 구성도


아래 그림은 우리가 이번 글에서 구축하게 될 ES 클러스터의 전체 구성도 입니다.

ES 클러스터의 구성도

클러스터는 총 6개의 노드로 구성되며 마스터 노드 3개, 데이터 노드 3개입니다. 각각은 EC2 인스턴스 하나씩에 올라가고, AZ (Available Zone) 이 2개 존재하기 때문에 각각의 AZ에 위치시킵니다. 그럼 Terraform 파일을 하나하나 만들어 가면서 그림을 완성시켜 보겠습니다.


구축 시나리오


Terraform을 이용해서 클러스터를 구축하기 전에 먼저 설치 과정에 대한 시나리오를 만들고 그에 따라서 Terraform 파일을 만들어야 합니다. 아래는 설치 시나리오입니다.


1. 최초의 마스터 노드 한 대가 실행되어 클러스터를 구성합니다. 하지만 클러스터의 안정성을 위해서 minimum_master_nodes를 2로 할 것이기 때문에 마스터 노드가 모자란다는 에러와 함께 클러스터가 정상적으로 구성되지는 않을 것입니다.

2. 최초의 마스터 노드가 실행된 후에 2대의 마스터 노드를 각각의 AZ에 한 대씩 만듭니다. 이때 discovery.zen.ping.unicast.hosts 값을 최초의 마스터 노드에 대한 IP로 설정하여 최초의 마스터 노드가 만들어 놓은 클러스터에 조인시킵니다. 2번 과정이 끝나게 되면 마스터 노드가 총 3개가 되고 클러스터가 구성되기 시작합니다.

3. 데이터 노드 3대를 실행시킵니다. 이 때도 역시 2번 과정에서 처럼 discovery.zen.ping.unicast.hosts 값을 최초의 마스터 노드에 대한 IP로 설정하여 클러스터에 조인인 시킵니다. 3번까지의 과정이 끝나면 클러스터는 3대의 마스터 노드와 3대의 데이터 노드로 구성됩니다.


그럼 이제부터 본격적으로 Terraform 파일을 만들어 보겠습니다.


최초의 마스터 노드 띄우기


아래는 최초의 마스터 노드를 띄우기 위한 Terraform 코드입니다.

최초의 데이터 노드를 만들 Terraform 코드

크게 두 가지 항목으로 나뉘어 있습니다.


1 : 최초의 마스터 노드 역할을 하게 될 EC2 인스턴스가 만들어진 후 실행하게 될 스크립트입니다. 각각의 노드들은 비어있는 AMI에서 만들어지게 되므로 ES를 설치하고 환경 설정 파일을 수정할 별도의 스크립트가 필요합니다. Terraformtemplate_file (https://www.terraform.io/docs/providers/template/d/file.html)을 이용해서 해당 파일을 정의해 주고, 파일에 있는 변수들의 값을 지정해 줍니다.

2 : 최초의 마스터 노드를 실행하기 위한 정보가 정의되어 있습니다. (https://www.terraform.io/docs/providers/aws/r/instance.html) 어떤 AMI를 통해서 만들 것인지, 그리고 어떤 타입 (사양)으로 만들 것인지를 정의해 줍니다. 그리고 해당 노드에 설정될 보안 그룹의 정보와 1에서 설정한 user_data를 정의해 줍니다. 그리고 마스터 노드는 외부에서의 접근이 필요하지 않기 때문에 공인 IP가 설정되지 않도록 해 줍니다. subnet 역시 VPC 내에 정의된 private subnet을 설정해 줍니다.

2번에 보면 몇 가지 이해할 수 없는 변수들이 있습니다. aws_security_group.elasticsearch_sg.id 와 같은 것들인데요, 이 값들은 뒤에서 나옵니다. 지금은 해당 변수가 있다는 것만 기억해 두시기 바랍니다.

다음엔 1에서 정의한 스크립트 파일을 살펴보겠습니다.

최초의 마스터 노드에서 실행하게 될 스크립트

앞에서 봤던 변수들 cluster_nameheap_memory가 각각 1과 2에 설정되어 있음을 알 수 있습니다.

yum을 이용한 ES 설치가 스크립트에 빠져 있는 것을 보실 수 있습니다. 제가 사용한 AMI는 Packer (https://www.packer.io/intro/)를 이용해서 이미 ES 설치까지만 완료한 AMI이기 때문입니다. Packer에 대한 내용도 다른 글을 통해서 다룰 예정입니다.

여기까지 진행하게 되면 최초의 마스터 노드가 실행됩니다. 아마도 아래와 같은 그림이 될 겁니다.

최초의 마스터 노드가 떠있을 때의 모습

나머지 마스터 노드 띄우기


이제 혼자 쓸쓸히 떠있는 최초의 마스터 노드를 위해 친구들을 만들어 줄 차례입니다.

나머지 마스터 노드 띄우기

최초의 데이터 노드를 띄울 때와 마찬가지로 두 가지 항목으로 나누어집니다.


1 : user-data를 통해서 넘겨줄 스크립트입니다. 최초의 마스터 노드 정의 시와 다른 부분은 변수가 더 추가되었다는 것입니다. 가장 중요한 변수는 first_master_node_ip 일 텐데요, 이 값은 위에서 최초의 마스터 노드 정의로부터 상속받아 가져오게 됩니다. 스크립트는 어떻게 변했는지 밑에서 살펴보겠습니다.

2 : 이번에도 최초의 마스터 노드 정의 시와 유사하지만 count라는 지시자가 추가되었습니다. count는 하나의 Terraform 블록 안에서 N 번의 작업을 할 때 사용하게 되는 지시자입니다. 우리는 master_node_count라는 변수를 받게 될 거고, 이미 최초의 마스터 노드는 띄웠기 때문에 해당 값에서 1을 뺀 값을 count로 넘겨줍니다. 그리고 이 마스터 노드들도 마찬가지로 외부에서의 접근은 필요 없기 때문에 private subnet으로 설정해 줍니다. subnet_id 란에 있는 element 지시자를 눈여겨보시기 바랍니다. private_subnets는 리스트 형식으로 넘어오게 되는 값이고, 이 값을 하나하나 뽑아 사용하게 될 것이기 때문에 element라는 지시자를 통해서 해당 값을 가져오게 합니다. 그리고 마스터 노드의 개수가 private_subnets 값보다 커질 경우를 대비해서 modular 연산을 해서 값을 가져옵니다.

아래는 나머지 마스터 노드들이 실행하게 될 스크립트입니다.

나머지 마스터 노드들이 실행하게 될 스크립트

master, data라는 변수와 함께 first_master_node_ip라는 변수가 추가되었습니다. 눈치채셨을지 모르겠지만 이 스크립트는 뒤에서 데이터 노드들도 실행하게 될 스크립트입니다.

여기까지 진행되었다면 시스템은 아래와 같이 구성되었을 것입니다.

마스터 노드 구축 완료

데이터 노드 생성


이제 데이터 노드를 생성해 보겠습니다.

데이터 노드 생성

데이터 노드 생성 부분은 마스터 노드 생성과는 조금 다릅니다. 데이터 노드는 경우에 따라서 스케일 아웃이 가능해야 하기 때문에 Terraformaws_instance 말고 autoscaling_group을 이용해서 만들어 줍니다. 

1 : 각각의 데이터 노드가 생성된 후 실행하게 될 스크립트를 정의해 줍니다.

2 : autoscaling_group이 자동으로 노드를 늘릴 때 사용하게 될 설정을 정의해 줍니다. (https://www.terraform.io/docs/providers/aws/r/launch_configuration.html) 어떤 AMI를 이용해서 어떤 타입 (사양)으로 실행시킬 것인지 등을 정의해 줍니다. 데이터 노드 역시 외부에서의 접근은 필요 없기 때문에 공인 IP 사용 부분은 false로 둡니다.

3 : autoscaling_group을 정의해 줍니다. 2에서 정의한 설정에 맞게 몇 대의 노드를 실행시킬 것인지를 정의해 주고 어떤 subnet에 위치시킬 것인지 등을 정의해 줍니다. 그리고 autoscaling_group은 자동으로 스케일링을 진행한 후 어떤 LB에 바인딩할 것인지도 정의해 주게 됩니다. 이 값은 target_group_arns 지시자로 정의해 줍니다. 이에 대한 정보도 뒤에 나올 테니 지금은 해당 정보가 필요하다는 것만 알고 넘어가겠습니다.

여기까지 실행해 주면 그림은 아래와 같이 됩니다.

클러스터 완성

이제 마스터 노드 3대, 데이터 노드 3대의 클러스터가 만들어졌습니다. 하지만 해당 서버들은 모두 사설 IP만을 가지고 있기 때문에 외부에서는 확인해 볼 수 있는 방법이 없습니다. 이제 외부와의 연결 통로를 만들어 보겠습니다.


LB와 보안 그룹 설정


먼저 아래와 같이 외부에서 접근이 가능하도록 LB를 만들어 줍니다.

LB 설정하기

크게 3개의 항목으로 나뉘어 있습니다.


1 : LB에 대한 정의를 해 줍니다. 외부에서의 접근이 가능해야 하기 때문에 public_subnets에 위치하도록 만들어 주고 외부에서의 접근이 가능하도록 보안 그룹을 설정해 줍니다. 이 보안 그룹은 사실 위에 마스터 노드와 데이터 노드를 만들 때에도 참조가 되었던 그룹입니다. 이 그룹에 대한 정의는 뒤에서 더 다루겠습니다.

2 : LB에 바인딩될 서버들을 정의해 줍니다. 이 서버들은 타깃 그룹이라고 불리며 aws_alb_target_group 지시자를 통해서 설정해 줄 수 있습니다. 어떤 포트를 사용할 것인지, 어떤 프로토콜을 사용할 것인지, 그리고 어떤 VPC에 생성할 것인지 등등을 정의할 수 있습니다. 여기서 사용하는 타깃 그룹이 데이터 노드들의 autoscaling_group과 연동됩니다. 즉 데이터 노드의 autoscaling_group 정의 시 사용한 target_group_arns값이 여기서 정의한 타깃 그룹들의 ARNS가 됩니다.

3 : LB의 리스너를 정의해 줍니다. 어떤 LB의 리스너를 정의하는 건지 그리고 어떤 포트와 프로토콜을 사용할 것인지를 정의해 줍니다. 

이제 마지막으로 마스터 노드, 데이터 노드, LB에서 다 같이 사용하게 될 보안 그룹에 대한 정의를 해 줍니다.

보안 그룹 설정

XX.XX.XX.XX/32로 표현된 부분은 외부에서 접근 시 사용하게 될 IP를 넣어 주시면 됩니다. (보통 사무실의 IP) 그리고 마스터 노드와 데이터 노드들이 정상적으로 통신할 수 있도록 9300번 포트에 대한 오픈도 잊으면 안 됩니다.

여기까지 진행하게 되면 최종적으로 우리가 만들려고 했던 클러스터가 만들어집니다.

최종 그림

마치며


지금까지 Terraform을 통해서 ES 클러스터를 만드는 과정을 살펴보았습니다. 사실 위에 정의된 내용들은 Terraform의 모듈로 구현된 내용을 가져온 것이기 때문에 빠진 파일들이 있고 위에 정의된 내용들만 가지고는 Terraform 코드가 돌아가진 않습니다. 또한 각각의 정의된 내용을 하나하나 뜯어봐야 했겠지만 그러기에는 내용이 너무 방대해질 것 같아서 전체적인 그림을 살펴보는 과정으로 글을 썼습니다. Terraform을 통해서 하나하나 리소스를 정의해 나가면 그림이 어떻게 달라지는지에 대한 이야기를 하고 싶었습니다. Terraform에 대해 학습하고자 하시면 https://blog.2dal.com/?s=terraform&submit=Search 님의 블로그를 참고하시면 좋습니다.


긴 글 읽어 주셔서 감사합니다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari