Skip to content

Commit

Permalink
chore(.github) terraform aws ec2 테스트 환경 구축
Browse files Browse the repository at this point in the history
- private subnet에 ec2가 연결, bastion public ip와 ssh키를 통해 ec2 접속 가능
- user_data.sh 파일을 통해 docker 설치 및 image pull && docker run 설정
- .jar image 빌드 시 arm64도 추가
- terraform state, tfvars는 commit에서 제외

state, tfvars는 별도로 공유하겠습니다. S3 버킷에 도입은 상황에 따라 도입하겠습니다.
  • Loading branch information
jlee38266 committed Aug 7, 2024
1 parent 8eb0301 commit 146f54e
Show file tree
Hide file tree
Showing 13 changed files with 614 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/jar-image-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
context: ./webtoon-search-back/webtoon-search # Dockerfile이 위치한 디렉토리 경로
file: ./webtoon-search-back/webtoon-search/docker/Dockerfile-spring # 사용할 Dockerfile 경로
push: true # 빌드 후 이미지 푸시 여부
platforms: linux/amd64 # 멀티 아키텍처 빌드 설정 (필요할 시 linux/arm64 추가)
platforms: linux/amd64, linux/arm64 # 멀티 아키텍처 빌드 설정
tags: |
${{ secrets.DOCKER_USERNAME }}/webtoon-search:latest
${{ secrets.DOCKER_USERNAME }}/webtoon-search:${{ github.sha }}
Expand Down
28 changes: 27 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
.idea/
.idea/

# infra
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Terraform variable definition files
*.tfvars

# Crash log files
crash.log

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore CLI configuration files
.terraformrc
terraform.rc

30 changes: 30 additions & 0 deletions infrastructure/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# EditorConfig is awesome: http://EditorConfig.org
# Uses editorconfig to maintain consistent coding styles

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 80
trim_trailing_whitespace = true

[*.{tf,tfvars}]
indent_size = 2
indent_style = space

[*.md]
max_line_length = 0
trim_trailing_whitespace = false

[Makefile]
tab_width = 2
indent_style = tab

[COMMIT_EDITMSG]
max_line_length = 0
7 changes: 7 additions & 0 deletions infrastructure/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 모든 텍스트 파일에 대해 LF를 사용
* text=auto eol=lf

# 특정 파일 유형에 대해 LF를 사용
*.sh text eol=lf
*.tf text eol=lf

25 changes: 25 additions & 0 deletions infrastructure/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions infrastructure/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
resource "aws_iam_role" "app_role" {
name = "${local.name}-app-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})

tags = local.tags
}

resource "aws_iam_instance_profile" "app_profile" {
name = "${local.name}-app-profile"
role = aws_iam_role.app_role.name
}

resource "aws_iam_role_policy_attachment" "cloudwatch_policy" {
policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
role = aws_iam_role.app_role.name
}
12 changes: 12 additions & 0 deletions infrastructure/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
locals {
name = "${var.project_name}-${var.environment}"

tags = merge(
var.tags,
{
Environment = var.environment
Project = var.project_name
ManagedBy = "Terraform"
}
)
}
110 changes: 110 additions & 0 deletions infrastructure/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# VPC 모듈
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"

name = local.name
cidr = var.vpc_cidr

azs = var.azs
private_subnets = [
for k, v in var.azs :
cidrsubnet(var.vpc_cidr, var.private_subnet_prefix_extension, k)
]
public_subnets = [
for k, v in var.azs :
cidrsubnet(var.vpc_cidr, var.public_subnet_prefix_extension, k + 48)
]

enable_nat_gateway = var.enable_nat_gateway
one_nat_gateway_per_az = var.one_nat_gateway_per_az
enable_dns_hostnames = var.enable_dns_hostnames
enable_dns_support = var.enable_dns_support

tags = local.tags
}

# Auto Scaling Group 모듈
module "asg" {
source = "terraform-aws-modules/autoscaling/aws"
version = "~> 6.5"

name = local.name

min_size = var.asg_config.min_size
max_size = var.asg_config.max_size
desired_capacity = var.asg_config.desired_capacity
wait_for_capacity_timeout = 0
health_check_type = "EC2"
vpc_zone_identifier = module.vpc.private_subnets

instance_refresh = {
strategy = "Rolling"
preferences = {
checkpoint_delay = 600
checkpoint_percentages = [35, 70, 100]
instance_warmup = 300
min_healthy_percentage = 50
}
triggers = ["tag"]
}

launch_template_name = "${local.name}-lt"
launch_template_description = "Launch template for ${local.name}"
update_default_version = true

instance_type = var.instance_config[var.environment].instance_type
image_id = var.instance_config[var.environment].ami_id
enable_monitoring = var.enable_detailed_monitoring

block_device_mappings = var.use_ebs ? [
{
device_name = "/dev/sda1"
ebs = {
volume_size = var.ebs_config.volume_size
volume_type = var.ebs_config.volume_type
}
}
] : []

security_groups = [module.app_sg.security_group_id]

user_data = base64encode(templatefile("${path.module}/user_data.sh", {
docker_image = var.docker_image
name = local.name
}))

iam_instance_profile_name = aws_iam_instance_profile.app_profile.name

key_name = var.ssh_key_name

tags = local.tags
}

# Bastion 호스트
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 3.0"

count = var.create_bastion ? 1 : 0

name = "${local.name}-bastion"

ami = var.instance_config[var.environment].ami_id
instance_type = var.instance_config[var.environment].instance_type
key_name = var.ssh_key_name
monitoring = true
vpc_security_group_ids = [module.bastion_sg[0].security_group_id]
subnet_id = module.vpc.public_subnets[0]
associate_public_ip_address = true # 퍼블릭 IP 할당 추가

tags = local.tags
}

# CloudWatch 로그 그룹
resource "aws_cloudwatch_log_group" "app" {
name = "/aws/ec2/${local.name}"
retention_in_days = var.cloudwatch_retention_days

tags = local.tags
}
65 changes: 65 additions & 0 deletions infrastructure/network.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# bastion 모듈
module "bastion_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
count = var.create_bastion ? 1 : 0

name = "${local.name}-bastion-sg"
description = "Security group for bastion host"
vpc_id = module.vpc.vpc_id

ingress_with_cidr_blocks = [
{
from_port = 22
to_port = 22
protocol = "tcp"
description = "SSH access"
cidr_blocks = var.bastion_ingress_cidr
}
]

egress_rules = ["all-all"]

tags = local.tags
}

# Security Group 모듈
module "app_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"

name = "${local.name}-app-sg"
description = "Security group for application servers"
vpc_id = module.vpc.vpc_id

ingress_with_source_security_group_id = [
{
from_port = 22
to_port = 22
protocol = "tcp"
description = "SSH access from Bastion"
source_security_group_id = var.create_bastion ? module.bastion_sg[0].security_group_id : null
}
]

ingress_with_cidr_blocks = [
{
from_port = 80
to_port = 80
protocol = "tcp"
description = "HTTP access from VPC"
cidr_blocks = module.vpc.vpc_cidr_block
},
{
from_port = 443
to_port = 443
protocol = "tcp"
description = "HTTPS access from VPC"
cidr_blocks = module.vpc.vpc_cidr_block
}
]

egress_rules = ["all-all"]

tags = local.tags
}
Loading

0 comments on commit 146f54e

Please sign in to comment.