IT STUDY LOG
Sprint - Terraform x AWS 본문
#학습 목표
다음의 아키텍처를 terraform을 이용해 작성
- 퍼블릭 인터넷이 아닌 웹 서버에서만 DB 인스턴스를 사용할 수 있어야 하므로 퍼블릭 서브넷과 프라이빗 서브넷을 모두 포함하여 VPC를 생성
- 퍼블릭 서브넷에서 웹 서버를 호스팅하므로 웹 서버에서 퍼블릭 인터넷에 액세스 가능
- DB 인스턴스는 프라이빗 서브넷에서 호스팅
- Amazon EC2 인스턴스는 동일한 VPC 내에서 호스팅되므로 DB 인스턴스에 연결할 수 있으나 퍼블릭 인터넷에서는 DB 인스턴스를 사용할 수 없으므로 보안이 강화됨
- 별도의 가용 영역에서 추가 퍼블릭 및 프라이빗 서브넷을 구성
- Amazon RDS DB 인스턴스용 VPC 구성
- 이러한 VPC 시나리오에 대한 웹 서버를 생성하는 방법을 보여 주는 자습서는 자습서: 웹 서버 및 Amazon RDS DB 인스턴스 생성 단원을 참조
- Amazon VPC 대한 자세한 내용은 Amazon VPC 시작 안내서 및 Amazon VPC 사용 설명서를 참조
- Amazon EC2 인스턴스와 DB 간에 네트워크 연결을 설정할 수 있음(자세한 내용은 EC2 인스턴스와의 자동 네트워크 연결 구성 섹션 참조)
#해결 과제
💡 자습서: DB 인스턴스에 사용할 Amazon VPC 생성
💡 EC2 인스턴스 생성
💡 애플리케이션 로드 밸런서 및 Auto Scaling Group 적용
# 참고 사항
- IaC 코드를 작성하려면 먼저 AWS Management Console을 이용해 먼저 최종 인프라 상태를 만들어놓고, 잘 작동하는지 확인한 다음, 이를 해당하는 리소스를 하나씩 코드로 옮기는 방법을 사용하는 방식을 사용하기
- 먼저 AWS Management Console을 통해 최종 결과물을 따라 해보고, 예상 상태가 무엇인지 먼저 파악
- 모든 리소스를 만들 때에는 반드시 이름을 붙이기
#과제 항목별 진행 상황
✏️ Terraform 구조 및 파일 구성
# version.tf : terraform 블럭
# variables.tf : 변수
# main.tf : IaC 인프라 생성 코드
# outputs.tf : RDS 생성 후 정보
# user-data.sh : EC2 생성 시 사용자 데이터
# version.tf
terraform {
cloud {
organization = "roheerumi"
workspaces {
name = "terraform-study"
}
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.67.0"
}
}
}
}
# variables.tf
variable "region" {
default = "ap-northeast-2"
description = "AWS region"
}
variable "server_port" {
default = 80
}
# main.tf
# 1) AWS provider의 resource, 2) terraform의 aws 레지스트리 module 사용
provider "aws" {
region = var.region
}
# ... 하략 ... #
✏️ 자습서: DB 인스턴스에 사용할 Amazon VPC 생성
Step 1 : VPC 및 서브넷 생성
- 프라이빗 서브넷 2개와 퍼블릭 서브넷 2개로 총 네 개 생성
[AWS 콘솔] 콘솔에서 생성
- https://console.aws.amazon.com/vpc/에서 Amazon VPC 콘솔로 접속
- AWS Management Console의 오른쪽 상단에서 VPC를 생성할 리전을 선택
- 왼쪽 상단 모서리에서 VPC 대시보드를 선택 VPC 생성을 시작하려면 VPC 생성을 선택
- VPC 설정의 생성할 리소스에서 VPC 등을 선택
- VPC 설정을 위해 다음 값을 설정
- 네임 태그 자동 생성 - 사용할 이름 지정
- IPv4 CIDR block: - 10.0.0.0/16
- IPv6 CIDR 블록 - No IPv6 CIDR Block(IPv6 CIDR 블록 없음)
- 테넌시 - 기본값
- 가용 영역(AZ)의 수 - 2
- Customize AZs(AZ 사용자 지정) - 기본값을 유지
- 퍼블릭 서브넷 수 – 2
- 프라이빗 서브넷 수 – 2
- Customize subnets CIDR blocks(서브넷 CIDR 블록 사용자 지정) - 기본값을 유지
- NAT 게이트웨이($) – 있음
- VPC 엔드포인트 – 없음
- DNS options(DNS 옵션) - 기본값을 유지
- VPC 생성을 선택
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
# 1. VPC 생성
# IPv4 CIDR block: - 10.0.0.0/16
# IPv6 CIDR 블록 - No IPv6 CIDR Block(IPv6 CIDR 블록 없음)
# 테넌시 - 기본값
# 가용 영역(AZ)의 수 - 2
# Customize AZs(AZ 사용자 지정) - 기본값을 유지
# 퍼블릭 서브넷 수 – 2
# 프라이빗 서브넷 수 – 2
# Customize subnets CIDR blocks(서브넷 CIDR 블록 사용자 지정) - 기본값 유지
# NAT 게이트웨이($) – 생성
# VPC 엔드포인트 – 없음
# DNS options(DNS 옵션) - 기본값 유지
module "terraform-aws-vps" { # 모듈 사용
source = "terraform-aws-modules/vpc/aws"
# 이름 및 vpc cidr 지정
name = "terraform-aws-vps"
cidr = "10.0.0.0/16"
# az, 서브넷 cidr 지정
azs = ["ap-northeast-2a", "ap-northeast-2c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
# 각 서브넷 생성 시 suffix 시정
private_subnet_suffix = "private"
public_subnet_suffix = "public"
# igw 이름 지정
igw_tags = {
Name = "terraform-aws-public-igw"
}
# nat gateway 생성 및 설정, 이름 지정
enable_nat_gateway = true
one_nat_gateway_per_az = true
nat_gateway_tags = {
Name = "terraform-aws-public-nat"
}
}
→ Result : terraform apply 실행 결과
(1) VPC 생성
(2) 4개 서브넷 생성
(3) 라우팅 테이블 생성
(4) IGW 생성
(5) NAT Gateway 및 관련 리소스(EIP 등) 생성
Step 2 : VPC 보안 그룹 생성 : 퍼블릭 웹 서버가 사용할 VPC 보안 그룹과 프라이빗 DB 웹 서버가 사용할 VPC 보안 그룹을 만들기
[AWS 콘솔] 콘솔에서 생성
2-1. 퍼블릭 서브넷의 보안 그룹 생성
- https://console.aws.amazon.com/vpc/에서 Amazon VPC 콘솔로 접속
- VPC 대시보드, 보안 그룹, 보안 그룹 생성을 차례대로 선택
- 보안 그룹 생성 페이지에서 다음 값을 설정
- 보안 그룹 이름: terraform-aws-securitygroup
- 설명: terraform-aws Security Group
- VPC: 이전에 생성한 VPC를 선택(예: vpc-identifier(terraform-aws-vpc)).
- 인바운드 규칙을 보안 그룹에 추가
- Secure Shell(SSH)을 사용하여 VPC의 EC2 인스턴스에 연결하는 데 사용할 IP 주소를 지정
- 퍼블릭 IP 주소를 확인하려면 다른 브라우저 창 또는 탭에서 https://checkip.amazonaws.com의 서비스를 사용
- 인바운드 규칙 섹션에서 규칙 추가를 선택
- 새로운 인바운드 규칙으로 다음 값을 설정하여 SSH에서 Amazon EC2 인스턴스에 액세스하도록 허용 (Amazon EC2 인스턴스에 연결하여 웹 서버 및 다른 유틸리티를 설치 가능하며 EC2 인스턴스에 연결하여 웹 서버의 콘텐츠를 업로드 가능)
- Type: SSH
- 소스: 4-1단계에서 확인한 퍼블릭 IP 주소 또는 범위(예: 203.0.113.25/32)
- [다른 규칙 추가(Add another rule)]를 선택
- 새 인바운드 규칙에 다음 값을 설정하여 웹 서버에 대한 HTTP 액세스를 허용
- 유형: HTTP
- 소스: 0.0.0.0/0
- Secure Shell(SSH)을 사용하여 VPC의 EC2 인스턴스에 연결하는 데 사용할 IP 주소를 지정
- 모든 아웃 바운드를 허용하는 아웃바운드 규칙을 보안 그룹에 추가
- 보안 그룹을 생성하려면 보안 그룹 생성(Create security group)을 선택
2-2. 프라이빗 DB 인스턴스에 대한 VPC 보안 그룹 생성
- https://console.aws.amazon.com/vpc/에서 Amazon VPC 콘솔로 접속
- VPC 대시보드, 보안 그룹, 보안 그룹 생성을 차례대로 선택
- 보안 그룹 생성 페이지에서 다음 값을 설정
- 보안 그룹 이름: terraform-aws-db-securitygroup
- 설명: terraform-aws DB Instance Security Group
- VPC: 이전에 생성한 VPC를 선택(예: vpc-identifier(terraform-aws-vpc)).
- 인바운드 규칙을 보안 그룹에 추가
- 인바운드 규칙 섹션에서 규칙 추가를 선택
- 새로운 인바운드 규칙으로 다음 값을 설정하여 Amazon EC2 인스턴스의 포트 3306에서 MySQL 트래픽을 허용 ( 웹 서버에서 DB 인스턴스에 연결 가능하며 웹 애플리케이션의 데이터를 데이터베이스에 저장하고 검색 가능)
- 유형: MySQL/Aurora
- 소스: 이 자습서에서 이전에 생성한 terraform-aws-securitygroup 보안 그룹의 식별자(예: sg-9edd5cfb)
- 보안 그룹을 생성하려면 보안 그룹 생성을 선택
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
#1. public subnet 보안그룹 생성
resource "aws_security_group" "public-terraform-aws-security-group" {
name = "public-terraform-aws-security-group"
description = "public-terraform-aws-security-group"
# VPC: 이전에 생성한 VPC를 선택
vpc_id = module.terraform-aws-vps.vpc_id
# inbound 규칙에 ssh, http 허용
ingress {
description = "Allow to Connect VPC EC2 instances by SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["HOST IP ADDRESS/32"]
}
ingress {
description = "Allow to Connect VPC EC2 instances by SSH"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/32"]
}
ingress {
description = "Allow Public Client to Connect VPC EC2 by HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# outbound 규칙에 전부 허용 - apt update 등을 위해
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "public-terraform-aws-security-group"
}
}
###################################################################################
# 2. private subnet 보안그룹 생성
resource "aws_security_group" "private-terraform-aws-db-security-group" {
name = "private-terraform-aws-db-security-group"
description = "private-terraform-aws-db-security-group"
# VPC: 이전에 생성한 VPC를 선택
vpc_id = module.terraform-aws-vps.vpc_id
# inbound 규칙에 ec2에서 3306포트에 접근 가능하도록 ec2 보안 그룹 허용
ingress {
description = "Allow EC2 instances to Connect MySQL"
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = [aws_security_group.public-terraform-aws-security-group.id]
}
egress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "private-terraform-aws-db-security-group"
}
}
→ Result : terraform apply 실행 결과
Step 3 : DB 서브넷 그룹 생성 : RDS 인스턴스가 사용할 VPC 서브넷 그룹을 만들기
[AWS 콘솔] 콘솔에서 생성
3-1. VPC 콘솔에서 DB 서브넷 그룹 생성 시 참고할 프라이빗 서브넷 식별
- https://console.aws.amazon.com/vpc/에서 Amazon VPC 콘솔로 접속
- VPC 대시보드를 선택한 다음 서브넷을 선택
- terraform-aws-subnet-private1-ap-northeast-2a 및 terraform-aws-subnet-private2-ap-northeast-2b라는 서브넷의 서브넷 ID를 기록
3-2. RDS 콘솔에서 DB 서브넷 그룹 생성 시 참고할 프라이빗 서브넷 식별
- https://console.aws.amazon.com/rds/에서 Amazon RDS 콘솔로 접속
- Amazon VPC 콘솔이 아닌 Amazon RDS 콘솔에 연결해야 함
- 탐색 창에서 [Subnet groups]를 선택
- DB 서브넷 그룹 생성을 선택
- DB 서브넷 그룹 생성 페이지에서 서브넷 그룹 세부 정보에 아래 값을설정
- 이름: terraform-aws-db-subnet-group
- 설명: terraform-aws DB Subnet Group
- VPC: terraform-aws-vpc(vpc-identifier)
- 서브넷 추가 섹션에서 가용 영역 및 서브넷을 선택
- VPC 생성 시 선택한 가용 영역으로 선택하고 서브넷에서 이전 단계에서 식별한 프라이빗 서브넷을 선택
- 생성(Create)을 선택
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
# DB 서브넷 그룹 생성
resource "aws_db_subnet_group" "terraform-aws-db-subnet-group" {
name = "terraform-aws-db-subnet-group"
description = "terraform-aws-db-subnet-group"
# private 서브넷으로 지정
subnet_ids = module.terraform-aws-vps.private_subnets
tags = {
Name = "terraform-aws-db-subnet-group"
}
}
→ Result : terraform apply 실행 결과
✏️ EC2 인스턴스 생성
- 생성할 EC2 사양
- AMI: Ubuntu Server 18
- 인스턴스 타입: t2.micro
- 사용자 데이터
- #!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
- #!/bin/bash
- 키 페어: 수동으로 만들고 EC2에 할당
Step 1 : EC2 생성
[AWS 콘솔] 콘솔에서 생성
- [이름 및 태그] 섹션에서 EC2 인스턴스 이름 지정
- [애플리케이션 및 OS 이미지] 섹션에서사용할 AMI 지정
- [인스턴스 유형] 섹션에서사용할 인스턴스 유형 지정
- [키 페어(로그인)] 섹션에서 키 페어를 새로 생성하거나 사용하는 키페어로 지정
- [네트워크 설정] 섹션의 VPC에 생성한 VPC 지정
- [네트워크 설정] 섹션의 서브넷에 해당 VPC의 퍼블릭 서브넷 선택
- [네트워크 설정] 섹션의 퍼블릭 IP 자동 할당에 활성화 설정
- [네트워크 설정] 섹션의 방화벽(보안 그룹)을 기존 보안 그룹 선택 > 생성한 퍼블릭 서브넷의 보안그룹 선택
[Terraform] IaC 코드로 작성
###################################################################################
# EC2 인스턴스 생성
# 1. 각 가용영역에 EC2 인스턴스 생성을 위해 local 변수 선언
locals {
# VPC에서 생성한 퍼블릭 서브넷 리스트
public_subnets = module.terraform-aws-vps.public_subnets
public_instance_conf = [
for index, subnet in local.public_subnets : [{
# 각 퍼블릭 서브넷에 생성
subnet_id = subnet
# 사용할 보안 그룹으로 퍼블릭 서브넷에 생성한 보안 그룹 지정
vpc_security_group_ids = [aws_security_group.public-terraform-aws-security-group.id]
# 인스턴스명, 사용할 ami와 instance type, 사용할 key-pair 이름 지정
name = "terraform-aws-ec2-${index}"
ami = "ami-0a2a74934366c9715" # AMI: Ubuntu Server 18
instance_type = "t2.micro" # 인스턴스 타입: t2.micro
key_name = "terraform-aws-key-pair" # 수동으로 만든 key pair를 EC2에 할당
# EC2 시작시 실행할 사용자 데이터 입력
user_data = <<-EOF
#!/bin/bash
sudo apt update
sudo apt install -y mysql-server
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
EOF
}
]
]
}
# terraform의 platten 함수를 이용해 일관된 시퀀스로 만듦
locals {
public_instance = flatten(local.public_instance_conf)
}
###################################################################################
# 2. local 변수를 활용해 EC2 인스턴스들 생성
resource "aws_instance" "terraform-aws-ec2" {
for_each = {for key, value in local.public_instance : key => value}
ami = each.value.ami
instance_type = each.value.instance_type
# network
vpc_security_group_ids = each.value.vpc_security_group_ids
subnet_id = each.value.subnet_id
associate_public_ip_address = true
# key-pair
key_name = each.value.key_name
user_data = each.value.user_data
tags = {
Name = each.value.name
Group = "terraform-aws-ec2"
}
}
→ Result : terraform apply 실행 결과
(1) EC2 인스턴스 생성
(2) 사용자 데이터 실행 내역
> 웹 서비스 기동
> mysql 서버 설치 후 DB 연결 되는지 확인
✏️ 자습서: DB 인스턴스 생성
Step 1 : DB 인스턴스 생성
[AWS 콘솔] 콘솔에서 생성
- AWS Management Console에 로그인한 후 https://console.aws.amazon.com/rds/에서 Amazon RDS 콘솔로 접속
- AWS Management Console의 오른쪽 상단 모서리에서 AWS 리전을 확인 EC2 인스턴스를 생성한 리전과 동일해야 함
- 탐색 창에서 데이터베이스를 선택
- 데이터베이스 생성을 선택
- 데이터베이스 생성 페이지에서 표준 생성을 선택
- 엔진 유형(Engine type)에서 MySQL을 선택
- 템플릿에서 프리 티어를 선택
- 가용성 및 내구성 섹션에서 기본값을 사용
- 설정 섹션에서 아래 값들을 설정
- DB 인스턴스 식별자 – terraform-aws-db-instance를 입력
- 마스터 사용자 이름 - admin 등 사용자명 입력
- Auto generate a password(암호 자동 생성) - 옵션 끄기
- 마스터 암호 – 암호를 입력
- 암호 확인 – 암호를 다시 입력
- [인스턴스 구성] 섹션에서 다음 값을 설정
- 버스트 가능 클래스(t 클래스 포함)
- db.t3.micro
- 스토리지 섹션에서 기본값으로 유지
- 연결 섹션에서 아래 값을 설정하고 다른 값을 기본값으로 유지
- 컴퓨팅 리소스에서 EC2 컴퓨팅 리소스에 연결을 선택
- EC2 인스턴스의 경우 terraform-aws-ec2-instance-web-server와 같이 이전에 생성한 EC2 인스턴스를 선택
- 서브넷 그룹에서 생성한 서브넷 선택
- 퍼블릭 액세스 불허
- VPC 보안 그룹에 기존 항목 선택
- [데이터베이스 인증(Database authentication)] 섹션에서 [암호 인증(Password authentication)]이 선택되어 있는지 확인
- 추가 구성 섹션을 열고 초기 데이터베이스 이름에 sample를 입력 다른 옵션은 기본 설정을 유지
- MySQL DB 인스턴스를 생성하려면 [데이터베이스 생성(Create database)]을 선택
- 새 DB 인스턴스가 데이터베이스목록에 생성 중의 상태로 나타나며 새 DB 인스턴스의 상태가 사용 가능으로 나타날 때까지 기다린 후 세부 정보를 표시할 DB 인스턴스 이름을 선택
- Connectivity & security(연결 및 보안) 섹션에서 DB 인스턴스의 엔드포인트 및 포트를 확인
- DB 인스턴스의 엔드포인트와 포트를 사용하여 웹 서버를 RDS DB 인스턴스에 연결
[Terraform] IaC 코드로 작성
# variables.tf
# 변수로 사용할 패스워드 지정
variable "MYSQL_DB_PASSWORD" {
description = "MySQL admin user password"
type = string
sensitive = true
}
# 추후 콘솔에서 DB 패스워드 환경 변수 선언
$ export TF_VAR_MYSQL_DB_PASSWORD="비밀번호"
$ terraform init
# outputs.tf
# db 인스턴스 생성 후 참조할 output
output "rds_hostname" {
description = "RDS instance hostname"
value = aws_db_instance.terraform-aws-db.address
sensitive = true
}
output "rds_port" {
description = "RDS instance port"
value = aws_db_instance.terraform-aws-db.port
sensitive = true
}
output "rds_username" {
description = "RDS instance admin username"
value = aws_db_instance.terraform-aws-db.username
sensitive = true
}
# main.tf
###################################################################################
# DB 인스턴스 생성
# 1. DB 파라메터 그룹 생성
resource "aws_db_parameter_group" "terraform-aws-db-parameter-group" {
name = "terraform-aws-db"
# 생성할 db 엔진 버전과 동일해야 함
family = "mysql8.0"
}
# 2. RDS 인스턴스 생성
resource "aws_db_instance" "terraform-aws-db" {
# db instance name
identifier = "terraform-aws-db"
# db spec
instance_class = "db.t3.micro"
allocated_storage = 20
engine = "mysql"
engine_version = "8.0.32"
# db network setting
db_subnet_group_name = aws_db_subnet_group.terraform-aws-db-subnet-group.name
vpc_security_group_ids = [aws_security_group.private-terraform-aws-db-security-group.id]
# db default setting
username = "admin"
password = var.MYSQL_DB_PASSWORD # terraform cloud setup
db_name = "terraformAwsDb"
parameter_group_name = aws_db_parameter_group.terraform-aws-db-parameter-group.name
skip_final_snapshot = true
}
→ Result : terraform apply 실행 결과
✏️ 애플리케이션 로드 밸런서 및 Auto Scaling Group 적용
Step 1 : Target Group 생성
[AWS 콘솔] 콘솔에서 생성
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
# 타겟 그룹 생성
resource "aws_lb_target_group" "terraform-aws-tg" {
name = "terraform-aws-tg"
target_type = "instance"
port = 80
protocol = "HTTP"
vpc_id = module.terraform-aws-vps.vpc_id
health_check {
matcher = "200-299"
}
}
→ Result : terraform apply 실행 결과
Step 2 : ALB 생성
[AWS 콘솔] 콘솔에서 생성
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
# 1. ALB 생성
resource "aws_lb" "terraform-aws-alb" {
name = "terraform-aws-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.public-terraform-aws-security-group.id]
subnets = [for subnet in module.terraform-aws-vps.public_subnets : subnet]
tags = {
Name = "terraform-aws-alb"
}
}
#2. 로드밸런서에 리스너 생성
resource "aws_lb_listener" "terraform-aws-alb-listener" {
load_balancer_arn = aws_lb.terraform-aws-alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.terraform-aws-tg.arn
}
}
→ Result : terraform apply 실행 결과
Step 3 : Auto Scaling Group을 위한 EC2 시작 템플릿 생성
[AWS 콘솔] 콘솔에서 생성
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
#1. EC2 시작 템플릿 생성
resource "aws_launch_template" "terraform-aws-launch-template" {
name = "terraform-aws-launch-template"
image_id = "ami-0a2a74934366c9715"
instance_type = "t2.micro"
#vpc_security_group_ids = [aws_security_group.public-terraform-aws-security-group.id]
key_name = "terraform-aws-key-pair"
user_data = filebase64("${path.module}/user-data.sh")
network_interfaces {
security_groups = [aws_security_group.public-terraform-aws-security-group.id]
associate_public_ip_address = true
}
monitoring {
enabled = true
}
tag_specifications {
resource_type = "instance"
tags = {
Name = "terraform-aws-ec2-autoscaled"
Group = "terraform-aws-ec2"
}
}
}
# user-data.sh
# EC2 인스턴스 시작시마다 스크립트가 기동하도록 설정
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
# 실제 실행하는 스크립트 내용
#!/bin/bash
sudo apt update -y
sudo apt install -y mysql-server
echo "Hello, World" > index.html
sudo nohup busybox httpd -f -p 80 &
--//--
→ Result : terraform apply 실행 결과
Step 4 : Auto Scaling Group 생성
- Auto Scaling Group은 최소 2개, 최대 10개로 설정
[AWS 콘솔] 콘솔에서 생성
[Terraform] IaC 코드로 작성
# main.tf
###################################################################################
# 시작 템플릿을 바탕으로 auto scaling group 생성
resource "aws_autoscaling_group" "terraform-aws-auto-scaling-group" {
name = "terraform-aws-auto-scaling-group"
max_size = 10
min_size = 2
health_check_grace_period = 300
desired_capacity = 2
vpc_zone_identifier = [for subnet in module.terraform-aws-vps.public_subnets : subnet]
launch_template {
id = aws_launch_template.terraform-aws-launch-template.id
version = "$Latest"
}
target_group_arns = [aws_lb_target_group.terraform-aws-tg.arn]
}
→ Result : terraform apply 실행 결과
#TROUBLE SHOOTING & STUDY LOG
📝 EC2 시작 시 user-data.sh 파일이 실행되지 않는 문제
현상
__init__.py[WARNING]: Unhandled non-multipart (text/x-not-multipart) userdata: 'b'\\ufeff#!/bin/bash'...'
원인
- terraform은 us-ascii 인코딩을 사용하는데 vscode에서 sh파일 생성 시 utf-8로 인코딩되기 때문에 발생하는 문제
- cloud-init.log 확인 시 python에서 인코딩 시 \\ufeff 문자가 디코딩된 로그 확인 가능
해결 방안
- user-data.sh 파일을 us-ascii 인코딩해서 전달
- ec2 인스턴스에 ssh 접속 시 /var/log/cloud-init.log에서 오류 확인이 가능하고, /var/lib/cloud/<instances명>에 실행된 사용자 데이터 확인 가능
2023-05-16 10:22:38,126 - handlers.py[DEBUG]: finish: init-network/consume-user-data: SUCCESS: reading and applying user-data
📝 terraform destroy 시 network Interface가 삭제되지 않는 현상
원인
- terraform 파일 작성 시 load balancer 리소스 블럭에 enable_deletion_protection = true 설정을 하면 삭제 방지가 되어 삭제되지 않는 현상
해결 방안
- 해당 설정을 해제
📝 terraform block 중 resource와 module 차이
resource
- 리소스는 aws_vpc, aws_db_instance등
- 리소스는 공급자에 속하고, 인수를 받아들이고, 속성을 출력하고, 수명 주기를 가짐
- 리소스를 생성, 검색, 업데이트 및 삭제 가능
module
- 리소스 모듈은 공통 작업을 함께 수행하는 연결된 리소스 모음 (ex. VPC, 서브넷, NAT 게이트웨이 등 생성)
- 공급자 구성에 따라 달라지며, 공급자 구성 또는 상위 수준 구조(예: 인프라 모듈)에서 정의 가능
#References
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html
https://cloud-images.ubuntu.com/locator/ec2/
https://ubuntu.com/server/docs/databases-mysql
https://developer-ping9.tistory.com/402
https://yunamom.tistory.com/295
https://developer-ping9.tistory.com/402
https://registry.terraform.io/providers/hashicorp/aws/latest/docs
https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest
https://registry.terraform.io/providers/hashicorp/aws/latest
https://registry.terraform.io/modules/terraform-aws-modules/security-group/aws/latest/submodules/web
https://github.com/terraform-aws-modules/terraform-aws-security-group/blob/master/
https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latestrules.tf
https://github.com/hashicorp/learn-terraform-rds
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
https://www.middlewareinventory.com/blog/terraform-aws-ec2-user_data-example/
https://developer.hashicorp.com/terraform/language/values/variables#environment-variables
https://discuss.hashicorp.com/t/passing-user-data-to-ec2-instance/12251
https://developer.hashicorp.com/terraform/language/expressions/for
https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-creating
https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/amazon-vpc-limits.html#vpc-limits-eips
https://terraform101.inflearn.devopsart.dev/cont/vpc-practice/vpc-practice-with-nat/
https://github.com/terraform-aws-modules/terraform-aws-vpc/pull/816
https://developer.hashicorp.com/terraform/language/expressions/references
https://developer.hashicorp.com/terraform/language/expressions/references
https://tf-eks-workshop.workshop.aws/600_extra_content/610-second-node-group/tf-files.html
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/user-data.html
https://developer.hashicorp.com/terraform/language/functions/filebase64
https://repost.aws/ko/knowledge-center/execute-user-data-ec2
https://developer.hashicorp.com/terraform/language/functions/flatten
https://medium.com/@mitesh_shamra/module-in-terraform-920257136228
https://www.terraform-best-practices.com/key-concepts
'devops bootcamp 4 > pair/team log' 카테고리의 다른 글
Sprint - Auto Scaling + CloudWatch를 이용한 알림 (0) | 2023.06.02 |
---|---|
Sprint - 새 버전이 망가졌어요 (0) | 2023.05.19 |
Sprint - 서버리스 애플리케이션 (0) | 2023.05.11 |
Sprint - API Gateway와 서버리스 애플리케이션 (1) | 2023.05.11 |
Sprint - 도메인 주도 설계 실습 (0) | 2023.05.04 |