티스토리 뷰
안녕하세요. CloudNet@ Terraform Study를 진행하며 해당 내용을 이해하고 공유하기 위해 작성한 글입니다. 도서 ‘Terraform: Up & Running(By Yevgeniy Brikman)’ 의 내용 및 스터디 시간 동안 언급된 주요 내용 위주로 간단히 정리했습니다.
프로덕션 수준의 인프라
- 서버, 데이터 저장소, 로드 밸런서, 보안 기능, 모니터링 및 경고 도구, 파이프라인 구축 및 비즈니스 운영에 필요한 기타 모든 기술을 의미합니다.
- 트래픽 과부하로 인프라가 중단되거나 장애가 발생하여 데이터가 손실되거나 해커의 침입으로 데이터에 문제가 생겨 비지니스가 중단되지 않는 수준입니다.
프로덕션 수준 인프라 구축에 오랜 시간이 걸리는 이유
- 아직 산업의 초기 단계이며, ‘Cloud Computing, IaC, DevOps, Docker, k8s’ 등 도구의 출현과 기술이 빠르게 변하고 있으면 충분히 성숙되지 않았습니다.
- 아직 수행해야 하는 작업의 체크 리스트가 너무 많습니다.
프로덕션 수준 인프라 체크 리스트
“프로덕션 환경으로 전환하는데 필요한 것이 뭐가 있을까요?”
- 대부분 회사는 프로덕션 단계로 전환하기 위한 요구 사항을 명확하게 정의하고 있지않으며 이는 각 인프라가 약간 다르게 배포되거나 중요한 기능이 누락될 수 있음을 의미합니다.
- 대부분의 개발자는 설치, 구성, 프로비저닝 및 배포와 같은 처음 몇가지 작업만 알고 있습니다.
- 예를 들어 서버가 다운되면 어떻게 될까요? 네트워크 작업(VPC, VPN, 서비스 검색 및 SSH 액세스 설정 등) 도 까다롭습니다. TLS를 사용하여 전송 중인 데이터를 암호화하고 인증 처리를 하고 시크릿 저장 방법을 정하는 것과 같은 보안 작업은 잊어버리는 경우가 많습니다.
- 프로뎍션 환경 수준에 참고할만한 추가적인 인프라 체크리스트 예시가 있습니다.
[Production Readiness Checklist — 링크1]
[terraform-The Production Grade Infrastructure Checklist 유투브 — 링크2]
프로덕션 수준 인프라 모듈
위에서 인프라 체크리스트를 확인했으니 이를 구현하기 위해 재사용 가능한 모듈을 구축하는 모범 사례를 살펴보겠습니다.
1. 소형 모듈
- 대형 모듈 단점 : 속도가 느림, 안전하지 않음, 위험성이 높음, 이해하기 어려움, 리뷰하기 어려움, 테스트하기 어려움 등
- 대체 방안 : 소형 모듈로 작성. 이는 클린 코드와 비슷한 내용입니다.
“ 함수의 첫 번째 규칙은 작아야 한다는 것입니다. 함수의 두 번째 규칙은 그보다 더 작아야 한다는 것입니다. — 로버트 C. 마틴”
지금까지 구축한 webserver-cluster 모듈이 커지기 시작했습니다.
여기서는 아래와 같은 3가지 작업을 처리하고 있습니다.
- 오토스케일링 그룹(ASG)
- 애플리케이션 로드 밸런서(ALB)
- Hello, World 애플리케이션
이를 소형 모듈 3개로 리팩터링 해봅니다.
2. 합성 가능한 모듈
- 이제 각각 한가지 작업을 잘 수행하는 2개의 소형 모듈, asg-rolling-deploy 모듈과 alb 모듈이 있습니다.
- 이 모듈들을 어떻게 함께 작동시킬 수 있을까요? 즉, 재사용 가능하고 합성 가능한 모듈(composable module)을 어떻게 구축할까요?
“ 한 가지 일을 잘 해내는 프로그램을 여러 개 작성하세요. 그리고 그 프로그램이 함께 작동하게 하세요. 이것이 바로 유닉스 철학입니다. -더그 매클로이”
- 테라폼 모듈에서 동일한 기본 원칙을 따를 수 있습니다. 모든 것을 입력 변수를 통해 전달하고 모든 것을 출력 변수를 통해 반환하며 간단한 모듈들을 결합해 더 복잡한 모듈을 만들 수 있습니다.
- modules/cluster/asg-rolling-deploy/variables.tf 에 아래 새로운 입력 변수 4개를 추가합니다.
# subnet_ids 는 asg-rolling-deploy 모듈을 배포할 서브넷을 지정
variable "subnet_ids" {
description = "The subnet IDs to deploy to"
type = list(string)
}
# target_group_arns 과 health_check_type 변수는
# ASG를 로드 밸런서와 통합하는 방식을 구성
variable "target_group_arns" {
description = "The ARNs of ELB target groups in which to register Instances"
type = list(string)
default = []
}variable "health_check_type" {
description = "The type of health check to perform. Must be one of: EC2, ELB."
type = string
default = "EC2"
}# user_data 는 사용자 데이터 스크립트를 전달
variable "user_data" {
description = "The User Data script to run in each Instance at boot"
type = string
default = null
}
- modules/cluster/asg-rolling-deploy/outputs.tf 에 유용한 출력 변수 몇 개를 다음과 같이 추가합니다.
- 보안 그룹에 사용자 정의 규칙을 추가하는 등 새로운 동작을 추가할수 있어서 asg-rolling-deploy 모듈의 재사용성을 높일 수 있습니다.
output "asg_name" {
value = aws_autoscaling_group.example.name
description = "The name of the Auto Scaling Group"
}
output "instance_security_group_id" {
value = aws_security_group.instance.id
description = "The ID of the EC2 Instance Security Group"
}
- 비슷한 이유로 modules/networking/alb/outputs.tf 에 추가해야 합니다.
output "alb_dns_name" {
value = aws_lb.example.dns_name
description = "The domain name of the load balancer"
}
output "alb_http_listener_arn" {
value = aws_lb_listener.http.arn
description = "The ARN of the HTTP listener"
}output "alb_security_group_id" {
value = aws_security_group.alb.id
description = "The ALB Security Group ID"
}
- 마지막 단계는 asg-rolling-deploy 및 alb 모듈을 사용하여 webserver-cluster 모듈을 ‘Hello, World’ 앱을 배포할 수 있는 hello-world-app 모듈로 변환하는 것입니다.
- 이를 수행하기 위해 module/services/webserver-cluster의 이름을 module/services/hello-world-app으로 변경합니다.
- 이때, module/services/hello-world-app/main.tf 에 아래 리소스는 남겨둡니다.
resource "aws_lb_target_group" "asg" {
name = var.cluster_name
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}resource "aws_lb_listener_rule" "asg" {
listener_arn = aws_lb_listener.http.arn
priority = 100 condition {
path_pattern {
values = ["*"]
}
} action {
type = "forward"
target_group_arn = aws_lb_target_group.asg.arn
}
}data "terraform_remote_state" "db" {
backend = "s3" config = {
bucket = var.db_remote_state_bucket
key = var.db_remote_state_key
region = "us-east-2"
}
}data "aws_vpc" "default" {
default = true
}data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}
- modules/services/hello-world-app/variables.tf 에 아래 변수를 추가합니다.
variable "environment" {
description = "The name of the environment we're deploying to"
type = string
}
- 전에 작성한 asg-rolling-deploy 모듈을 hello-world-app 모듈에 추가합니다
module "asg" {
source = "../../cluster/asg-rolling-deploy"
cluster_name = "hello-world-${var.environment}"
ami = var.ami
instance_type = var.instance_type user_data = templatefile("${path.module}/user-data.sh", {
server_port = var.server_port
db_address = data.terraform_remote_state.db.outputs.address
db_port = data.terraform_remote_state.db.outputs.port
server_text = var.server_text
}) min_size = var.min_size
max_size = var.max_size
enable_autoscaling = var.enable_autoscaling subnet_ids = data.aws_subnets.default.ids
target_group_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"
custom_tags = var.custom_tags
}
- 그리고 이전에 생성한 alb 모듈을 hello-world-app 모듈에 추가합니다
module "alb" {
source = "../../networking/alb"
alb_name = "hello-world-${var.environment}"
subnet_ids = data.aws_subnets.default.ids
}
- environment 입력 변수를 사용해 모든 리소스의 네임스페이스가 hello-world-stage, hello-world-prod 같은 환경을 기준으로 지정되도록 명명 규칙을 시행합니다.
- 이 코드는 또한 이전에 추가한 새로운 subnet_ids, target_group_arns, health_check_type, and user_data 변수를 적절한 값으로 설정합니다.
- 다음으로 이 앱에 대한 ALB 대상 그룹 및 리스너 규칙을 구성합니다.
- name 에서 environment 를 사용하도록 module/services/hello-world-app/main.tf에서 aws_lb_target_group 리소스를 업데이트합니다.
resource "aws_lb_target_group" "asg" {
name = "hello-world-${var.environment}"
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
- 이제 aws_lb_listener_rule 리소스의 listener_arn 매개 변수가 ALB 모듈의 alb_http_listener_arn 출력을 가리키도록 업데이트합니다.
resource "aws_lb_listener_rule" "asg" {
listener_arn = module.alb.alb_http_listener_arn
priority = 100
condition {
path_pattern {
values = ["*"]
}
} action {
type = "forward"
target_group_arn = aws_lb_target_group.asg.arn
}
}
- 마지막으로 asg-rolling-deploy 및 alb 모듈의 중요한 출력을 hello-world-app 모듈의 출력으로 전달합니다.
output "alb_dns_name" {
value = module.alb.alb_dns_name
description = "The domain name of the load balancer"
}
output "asg_name" {
value = module.asg.asg_name
description = "The name of the Auto Scaling Group"
}output "instance_security_group_id" {
value = module.asg.instance_security_group_id
description = "The ID of the EC2 Instance Security Group"
}
3. 테스트 가능한 모듈
- asg-rolling-deploy, alb, hello-world-app의 세 가지 모듈 형식으로 많은 코드를 작성했습니다. 다음 단계는 코드가 실제로 작동하는지 확인하는 것입니다.
- examples/asg/main.tf 작성 : asg-rolling-deploy 모듈을 사용하여 크기가 1인 ASG를 배포해봅니다. [실습 코드]
4. 릴리스 가능한 모듈
- 모듈을 작성하고 테스트한 후 다음 단계는 릴리스(release)하는 것입니다.
- 테라폼 0.13 validation blocks 은 입력 변수를 체크합니다.
[참고 : 실습 코드 ]
blog migration project
written in 2022.12.4
https://medium.com/techblog-hayleyshim/iac-production-grade-terraform-code-4417b98185e3
'Programming > IaC' 카테고리의 다른 글
[IaC] Working with Multiple Providers (0) | 2023.10.28 |
---|---|
[IaC] GKE configuration deep dive (0) | 2023.10.28 |
[IaC] Managing Secrets with Terraform (0) | 2023.10.28 |
[IaC] Terraform tips & tricks — Loops & Conditions (0) | 2023.10.28 |
[IaC] Terraform modules (0) | 2023.10.28 |
- Total
- Today
- Yesterday
- S3
- handson
- OS
- 혼공파
- GKE
- EKS
- NW
- GCP
- operator
- gcp serverless
- 혼공단
- terraform
- cloud
- NFT
- 도서
- cni
- k8s
- AWS
- k8s cni
- k8s calico
- PYTHON
- security
- AI
- IaC
- 국제 개발 협력
- VPN
- 파이썬
- SDWAN
- controltower
- 혼공챌린지
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |