본문 바로가기

Java/Vert.x

AWS EC2에서 호스팅되는 Vertx 앱 Hazelcast discovery로 클러스터링하기

테스트 환경 및 주요 아젠다

더보기

이 프로젝트의 개발 환경

  • 개발 언어 및 환경
    • OpenJDK 12.0.1
  • 기타 환경
    • IntelliJ IDEA 2020.3 Ultimate Edition
    • AWS IAM & EC2
    • Hazelcast AWS plugin(AWS Hazelcast discovery)

두 개의 AWS EC2 인스턴스를 생성하고 Hazelcast 멤버로 구성하기 위해 Vertx 애플리케이션을 호스팅합니다.

Vertx 애플리케이션은 Hazelcast AWS plugin(AWS Hazelcast discovery)을 사용하여 클러스터링 됩니다. 클러스터링 멤버 간에는 Vertx의 이벤트 버스를 통해 커뮤니케이션합니다.

Members {size:2, ver:2} [
    Member [10.0.18.170]:5701 - 1e4dc9ea-a823-41ff-80fc-801ecbe04add
    Member [10.0.223.116]:5701 - a60796bb-8a68-4ca1-a5c1-8288315957b1 this
]
  
[2023-01-09 18:38:37.162][INFO][READ]hello world < 7845 [ip-10-0-18-170.ap-northeast-2.compute.internal/10.0.18.170]
[2023-01-09 18:38:44.913][INFO][WRITE]hello world > 6928
[2023-01-09 18:38:44.938][INFO][READ]hello world < 6928 [ip-10-0-223-116.ap-northeast-2.compute.internal/10.0.223.116]
[2023-01-09 18:38:47.040][INFO][READ]hello world < 3690 [ip-10-0-18-170.ap-northeast-2.compute.internal/10.0.18.170]
더보기

Hazelcast 클러스터링을 TCP IP 방식으로 구축하면 Scale In/Out을 위해 전체 cluster.xml 파일을 수정해야 합니다.

Hazelcast discovery는 cluster.xml 파일 변경 없어 Runtime에 Scale In/Out에 용이합니다.

AWS Hazelcast discovery를 이용하려면 다음 AWS 리소스에 대한 준비가 필요합니다.

이미 IAM 사용자 및 VPC가 생성되어 있고, EC2 인스턴스를 생성할 때 IAM 역할에서 ec2:DescribeInstances 권한(AmazonEC2ReadOnlyAccess)이 부여되어 있는 경우 환경 구성을 건너뜁니다.

  • AWS VPC 생성
  • AWS Internet Gateway 생성
  • AWS Subnet 생성
  • AWS IAM 역할 생성
  • AWS 보안 그룹 생성
  • AWS EC2 인스턴스 생성

Step 1: AWS VPC 구성

AWS Console | VPC Section | VPC | VPC 생성에서 VPC를 새로 만듭니다.

생성할 리소스 이름 태그 IPv4 CIDR IPv6 CIDR 블록 테넌시
VPC만 hazelcast-guide 10.0.0.0/16 IPv6 CIDR 블록 없음 기본값

이어서 키: Name 값: hazelcast-guide 태그를 추가합니다.

Step 2: AWS 인터넷 게이트웨이 생성

AWS Console | VPC Section | 인터넷 게이트웨이 | 인터넷 게이트웨이 생성에서 VPC에 연결할 인터넷 게이트웨이를 생성합니다.

인터넷 게이트웨이는 AWS EC2 인스턴스에 SSH 연결하기 위해 사용합니다.

이름 태그 태그 - 태그 키 태그 - 태그 값
hazelcast-guide-igw Name hazelcast-guide-igw

인터넷 게이트웨이를 생성하고 VPC에 연결합니다.

  • 디폴트 상태는 Detached입니다.
  • 이 작업을 완료하면 상태는 Attached가 됩니다.

AWS Console | VPC Section | 인터넷 게이트웨이 | 생성 인터넷 게이트웨이 선택 | 작업 | VPC에 연결에서 다음을 진행합니다.

사용 가능한 VPC에서 hazelcast-guide에 연결합니다.

Step 3: AWS 디폴트 라우트 추가

디폴트 경로를 라우트 테이블에 추가합니다. AWS Console | VPC Section|> VPC | 생성한 VPC 선택 | 세부 정보 탭 | 기본 라우팅 테이블에 들어갑니다.

기본 라우팅 테이블에서 디폴트 Route(0.0.0.0/0)을 추가합니다.

AWS Console | VPC Section | 라우팅 테이블 | 자동 선택된 라우팅 테이블 | 라우팅 탭 | 라우팅 편집 | 라우팅 추가에서 다음을 진행합니다.

대상에서 0.0.0.0/0과 이전 섹션에서 생성한 인터넷 게이트웨이를 연결합니다.

Step 4: AWS VPC의 서브넷 생성

AWS Console | VPC Section | 서브넷 | 서브넷 생성에 들어갑니다.

VPC ID에서 이전 섹션에서 생성한 VPC: hazelcast-guide를 선택합니다.

서브넷 이름 가용 영역 IPv4 CIDR 블록 태그 - 키 태그 값
hazelcast-guides-subnet 아시아 태평양 (서울) / ap-northeast-2a 10.0.0.0/16 Name hazelcast-guides-subnet

Step 5: AWS IAM 역할 생성

AWS EC2에서 ec2:DescribeInstances 권한이 부여된 IAM 역할 필요합니다. Hazelcast 멤버들은 다른 EC2 인스턴스의 IP를 가져와서 동적으로 연결합니다.

AWS Console | Identity and Access Management(IAM) Section | 역할 | 역할 만들기에 들어갑니다.

신뢰할 수 있는 엔터티 유형은 AWS 서비스입니다. 일반 사용 사례는 EC2입니다.

다음으로 이동하여 ec2read를 검색하고 AmazonEC2ReadOnlyAccess 권한 정책을 선택합니다.

다음에서 IAM 역할 이름 hazelcast-guide-iam-role을 입력하고 나머지는 디폴트 설정을 사용합니다.

Step 6: AWS 보안 그룹 설정

보안 규칙을 생성하고 VPC에서 Hazelcast를 위한 인바운드 규칙을 추가합니다. 

5701번 포트는 Hazelcast에서 사용하는 디폴트 포트이므로 인바운드 규칙으로 허용되어야 합니다.

만약 EC2 인스턴스에서 둘 이상의 Hazelcast 멤버를 실행하려면 더 많은 포트를 열어야 할 수 있습니다. 또한 보안 규칙에서는 SSH 연결을 위한 포트 역시 허용되어야 합니다.

AWS Console | VPC Section | 보안 그룹 | 보안 그룹 생성에 들어갑니다.

보안 그룹 이름은 hazelcast-guide-sg입니다. VPC는 이전 섹션에서 생성한 VPC를 선택합니다.

인바운드 규칙 유형  인바운드 규칙 프로토콜 인바운드 규칙 포트 범위 인바운드 규칙 소스
SSH TCP 22 Anywhere-IPv4(0.0.0.0/0)
사용자 지정 TCP TCP 5701 Anywhere-IPv4(0.0.0.0/0)

아웃바운드 규칙에서는 모든 트래픽(0.0.0.0/0)에 대해서 허용합니다.

Step 7: AWS EC2 인스턴스 생성

Hazelcast에서 클러스터링되는 EC2 인스턴스를 생성합니다.

AWS Console > EC2 Section > 인스턴스 > 인스턴스 시작에 들어갑니다.

애플리케이션 및 OS 이미지(Amazon Machine Image)는 CentOS 7 (x86_64) - with Updates HVM입니다.

인스턴스 유형은 t2.micro입니다. 키 페어(로그인)은 선택 안함입니다.

VPC - 필수 서브넷 퍼블릭 IP 자동 할당 방화벽(보안 그룹) 일반 보안 그룹
이전 섹션에서 생성한 VPC 이전 섹션에서 생성한 VPC 서브넷 활성화 기존 보안 그룹 선택 이전 섹션에서 생성한 보안 그룹

IAM 인스턴스 프로파일은 이전 섹션에서 생성한 IAM 역할입니다.

인스턴스 개수는 2입니다.

더보기

AWS EC2 인스턴스에 SSH로 연결하려면 키 페어를 생성해야 합니다.

새 키 페어 생성을 클릭하고 다음과 같이 입력합니다. 이미 키 페어가 있는 경우 기존 키 페어를 사용 할 수 있습니다.

Step 8: AWS EC2에서 Hazelcast 설치

Vertx 애플리케이션을 호스팅하기 위한 AWS EC2 인스턴스와 기타 환경을 구성했습니다.

AWS Console > EC2 Section > 인스턴스에서 EC2 인스턴스 목록을 확인합니다.

EC2 인스턴스에 대한 Public IP는 네트워킹 탭에서 확인합니다.

CLI에서 ssh를 사용해 EC2 인스턴스에 SSH 연결합니다.

$ ssh -i '<key pair file path>' 'centos@<ec2 instance public ip>'
더보기

SSH 연결 중 다음 오류가 발생 할 수 있습니다.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '<key pair file path>' are too open.

키 페어에 대한 접근 권한을 chmod로 수정합니다.

$ chmod 400 <key pair file path>

SSH 연결이 성사되면 EC2 인스턴스에서 Hazelcast를 설치합니다. CentOS 7에서 Package Manager를 사용하여 Hazelcast 설치에 오류가 제한됩니다. 

이 문서에서는 Docker를 사용하여 설치를 진행합니다.

$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
$ sudo systemctl start docker
더보기

SSH 연결 시 centos 계정으로 접근하면 root 권한의 명령문이 실행되지 않습니다.

다음 파일을 열고 아래와 같이 수정합니다.

$ sudo vi /root/.ssh/authorized_keys

ssh-rsa 이전까지 텍스트를 모두 삭제하고 저장합니다.

o-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="echo 'Please login as the user \"centos\" rather than the user \"root\".';echo;sleep 10" ssh-rsa ...

SSH 연결을 종료하고 centos@<ec2 instance public ip> 대신 root@<ec2 instance public ip>으로 다시 연결합니다.

설치가 완료되면 Docker로 Hazelcast를 실행합니다.

$ docker run -it --network host --rm -e HZ_CLUSTERNAME=hello-world -p 5701:5701 hazelcast/hazelcast:5.2.1
...
Members {size:2, ver:2} [
    Member [10.0.18.170]:5701 - 6406114c-8e98-4dd0-8e3d-e1d99f491e35
    Member [10.0.223.116]:5701 - 1823b6ad-a91c-4e9d-8af1-35a6b1ba68c1 this
]
...

Step 9: Vertx 애플리케이션의 Hazelcast 클러스터링 테스트

클러스터링 환경에서 Vertx 애플리케이션이 커뮤니케이션하려면 이벤트 버스 연결에 대한 포트를 허용해야합니다.

AWS Console > EC2 Section > 보안 그룹 > 생성한 보안 그룹 선택 > 인바운드 규칙 탭 > 인바운드 규칙 수정에 들어갑니다.

포트 범위에서 5701 허용을 5701 - 5702로 변경합니다.

AWS Hazelcast discovery에서는 동일한 태그의 EC2 인스턴스와 연결합니다. 이전 섹션에서 생성한 EC2 인스턴스 2개 모두에 태그를 등록합니다.

AWS Console > EC2 Section > 인스턴스 > 생성한 인스턴스 선택 > 태그 탭 > 태그 관리에 들어갑니다.

키는 cluster-tag입니다. 값은 hazelcast-cluster-ec2입니다.

이제 Vertx 애플리케이션에서 클러스터링 구성을 위한 default-cluster.xml 파일을 열고 AWS 

<hazelcast>
    <network>
        <join>
            <aws enabled="true">
                <access-key></access-key>
                <secret-key></secret-key>
                <region></region>
                <tag-key></tag-key>
                <tag-value></tag-value>
            </aws>
        </join>
    </network>
</hazelcast>
aws enabled access-key secret-key region tag-key tag-value
true AWS 계정 또는 IAM 계정의 엑세스 키입니다. AWS 계정 또는 IAM 계정의 시크릿 키입니다. EC2 인스턴스가 실행되는 AWS 리전입니다. 이전 섹션에서 EC2 인스턴스에 등록한 태그입니다.
cluster-taghazelcast-cluster-ec2를 입력합니다.

Vertx 애플리케이션을 실행하고 Hazelcast 클러스터링과 멤버 간 이벤트 버스 커뮤니케이션 로그를 확인합니다.

Members {size:2, ver:2} [
    Member [10.0.18.170]:5701 - 1e4dc9ea-a823-41ff-80fc-801ecbe04add this
    Member [10.0.223.116]:5701 - a60796bb-8a68-4ca1-a5c1-8288315957b1
]
  
[2023-01-09 18:38:37.036][INFO][WRITE]hello world > 7845
[2023-01-09 18:38:37.069][INFO][READ]hello world < 7845 [ip-10-0-18-170.ap-northeast-2.compute.internal/10.0.18.170]
[2023-01-09 18:38:44.947][INFO][READ]hello world < 6928 [ip-10-0-223-116.ap-northeast-2.compute.internal/10.0.223.116]
[2023-01-09 18:38:47.036][INFO][WRITE]hello world > 3690
[2023-01-09 18:38:47.038][INFO][READ]hello world < 3690 [ip-10-0-18-170.ap-northeast-2.compute.internal/10.0.18.170]