🐸 서론
회사 인프라를 점점 MSA 로 옮기고 있는 와중에 내부 ALB 로 gRPC 서버를 연결해야 하는 일이 생겼다.
ALB 를 gRPC 통신을 사용하는 방법을 알아보자.
우리는 ALB를 사용하기로 했는데 이유는 아래와 같다.
1. gRPC Server 를 다중화하고 ALB를 이용해서 부하를 분산시킬 수 있다.
2. EC2 인스턴스는 재시작시 IP 가 변경되는데 그런 변경되는 IP 를 관리할 필요가 없다.
3. ALB 가 Health Check / 장애 발생 시 정상 인스턴스에만 트래픽을 전달해 줌
즉 ALB 를 이용해서 더 고가용성의 서버를 구축할 수 있게 된다.
0. 목차
- Target Group ( 대상그룹 ) 설정
- ALB 생성
- Bastion Server 에서 grpcurl 로 ALB 동작 검증하기 (실패)
- Route53 을 이용해 ALB 에 내부 도메인 설정하기
- Bastion Server 에서 gprcurl 로 ALB 동작 검증하기 (성공)
아키텍처는 아래와 같다.
![](https://blog.kakaocdn.net/dn/c7SLF7/btsMdMokDqf/dXPdJBn0saLHpKozuMnTbk/img.png)
1. Target Group (대상그룹) 설정
ALB 는 하나의 포트에 대해 하나의 Listener를 가질 수 있으며, 한 개의 Listener는 여러 개의 대상 그룹(Target Group)을 가질 수 있다.
즉, 하나의 Listener에서 규칙(Rules)을 이용하여 여러 Target Group으로 라우팅할 수 있다.
ALB 설정 전에 Listener 에 추가할 Target Group 을 먼저 생성해 주자.
EC2 → Load Balancing → Target Groups → Create target group 을 클릭해보자
1-0) Target Group 설정 과정
- Target Group Type 설정
- VPC / Protocol 설정
- HealthCheck 설정
- Register Tareget
- 결과 화면
1-1) Target Group Type 설정
![](https://blog.kakaocdn.net/dn/dzE1ax/btsMftgpqX1/nSSQLhPgaQPDTml3jaT2nK/img.png)
Target Type 은 위의 사진 처럼 네 가지의 종류가 있다.
우리는 ALB 를 이용해서 gRPC Server 에 요청을 전달할 예정이므로
Instances 또는 IP Addresses 를 사용해 주면 된다.
본 글에서 Instances 를 이용해서 EC2 인스턴스에 연결합니다.
Protocol 의 경우 ALB 를 내부 용으로 사용하기 때문에 HTTP 를 선택했습니다.
Port 는 Application 이 실행 중인 9100 번 Port 설정해 줍시다.
1-2) VPC / Protocol Version 선택
![](https://blog.kakaocdn.net/dn/ZnG0u/btsMdITVNJU/HSISSOAyWLk3zWF4H2KIC1/img.png)
VPC 는 Target Group, Target EC2 가 존재하는 VPC 를 선택해 줍시다.
Protocol version 은 gRPC 를 사용할 예정이니 당연히 gRPC 를 선택해 줍니다.
gRPC는 HTTP2 기반이기 때문에 HTTP2 를 선택해도 되지만 AWS 의 설명 처럼 일부 기능을 사용할 수 없다고 합니다.
그러니 저는 gRPC 를 선택했습니다.
1-3) Health Check 설정
![](https://blog.kakaocdn.net/dn/cMv0cM/btsMdGBMfsB/i4GlkUJBcGnpUnlzexUT8K/img.png)
AWS ALB의 gRPC 기본 HealthCheckPath 는 /AWS.ALB/healthcheck 이다.
Advanced health check settings 눌러보자
Success Codes = 12 로 되어 있다
이는 gRPC code 상 NOT IMPLEMENTED 를 의미한다.
즉, AWS 는 대상그룹의 gRPC 서버 까지 요청이 도달하는지만 체크한다는 의미이다.
실제 요청이 성공했는지는 체크하지 않는다.
우리는 상남자 답게 직접 HealthCheck 엔드포인트를 열어 주자
![](https://blog.kakaocdn.net/dn/dAhZF0/btsMft8Aqxq/Bj2OK1c0AGima9nkKuBKK1/img.png)
HealthCheckPath : /chat.HealthCheckService/Check
chat : proto 파일의 package
HealthCheckService : Service
Check : Method
Port 는 Target Group 의 9100 port 를 그대로 사용할 예정이니 Traffic Port 로 선택해 주자.
Health Check port 가 Target Group 에서 설정한 Port 와 다르다면 Override 선택후 port 번호를 입력해 주자.
Success codes
기본값으로 12 가 설정되어 있다. 12는 NOT IMPLEMENTED 를 의미한다.
우리는 실제 요청을 보낼 예정이기 때문에 12로 그대로 두면 오히려 Health Check 가 실패하게 된다.
그러므로 성공을 의미하는 0 ( SUCCESS ) 로 success codes 를 변경해 주자.
1-4) Register Tareget
Target Group 은 말 그대로 요청을 수신할 Target 들의 Group 이다.
Target Group 은 요청을 받아 Health Check 를 성공한 연결 가능한 Target 들에게 요청을 라우팅 한다.
![](https://blog.kakaocdn.net/dn/RyIGm/btsMeJRQBkY/Y0ufFN4ptdo444VpH2PqMK/img.png)
우리는 Target Group Type : Instance 로 설정했으므로 Available instances 에서 요청을 보낼 Target Instance 를 선택해 주자.
![](https://blog.kakaocdn.net/dn/bjry8v/btsMevffHQv/78LRaFpOqvA25txRdA3EaK/img.png)
Target 을 선택했다면 잊지 말고 Include as pending below 버튼을 클릭해 선택한 인스턴스를 Targets 에 추가해 주자.
만약 Target Group Type : IP Addresses 를 선택한 경우
아래의 사진처럼 IP 주소를 입력한 후에 Include as pending below 버튼을 클릭
![](https://blog.kakaocdn.net/dn/P3HYg/btsMd6mzgSp/ZBnQ6wI6dXHeGpxfz4JLEK/img.png)
1-5) 결과
![](https://blog.kakaocdn.net/dn/cMA9nK/btsMesphKhy/7G7v8hek8N92uktAto0Ks0/img.png)
Protocol : gRPC
Health : 헬스체크는 이뤄지지 않은 상태
Load Balancer : 연결된 로드 밸런서 없음
이 대상 그룹은 연결된 Load Balancer 가 없어 사용되지 않고 있으므로 헬스체크가 실행되지 않습니다.
이제 로드 밸런서를 만들어 연결해 줍시다.
2. ALB 생성
생성된 Target Group 에서 Load Balancer 를 서택해 연결할 Load Balancer 를 생성하러 가보자.
![](https://blog.kakaocdn.net/dn/MaSJX/btsMeaPZRHf/3qRuHykZaZ1Ulh0EFwwPDK/img.png)
2-1) ALB 기본 정보
![](https://blog.kakaocdn.net/dn/lfzez/btsMdqeLJ6I/ifVGfDyXpFtpF3XQGlsxbK/img.png)
ALB 이름을 입력해 줍니다.
Scheme: 저는 내부 서버 간 통신을 위한 ALB 이므로 Internal 로 선택
VPC , Availability Zones, Subnet 은 필요한 영역으로 선택해 줍시다
2-2) 보안 그룹 설정
![](https://blog.kakaocdn.net/dn/KS6is/btsMdOfsbfa/qijgbjA5NKYqKgo1rYtZu0/img.png)
이 Load Balancer 의 방화벽입니다.
요청을 받을 수 있는 Inbound Rules 와 요청을 내보내는 Outbound Rules 를 조작할 수 있습니다.
저희는 9100 포트를 사용할 예정이니 Inbound Rule 에서 Custom TCP 9100 port 를 열어주면 되겠습니다.
2-3) Listener 설정 ⭐ 중요 !
![](https://blog.kakaocdn.net/dn/cORtRV/btsMeTNDzEZ/PYzd2nKfVrmQOYNq76zF11/img.png)
ALB 의 Listener는 한 port 번호에 대해 한 개의 Listener 를 설정할 수 있다.
ALB의 9100 PORT 로 들어오는 요청을 앞에서 생성한 Target Group 으로 전달해 주자 !
이 때 중요한 건 ⭐ 반드시 Protocol 을 HTTPS 를 사용해야 한다.
AWS의 ALB는 gRPC를 사용하려면 반드시 HTTPS(HTTP/2) 프로토콜을 사용해야 한다.
( 애초에 HTTP 9100 으로 하면 gRPC target Group 자체 선택이 불가능하다. )
2-4) 보안 설정
![](https://blog.kakaocdn.net/dn/Kog5G/btsMd9p7cHC/qASbsECzA5AJA5xKaqsF41/img.png)
HTTPS 를 사용할 것이니 SSL/TLS certificate 설정을 해주자.
저는 이미 생성한 ACM 을 사용하겠습니다.
( 추후에 나오겠지만 ACM 은 도메인 기반으로 동작하기 때문에 Route53 을 이용해 ALB 에 도메인 주소를 달아주어야 합니다. )
여기까지 설정하셨다면 ALB 를 생성할 수 있습니다 !
2-5) 생성 결과 확인
Load Balancer 를 생성하고 Target Group 을 연결해 주었으니
1번 과정에서 생성한 Target Group 으로 돌아가서 Health Check 가 정상적으로 동작하는지 확인해 줍시다.
Target Group 이 Load Balancer 에 연결 되었으니 자동을 Health Check 가 실행될 것입니다.
( 시간이 조금 걸리니 기다려 주면 됩니다 )
![](https://blog.kakaocdn.net/dn/cMvg0o/btsMdI0KHHu/shdnUSANm4ZTWoeQIVJsu0/img.png)
HealthCheck 가 정상적으로 이뤄진 것을 Health 1 로 확인할 수 있습니다.
3. Bastion Server 에서 grpcurl 로 ALB 동작 검증하기 (실패)
Internal ALB 를 생성했으니 Bastion Server 에서 grpcurl 과 ALB를 이용해서 요청을 보내봅시다.
// -d 는 요청의 payload 입니다. HealthCheck API는 payload 와 관계 없으므로 비워서 보냈습니다.
// -proto 는 요청을 보내는 Instance 내에 proto 파일이 위치한 경로
// ALB DNS NAME:PORT
// 요청을 보낼 메소드 명
grpcurl -d '{}' -proto ./chat.proto \
your-alb-DNS-name.elb.amazonaws.com:9100 \
chat.HealthCheckService/Check
결과
![](https://blog.kakaocdn.net/dn/mKA4u/btsMdoaoWGy/tjkjW97GRcfPuHBUI5L9Nk/img.png)
아마 이런 에러가 발생했을 것입니다.
Failed to dial target host "your-alb-DNS-name.ap-northeast2.elb.amazonaws.com:9100": tls: failed to verify certificate: x509: certificate is valid for
ALB 설정할 때 인증서로 ACM 을 선택했는데 ALB 에 도메인을 달아주지 않았기 때문입니다.
이제 Route53 을 이용해 ALB 에 도메인을 달아주러 갑시다.
4. Route53 을 이용해 ALB 에 내부 도메인 설정하기
그런데 Internal ALB 에도 도메인을 달 수 있나요 ?
⇒ 가능합니다.
Route53 ⇒ Create Hosted Zone 을 클릭해 Pivate hosted zone 을 생성해 주시면
VPC 내에서 사용 가능한 private hosted zone 을 생성할 수 있습니다. ( 간단하니 과정은 생략하겠습니다 )
생성한 Hosted Zone 에 들어가서 Create Record 를 선택해 줍니다.
![](https://blog.kakaocdn.net/dn/cVk799/btsMfuGtrNP/8krdBzG7ck87lDNmiB5ixk/img.png)
사용할 도메인을 입력하고 Record Type ⇒ A 를 선택해 줍니다.
( 깨알 : A Record 는 도메인 이름을 특정 IPv4 주소로 매핑하는 DNS(Domain Name System) 레코드입니다. )
우리는 바로 ALB 의 IP 로 매핑할 것이기 때문에 A 레코드를 사용합니다.
⭐ 중요!
A 레코드를 선택 후 Alias 를 On 해주면 사진과 같이 Route Traffic To 설정이 나옵니다.
여기서 Alias to Application and Classic Load Balancer 를 선택한 후 생성한 ALB 를 선택해 줍니다.
그런데 왜 IP 주소가 아닌 Alias 를 이용해 ALB 를 선택해 주어야 하나요 ?
- ALB는 내부적으로 여러 개의 동적 IP를 가지는데 Alias 를 사용하면 IP 가 변경될 때마다 Route53 이 자동으로 IP를 업데이트 해줌
- ALB가 다수의 IP를 사용하여 트래픽을 분산 처리할 수 있도록 자동 최적화됨.
- 일반적으로 Route 53은 DNS 조회당 비용이 부과되지만, Alias 레코드는 AWS 내부 트래픽으로 처리되어 추가 비용 없이 제공됨.
위와 같이 설정한 후 레코드를 생성해 줍시다.
5. Bastion Server 에서 gprcurl 로 ALB 동작 검증하기 (성공)
Internal ALB 에 Route53을 이용해 도메인을 달아 주었으니
다시Bastion Server 에서 grpcurl 과 ALB를 이용해서 요청을 보내봅시다.
// -d 는 요청의 payload 입니다. HealthCheck API는 payload 와 관계 없으므로 비워서 보냈습니다.
// -proto 는 요청을 보내는 Instance 내에 proto 파일이 위치한 경로
// 이번엔 ALB 의 도메인 명
// 요청을 보낼 메소드 명
grpcurl -d '{}' -proto ./chat.proto \
CREATED_DOMAIN_NAME:9100 \
chat.HealthCheckService/Check
결과
![](https://blog.kakaocdn.net/dn/BMh7D/btsMeMnz9eY/Fmlhyrp3HzmbSa59XUJNnK/img.png)
요청 성공 !
gRPC ALB 설정 참 쉽죠 ?
참조
AWS gRPC : https://aws.amazon.com/ko/blogs/korea/new-application-load-balancer-support-for-end-to-end-http-2-and-grpc/
grpcurl : https://github.com/fullstorydev/grpcurl