[Terraform] 간단한 3-tier 아키텍쳐 - Application
지난 3-tier VPC 구축에 이어서, 이번에는 Application단(EC2, ALB 등)을 설계해보도록 한다.
아키텍쳐 구성도
Terraform 코드 작성
Application 단에서 생성할 리소스는 크게 다음과 같다.
- 인스턴스 4개
- 보안그룹
- 키 페어
- ALB 2개 (외부, 내부)
- 대상그룹 2개 (외부, 내부)
먼저 Application 모듈의 변수들을 구성한다.
Application 단에서 사용될 외부 변수들에는 주로 vpc 관련의 것이 있다. 인스턴스를 생성할 때 사용될 vpc_id나 배치될 서브넷의 id 값이 여기에 해당된다.
이외에도 ami의 id값이나 미리 생성해둔 security group의 id 같은 리소스도 변수로 불러와서 사용할 수도 있을 것이다.
variable "vpc_id" {}
variable "public_subnet_id" {
type = list(string)
}
variable "application_subnet_id" {
type = list(string)
}
이어서 인스턴스를 생성해본다. 생성해야할 인스턴스는 총 4개로 웹 서버용 2개, WAS 서버용 2개가 있다.
이들은 앞서 생성했던 6개의 Private 서브넷 중 4개에 각각 배치되어야한다.
여기에서도 앞서 VPC 부분에서 사용했던 count를 통해 resource block을 2개로 처리해보았다.
# Instance
resource "aws_instance" "simple-3tier-web" {
count = 2
ami = var.instance_ami
instance_type = "t2.micro"
subnet_id = element(var.application_subnet_id, count.index)
user_data = filebase64("${path.module}/script/install_nginx.sh")
key_name = aws_key_pair.simple-3tier-key.key_name
vpc_security_group_ids = [ aws_security_group.simple-3tier-application-sg.id ]
tags = {
Name = "simple-3tier-web-${count.index+1}"
}
}
resource "aws_instance" "simple-3tier-was" {
count = 2
ami = var.instance_ami
instance_type = "t2.micro"
subnet_id = element(var.application_subnet_id, 2+count.index)
user_data = filebase64("${path.module}/script/install_tomcat.sh")
key_name = aws_key_pair.simple-3tier-key.key_name
vpc_security_group_ids = [ aws_security_group.simple-3tier-application-sg.id ]
tags = {
Name = "simple-3tier-was-${count.index+1}"
}
}
인스턴스 resource block을 보면 키 페어를 설정해주는 attribute를 확인할 수 있다.
Terraform에서는 키 페어를 직접 생성하고 등록할 수 있다.
# Key pair
resource "tls_private_key" "simple-3tier-key" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "aws_key_pair" "simple-3tier-key" {
key_name = "simple-3tier-key"
public_key = tls_private_key.simple-3tier-key.public_key_openssh
}
resource "local_file" "simple-3tier-key" {
content = tls_private_key.simple-3tier-key.private_key_pem
filename = "simple-3tier-key.pem"
}
tls_private_key 리소스로 private key를 생성할 수 있고, 여기에서는 Key의 알고리즘과 bit 수를 지정할 수 있다.
그리고 aws_key_pair 리소스에서 tls_private_key 리소스의 public_key 정보를 담아 AWS상에서 사용할 수 있는 키 페어로 등록할 수 있다.
더 나아가 local_file 리소스를 이용해 이 Private key를 로컬파일 형태로 저장할 수도 있다.
이 경우 private_key 리소스의 private_key_pem 값을 content로 가져와서 저장해준다.
+) Terraform Resource로 생성되는 private key는 State file에 Unencrypted되어 저장된다고 한다. Private Key는 Terraform 외부에서 생성한 뒤 Private Key를 사용하는 리소스를 생성할 때에 가져오는 것이 권장된다.
다음으로 인스턴스들을 연결할 ALB 리소스를 생성한다.
ALB 리소스를 만들기 위한 하위 리소스로는 Target Group과 Listener가 존재한다.
### External ALB
resource "aws_alb" "simple-3tier-ex-alb" {
name = "simple-3tier-ex-alb"
internal = false
load_balancer_type = "application"
security_groups = [ aws_security_group.simple-3tier-alb-sg.id ]
subnets = var.public_subnet_id
}
resource "aws_alb_target_group" "simple-3tier-ex-tg" {
name = "simple-3tier-ex-tg"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
}
resource "aws_alb_listener" "simple-3tier-ex-listener" {
load_balancer_arn = aws_alb.simple-3tier-ex-alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_alb_target_group.simple-3tier-ex-tg.arn
}
}
간단하게 구성하기 위해 Target group의 포트와 Listener의 포트를 모두 80으로 설정해주었다.
그리고 각 ALB에 연결할 Target group과 Listener외에도 Target group을 ALB에 연결하는 리소스(alb_target_group_attachment)도 선언을 해준다.
resource "aws_alb_target_group_attachment" "simple-3tier-ex-attach" {
count = 2
target_group_arn = aws_alb_target_group.simple-3tier-ex-tg.arn
target_id = element(aws_instance.simple-3tier-web.*.id, count.index)
port = 80
}
앞서 생성해주었던 웹 서버 인스턴스 2개를 Target group에 할당해주는 것을 볼 수 있다.
웹서버 방향의 외부 ALB를 구축한 것과 마찬가지로 WAS 서버 방향의 내부 ALB도 구축해준다.
### Internal ALB
resource "aws_alb" "simple-3tier-inner-alb" {
name = "simple-3tier-inner-alb"
internal = true
load_balancer_type = "application"
security_groups = [ aws_security_group.simple-3tier-alb-sg.id ]
# subnet is last 2 item of var.application_subnet_id
subnets = slice(var.application_subnet_id, 2,4)
}
resource "aws_alb_target_group" "simple-3tier-inner-tg" {
name = "simple-3tier-inner-tg"
port = 8080
protocol = "HTTP"
vpc_id = var.vpc_id
}
resource "aws_alb_target_group_attachment" "simple-3tier-inner-attach" {
count = 2
target_group_arn = aws_alb_target_group.simple-3tier-inner-tg.arn
target_id = element(aws_instance.simple-3tier-was.*.id, count.index)
port = 8080
}
resource "aws_alb_listener" "simple-3tier-inner-listener" {
load_balancer_arn = aws_alb.simple-3tier-inner-alb.arn
port = "8080"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_alb_target_group.simple-3tier-inner-tg.arn
}
}
내부 ALB에서는 8080포트로 Target group 포트와 Listener 포트를 설정해주었다.
마지막으로 Application 모듈의 output을 작성한다. 생성된 ALB의 DNS 주소 같은 값들이 사용될 수 있다.
output "alb_dns" {
value = aws_alb.simple-3tier-ex-alb.dns_name
}
이렇게 3tier 아키텍쳐의 Application 모듈을 구성해보았다.
해당 프로젝트는 깃헙 레포에서 확인할 수 있다.