103 V1 IaC Input Spec - 100-hours-a-week/KTB4-3rd-CLOUD GitHub Wiki
๊ธฐ์ค ๋ฌธ์
- 103 V1 ์ํคํ ์ณ ์ค๊ณ
- 101 ์๋ฒ ๊ตฌ์ฑ
docs/103-Milestones-Docker-Compose.md
์ด ๋ฌธ์๋ V1 ์ํคํ ์ฒ์ ๊ฒฐ์ ์ Terraform ๋ฑ์ IaC ์ฝ๋์ ๋ฐ๋ก ์ฎ๊ธธ ์ ์๋๋ก ๋ฆฌ์์ค, ๋ณ์, ๊ถํ๊ณผ ๋ฏธ๊ฒฐ์ ๊ฐ์ ๋ถ๋ฆฌํ๋ค. ์์ง ๋ถํ ํ ์คํธ์ ์ด์ ์ ์ฑ ์ผ๋ก ํ์ ๋์ง ์์ ์์น๋ฅผ ํ์ ์ฌ์์ผ๋ก ์ทจ๊ธํ์ง ์๋๋ค.
| ์ํ | ์๋ฏธ |
|---|---|
| ํ์ | ๊ธฐ์ค ๋ฌธ์์ ์ง์ ๋ช ์๋ ๊ฐ |
| ์ด๊ธฐ ๊ถ์ฅ | IaC ๊ตฌํ์ ์์ํ๊ธฐ ์ํ ๊ธฐ๋ณธ๊ฐ. ๋ฐฐํฌ ์ ๊ฒํ ํ์ |
| ๊ฒฐ์ ํ์ | ์ค์ ๊ณ์ , ๋คํธ์ํฌ, ๋๋ฉ์ธ ๋๋ ์ด์ ์ ์ฑ ์ ๋ ฅ ํ์ |
| ๊ตฌ๋ถ | ๊ฐ | ์ํ |
|---|---|---|
| AWS ๋ฆฌ์ |
ap-northeast-2 (์์ธ) |
ํ์ |
| ํ๊ฒฝ |
dev, prod
|
ํ์ |
| ์ปดํจํ | ํ๊ฒฝ๋ณ EC2 1๋, ์ด 2๋ | ํ์ |
| ํ๊ฒฝ ๊ฒฉ๋ฆฌ | Dev์ Prod๋ฅผ ์๋ก ๋ค๋ฅธ EC2๋ก ๋ถ๋ฆฌ | ํ์ |
| ๋ฐฐ์น ๋ฐฉ์ | ๊ฐ EC2์์ Docker Compose ์คํ | ํ์ |
| ์ธ๋ถ ์ง์ ์ | ๊ฐ EC2์ Nginx 80, 443๋ง ๊ณต๊ฐ |
ํ์ |
| ์ ํ๋ฆฌ์ผ์ด์ | Next.js, Spring Boot, ์ ํ์ ์ธ FastAPI | ํ์ |
| ๋ฐ์ดํฐ๋ฒ ์ด์ค | ํ๊ฒฝ๋ณ EC2์ MySQL ์ปจํ ์ด๋ | ํ์ |
| ๋ก๋ ๋ฐธ๋ฐ์ | ์ฌ์ฉํ์ง ์์ | ํ์ |
| NAT Gateway | ์ฌ์ฉํ์ง ์์ | ํ์ |
| ์๋ธ๋ท | ์ธํฐ๋ท ๊ฒ์ดํธ์จ์ด ๊ฒฝ๋ก๊ฐ ์๋ Public Subnet | ํ์ |
| ์ด์ ์ ์ | Prod๋ SSM, Dev๋ SSM ๋ฐ ์ ํ๋ SSH | ํ์ |
| ์ด๋ฏธ์ง ์ ์ฅ์ | Amazon ECR | ํ์ |
| ๋ก๊ทธ | CloudWatch Logs๋ก ์ธ๋ถ ๋ณด์กด | ํ์ |
| ๋ฐฑ์ ยท์ฌ์ฉ์ ํ์ผ | S3์ ์ ์ฅํ๊ณ ์ฉ๋์ ํ๊ฒฝ๋ณ๋ก ๋ถ๋ฆฌ | ํ์ |
| ๋ฐฐํฌ ์ธ์ฆ | GitHub Actions OIDC๋ก AWS Role ์ฌ์ฉ | ํ์ |
| ๊ณ ๊ฐ์ฉ์ฑ | ์ ๊ณตํ์ง ์์. ํ๊ฒฝ๋ณ EC2๊ฐ ๋จ์ผ ์ฅ์ ์ | ํ์ |
์๋ ๊ฐ์ V1 Terraform์ ๊ธฐ๋ณธ ์ ๋ ฅ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ค. ์ค์ ๊ฐ ์์ด๋ ์ ํ ์ ์๋ ํ ๊ณต์ธ IP์ ๋๋ฉ์ธ๋ง ํ์ ๋ณ์๋ก ๋จ๊ธด๋ค.
| ํญ๋ชฉ | ๊ฐ |
|---|---|
| Region | ap-northeast-2 |
| VPC ์ | 1 |
| VPC CIDR | 10.20.0.0/16 |
| DNS support / hostname |
true / true
|
| Instance tenancy | default |
| IPv6 CIDR | ์ฌ์ฉํ์ง ์์ |
| Availability Zone ์ | 1 |
| Availability Zone | ap-northeast-2a |
| Public Subnet ์ | 1 |
| Prod Subnet |
10.20.10.0/24, ap-northeast-2a
|
| Dev Subnet |
10.20.20.0/24, ap-northeast-2a
|
map_public_ip_on_launch |
false โ EC2๋ณ EIP ์ฌ์ฉ |
| Internet Gateway |
1๊ฐ |
| NAT Gateway |
0๊ฐ |
| Elastic IP |
2๊ฐ โ Dev 1, Prod 1 |
| Route Table |
2๊ฐ โ Dev 1, Prod 1 |
| ๊ฐ Route Table local route | 10.20.0.0/16 -> local |
| ๊ฐ Route Table public route | 0.0.0.0/0 -> Internet Gateway |
| Custom Network ACL |
0๊ฐ โ VPC default NACL ์ฌ์ฉ |
๋จ์ผ AZ์ด๋ฏ๋ก AZ ์ฅ์ ์ Dev์ Prod๊ฐ ๋์์ ์ํฅ์ ๋ฐ๋๋ค. ์ด ๊ตฌ์ฑ์ ํ๊ฒฝ๋ณ ๋ฐฐํฌ์ ๋ฆฌ์์ค ๊ฒฝํฉ์ ๋ถ๋ฆฌํ์ง๋ง ๊ฐ์ฉ ์์ญ ์ฅ์ ๋ฅผ ๊ฒฉ๋ฆฌํ์ง๋ ์๋๋ค.
| ํญ๋ชฉ | Dev | Prod |
|---|---|---|
| ์ธ์คํด์ค ์ | 1 |
1 |
| Instance type | t3.medium |
t3.medium |
| vCPU / Memory | 2 vCPU / 4 GiB |
2 vCPU / 4 GiB |
| Architecture | x86_64 |
x86_64 |
| AMI | Ubuntu 24.04 LTS (Noble) ์ต์ x86_64 SSM parameter | ๋์ผ |
| AMI parameter | /aws/service/canonical/ubuntu/server/noble/stable/current/amd64/hvm/ebs-gp3/ami-id |
๋์ผ |
| OS ์ ์ ์ฌ์ฉ์ | ubuntu |
ubuntu |
| Root EBS |
gp3, 30 GiB, 3,000 IOPS, 125 MiB/s
|
๋์ผ |
| Data EBS |
gp3, 30 GiB, 3,000 IOPS, 125 MiB/s
|
gp3, 30 GiB, 3,000 IOPS, 125 MiB/s
|
| EBS encryption | true |
true |
| Root delete on termination | true |
true |
| Data delete on termination | false |
false |
| Data mount | /mnt/docker-data |
/mnt/docker-data |
| Elastic IP | 1 |
1 |
| Detailed monitoring |
false โ ๊ธฐ๋ณธ 5๋ถ metric |
false โ ๊ธฐ๋ณธ 5๋ถ metric |
| IMDS endpoint | enabled, token required, hop limit 2
|
๋์ผ |
| EC2 key pair | ๊ธฐ์กด Dev ์ด์์ key ์ด๋ฆ | null |
| ์ด์ ์ ์ | ์ ํ๋ SSH | SSM only |
| ํ๊ฒฝ | Ingress ๊ท์น ์ | Egress ๊ท์น ์ | IPv6 ๊ท์น ์ |
|---|---|---|---|
| Prod | 2 |
1 |
0 |
| Dev | 3 |
1 |
0 |
Prod๋ 80/443์ 0.0.0.0/0์ ๊ณต๊ฐํ๊ณ SSH ๊ท์น์ ์์ฑํ์ง ์๋๋ค. Dev์
80/443์ dev_qa_cidrs, 22๋ admin_cidrs์ ์ค์ ๊ณต์ธ IPv4 /32 ๋ชฉ๋ก๋ง
ํ์ฉํ๋ค. ๋ ๋ชฉ๋ก์๋ 0.0.0.0/0๋ฅผ ํ์ฉํ์ง ์๋๋ค. ์์ชฝ ํ๊ฒฝ์ egress๋
tcp/443 -> 0.0.0.0/0 ํ ๊ฐ๋ค.
| ํญ๋ชฉ | ์์น/๊ฐ |
|---|---|
| EC2 IAM role |
2๊ฐ โ moyeota-ec2-dev, moyeota-ec2-prod
|
| Instance profile |
2๊ฐ |
| GitHub Actions role |
3๊ฐ โ CI, Dev CD, Prod CD |
| GitHub OIDC provider |
1๊ฐ |
| ์ด IAM role |
5๊ฐ |
| Role max session duration |
3,600์ด |
| EC2 managed policy |
AmazonSSMManagedInstanceCore 1๊ฐ์ฉ ์ฐ๊ฒฐ |
| EC2 custom policy | ํ๊ฒฝ๋ณ 1๊ฐ |
| GitHub OIDC audience | sts.amazonaws.com |
EC2 custom policy๋ ECR pull 4๊ฐ action, CloudWatch Logs 3๊ฐ action๊ณผ ์๊ธฐ ํ๊ฒฝ์ S3
backup/deployment prefix ์ ๊ทผ๋ง ํ์ฉํ๋ค. GitHub role trust์ sub์๋ ์ค์ FE, BE,
AI, CLOUD repository์ branch ๋๋ GitHub Environment๋ฅผ ์
๋ ฅํ๋ค.
| ํญ๋ชฉ | ์์น/๊ฐ |
|---|---|
| Repository ์ |
4๊ฐ |
| Repository |
moyeota/nginx, moyeota/fe, moyeota/be, moyeota/ai
|
| Tag mutability | IMMUTABLE |
| Scan on push | true |
| Encryption | AES256 |
| Force delete | false |
dev-* ๋ณด์กด |
repository๋ณ ์ต๊ทผ 20๊ฐ |
rc-* ๋ณด์กด |
repository๋ณ ์ต๊ทผ 10๊ฐ |
prod-* ๋ณด์กด |
repository๋ณ ์ต๊ทผ 10๊ฐ |
| Untagged image |
7์ผ ํ ์ญ์ |
๋ฐฐํฌ์๋ tag๊ฐ ์๋ @sha256:<digest>๋ฅผ ์ฌ์ฉํ๋ค. ์ง๋ฌธ์์ ์ค๋ณต๋ ECR ํญ๋ชฉ์
repository ์ค์ ๊ณผ EC2์ ECR pull ๊ถํ์ผ๋ก ๋๋์ด ๋ฐ์ํ๋ค.
| ํญ๋ชฉ | ์์น/๊ฐ |
|---|---|
| SSM managed instance |
2๋ |
| SSM VPC endpoint |
0๊ฐ โ Public Subnet์ HTTPS egress ์ฌ์ฉ |
| Session idle timeout |
20๋ถ |
| Maximum session duration |
60๋ถ |
| Run Command document | AWS-RunShellScript |
| Command execution timeout |
900์ด |
| Max concurrency | 1 |
| Max errors | 0 |
| Prod SSH ingress |
0๊ฐ |
Secret์ Parameter Store์ ๋ ๊ฒฝ์ฐ ๊ฒฝ๋ก๋ง IaC์์ ๋ง๋ค๊ณ ์ค์ SecureString ๊ฐ์
Terraform ๋ฐ์์ ์ฃผ์
ํ๋ค. V1 ํ์ secret์ ํ๊ฒฝ๋ณ MySQL ์ฌ์ฉ์ ๋น๋ฐ๋ฒํธ, MySQL
root ๋น๋ฐ๋ฒํธ, JWT secret์ 3๊ฐ์ด๋ฉฐ Dev/Prod ํฉ๊ณ 6๊ฐ๋ค. AI ํ์ฑํ ์ ํ๊ฒฝ๋ณ
์ธ๋ถ API key๋ฅผ ์ถ๊ฐํ๋ค.
| ํญ๋ชฉ | Dev | Prod |
|---|---|---|
| App log group |
5๊ฐ |
5๊ฐ |
| SSM session log group |
1๊ฐ |
1๊ฐ |
| ์ด log group |
6๊ฐ |
6๊ฐ |
| Log retention |
14์ผ |
30์ผ |
| CloudWatch Agent metric interval |
60์ด |
60์ด |
| EC2 alarm |
4๊ฐ |
4๊ฐ |
ํ๊ฒฝ๋ณ alarm ์ด๊ธฐ๊ฐ์ ๋ค์๊ณผ ๊ฐ๋ค.
| Alarm | Threshold | Period / Evaluation |
|---|---|---|
| CPU high | CPUUtilization >= 80% |
300์ด x 3ํ |
| Instance status failed | StatusCheckFailed >= 1 |
60์ด x 2ํ |
| Memory high | mem_used_percent >= 85% |
300์ด x 3ํ |
| Data disk high | disk_used_percent >= 80% |
300์ด x 3ํ |
์๋ ์์ ์ฉ SNS topic์ ๊ณต์ฉ 1๊ฐ๋ฅผ ๋ง๋ค๊ณ ์ค์ ๊ตฌ๋
์ด๋ฉ์ผ ๋๋ ChatOps endpoint๋
๋ณ๋ ์
๋ ฅ๊ฐ์ผ๋ก ๋ฐ๋๋ค.
| ํญ๋ชฉ | ์์น/๊ฐ |
|---|---|
| Hosted Zone | ๊ธฐ์กด public hosted zone 1๊ฐ ์ฌ์ฉ |
| A record |
2๊ฐ |
| Prod record | app.<domain> -> Prod EIP |
| Dev record | dev.<domain> -> Dev EIP |
| TTL |
300์ด |
| Alias record |
false โ EIP ๊ฐ์ ์ฌ์ฉํ๋ ์ผ๋ฐ A record |
| AAAA record |
0๊ฐ |
| Route 53 health check |
0๊ฐ |
| Failover/weighted policy | ์ฌ์ฉํ์ง ์์ |
์ค์ <domain>, hosted zone ID, dev_qa_cidrs, admin_cidrs, Dev key pair ์ด๋ฆ๊ณผ
์๋ ๊ตฌ๋
๋์์ apply ์ ํ์ ์
๋ ฅ๊ฐ์ด๋ค.
| ์์ญ | Terraform ๋ฆฌ์์ค ์์ | ์๋/๋ฒ์ | ์ฃผ์ ์ ๋ ฅ |
|---|---|---|---|
| Provider |
aws provider |
1 |
ap-northeast-2, ๊ณตํต ํ๊ทธ |
| Network | aws_vpc |
1 | VPC CIDR |
| Network | aws_internet_gateway |
1 | VPC ์ฐ๊ฒฐ |
| Network | aws_subnet |
2 | Dev/Prod Public CIDR, AZ |
| Network |
aws_route_table, association |
ํ๊ฒฝ๋ณ 1 | 0.0.0.0/0 -> IGW |
| Address | aws_eip |
2 | Dev/Prod EC2 ๊ณ ์ ๊ณต์ธ IP |
| Security | aws_security_group |
2 | ํ๊ฒฝ๋ณ ingress/egress |
| Compute |
aws_instance ๋๋ EC2 module |
2 | AMI, type, profile, user data |
| Storage | root EBS | EC2๋ณ 1 | encrypted gp3
|
| Storage | ๋ณ๋ data EBS | EC2๋ณ 1 ๊ถ์ฅ | Docker/MySQL ์์ ๋ฐ์ดํฐ |
| IAM | EC2 role, instance profile | ํ๊ฒฝ๋ณ 1 | SSM, ECR pull, S3, Logs |
| Registry | aws_ecr_repository |
4 |
nginx, fe, be, ai
|
| Object storage | aws_s3_bucket |
3 ๊ถ์ฅ | backup, upload, deployment |
| Logging | aws_cloudwatch_log_group |
ํ๊ฒฝยท์๋น์ค๋ณ | retention, encryption |
| DNS | aws_route53_record |
2 | Prod/Dev ๋๋ฉ์ธ -> EIP |
| CI/CD IAM | GitHub OIDC provider์ roles | provider 1, role 3 ๊ถ์ฅ | CI, Dev CD, Prod CD |
| Secret path | SSM Parameter Store ๋๋ Secrets Manager | ํ๊ฒฝ๋ณ | ์ด๋ฆ๋ง IaC ๊ด๋ฆฌ, ๊ฐ์ ๋ณ๋ ์ฃผ์ |
| State | ์๊ฒฉ state S3์ ์ ๊ธ | bootstrap 1์ | workload์ ๋ถ๋ฆฌ |
IPv6, ALB, NAT Gateway, RDS, Auto Scaling Group์ V1 ๋ฒ์์ ํฌํจํ์ง ์๋๋ค.
๋ค์ ๊ฐ์ IaC ๊ณจ๊ฒฉ์ ๋ง๋ค๊ธฐ ์ํ ์ด๊ธฐ ๊ถ์ฅ๊ฐ์ด๋ค. ํนํ ์ธ์คํด์ค์ ๋ณผ๋ฅจ ํฌ๊ธฐ๋ ๋ถํ ํ ์คํธ ๋ฐ ์ค์ ๋ฐ์ดํฐ ์ฆ๊ฐ๋์ผ๋ก ์กฐ์ ํ๋ค.
| ๋ณ์ | Dev | Prod | ์ํ/๊ทผ๊ฑฐ |
|---|---|---|---|
environment |
dev |
prod |
ํ์ |
aws_region |
ap-northeast-2 |
ap-northeast-2 |
ํ์ |
vpc_cidr |
10.20.0.0/16 ๊ณต์ฉ |
10.20.0.0/16 ๊ณต์ฉ |
์ด๊ธฐ ๊ถ์ฅ, ์ฌ๋ด/VPN CIDR ์ถฉ๋ ํ์ธ |
subnet_cidr |
10.20.20.0/24 |
10.20.10.0/24 |
์ด๊ธฐ ๊ถ์ฅ |
availability_zone |
ap-northeast-2a |
ap-northeast-2a |
๋จ์ผ AZ ๊ธฐ์ค, ๊ณ์ ์์ ์ฌ์ฉ ๊ฐ๋ฅ ์ฌ๋ถ ํ์ธ |
public_ip |
EIP 1๊ฐ | EIP 1๊ฐ | ์ด๊ธฐ ๊ถ์ฅ, DNS์ stop/start ์์ ์ฑ |
ami_architecture |
x86_64 |
x86_64 |
ํ์ฌ ์ด๋ฏธ์ง build ๋์ linux/amd64์ ์ผ์น |
ami |
์ต์ Ubuntu 24.04 LTS SSM parameter ์กฐํ | ๋์ผ | ์ด๊ธฐ ๊ถ์ฅ, AMI ID ํ๋์ฝ๋ฉ ๊ธ์ง |
instance_type |
t3.medium |
t3.large |
์ด๊ธฐ ๊ถ์ฅ, AI ๋นํ์ฑ ๊ธฐ์ค |
root_volume_type |
gp3 |
gp3 |
์ด๊ธฐ ๊ถ์ฅ |
root_volume_size_gib |
30 |
30 |
์ด๊ธฐ ๊ถ์ฅ |
data_volume_type |
gp3 |
gp3 |
์ด๊ธฐ ๊ถ์ฅ |
data_volume_size_gib |
30 |
50 |
์ด๊ธฐ ๊ถ์ฅ, DBยท์ด๋ฏธ์ง ์ฆ๊ฐ๋์ผ๋ก ์กฐ์ |
ebs_encrypted |
true |
true |
์ด๊ธฐ ๊ถ์ฅ |
delete_data_volume_on_termination |
false |
false |
์ด๊ธฐ ๊ถ์ฅ |
ai_enabled |
false |
false |
V1 ๊ธฐ๋ณธ๊ฐ |
log_retention_days |
14 |
30 |
์ด๊ธฐ ๊ถ์ฅ |
backup_retention_days |
7 |
30 |
์ด๊ธฐ ๊ถ์ฅ, RPO/RTO ๊ฒฐ์ ํ ํ์ |
stop_when_unused |
true |
false |
Dev ๋น์ฉ ์ ๊ฐ ๋ฐฉ์นจ |
์ปจํ
์ด๋ ์ ํ์ ํฉ๊ณ๋ AI๋ฅผ ์ ์ธํด๋ CPU 2.0, ๋ฉ๋ชจ๋ฆฌ ์ฝ 2.125 GiB๋ค. OS,
Docker daemon, ๋ก๊ทธ ์์ง๊ธฐ, ํ์ผ ์บ์์ ๋ฐฐํฌ ์์
์ ์ฌ์ ๊ฐ ํ์ํ๋ฏ๋ก Dev๋
t3.medium์ ์์์ ์ผ๋ก, Prod๋ t3.large๋ฅผ ์์์ ์ผ๋ก ๋๋ค. ์ด๋ ์ฑ๋ฅ ๋ณด์ฅ๊ฐ์ด
์๋๋ฉฐ HTTP p95/p99, WebSocket ๋์ ์ฐ๊ฒฐ, JVM GC, MySQL buffer์ OOM ๋ฐ์ ์ฌ๋ถ๋ก
๊ฒ์ฆํด์ผ ํ๋ค. FastAPI๋ฅผ ํ์ฑํํ๋ฉด ๋ณ๋ ์ธก์ ํ ์ธ์คํด์ค ํ์
์ ๋ค์ ์ ํํ๋ค.
IaC๊ฐ ์ง์ ์ปจํ ์ด๋๋ฅผ ์์ฑํ์ง๋ ์์ง๋ง, ์ธ์คํด์ค ํฌ๊ธฐ์ Security Group ๊ฒ์ฆ์๋ ๋ค์ ์คํ ๊ณ์ฝ์ ์ฌ์ฉํ๋ค.
| ์๋น์ค | ๋ด๋ถ ํฌํธ | ์ธ๋ถ ๊ณต๊ฐ | CPU | Memory | Swap | ์์ ๋ฐ์ดํฐ |
|---|---|---|---|---|---|---|
| Nginx | 80/443 | Host 80/443 | 0.25 | 128 MB | ์์ | ์ธ์ฆ์ read-only mount |
| Next.js | 3000 | ์์ | 0.50 | 512 MB | ์์ | ์์ |
| Spring Boot | 8080 | ์์ | 0.75 | 768 MB | 256 MB | ์์ |
| MySQL | 3306 | ์์ | 0.50 | 768 MB | ์์ | named volume -> data EBS |
| FastAPI | 8000 | ์์ | ์ธก์ ํ์ | ์ธก์ ํ์ | ์ธก์ ํ์ | V1 ๊ธฐ๋ณธ ๋นํ์ฑ |
/ -> frontend:3000
/api/* -> backend:8080
/ws/* -> backend:8080 (WebSocket Upgrade)
/ai/* -> ai:8000 (์ ํ ๊ธฐ๋ฅ)
| ๋ฐฉํฅ | Protocol | Port | Source/Destination | ์ค๋ช |
|---|---|---|---|---|
| Ingress | TCP | 80 | 0.0.0.0/0 |
HTTPS redirect ๋๋ ์ธ์ฆ์ ๋ฐ๊ธ |
| Ingress | TCP | 443 | 0.0.0.0/0 |
Nginx HTTPS |
| Egress | TCP | 443 | 0.0.0.0/0 |
ECR, S3, SSM, CloudWatch, ์ธ๋ถ API |
Prod์๋ 22๋ฒ ingress๋ฅผ ๋ง๋ค์ง ์๋๋ค. ์ด์ ์ ์๊ณผ ๋ฐฐํฌ๋ SSM์ ์ฌ์ฉํ๋ค.
| ๋ฐฉํฅ | Protocol | Port | Source/Destination | ์ค๋ช |
|---|---|---|---|---|
| Ingress | TCP | 80 | dev_qa_cidrs |
ํตํฉ ํ ์คํธ, HTTPS redirect |
| Ingress | TCP | 443 | dev_qa_cidrs |
ํตํฉ ํ ์คํธ HTTPS |
| Ingress | TCP | 22 | admin_cidrs |
์์ ์ด์ SSH |
| Egress | TCP | 443 | 0.0.0.0/0 |
ECR, S3, SSM, CloudWatch, ์ธ๋ถ API |
dev_qa_cidrs์ admin_cidrs๋ /32 ๋๋ ์กฐ์ง์ ๊ณ ์ CIDR๋ง ํ์ฉํ๋ค. ๋ ๋ณ์์
0.0.0.0/0๊ฐ ๋ค์ด์ค๋ฉด plan ๋จ๊ณ์ validation์ผ๋ก ์คํจ์ํจ๋ค.
AWS Security Group์ ๋ชฉ์ ์ง๋ ๋๋ฉ์ธ ์ด๋ฆ์ด ์๋๋ผ CIDR, Security Group ๋๋
Prefix List๋ก ํํํ๋ค. ๋ฐ๋ผ์ ๋ฌธ์์ "์ธ๋ถ ์ ์ฒด ๋๋ ํ์ฉ ๋๋ฉ์ธ" ์ค V1 IaC๋ก
์ง์ ๊ตฌํ ๊ฐ๋ฅํ ๊ฐ์ tcp/443 -> 0.0.0.0/0์ด๋ค. ๋๋ฉ์ธ ๋จ์ egress ํต์ ๊ฐ
ํ์๋ผ๋ฉด HTTP proxy, DNS Firewall, Network Firewall ๋ฑ์ ๋ณ๋ ์ค๊ณ๊ฐ ํ์ํ๋ฉฐ V1
์ต์ ๊ตฌ์ฑ์๋ ํฌํจํ์ง ์๋๋ค.
Project = moyeota
Environment = dev | prod
ManagedBy = terraform
Service = compose-host
Owner = cloud
- Docker Engine๊ณผ Docker Compose v2 ์ค์น
- SSM Agent์ CloudWatch Agent ์ค์นยทํ์ฑํ
- data EBS format/mount ๋ฐ ์ฌ๋ถํ ํ ์๋ mount
- Docker
data-root๋ฅผ data EBS๋ก ์ง์ -
/opt/moyeota/{deploy,certs,backup}์์ฑ๊ณผ ๊ถํ ์ค์ -
/opt/moyeota/deploy/runtime.env์release.env๋ฅผ0600์ผ๋ก ๊ด๋ฆฌ - CloudWatch ๋ก๊ทธ ์ ์ก ์ค์
- ๋ฐฐํฌ ์คํฌ๋ฆฝํธ๊ฐ ์ฌ์ฉํ AWS region๊ณผ ํ๊ฒฝ๋ช ์ค์
MySQL named volume์ root EBS๊ฐ ์๋๋ผ ๋ณ๋ data EBS์ ๋ณด์กดํ๋ ค๋ฉด Docker์
data-root๋ฅผ data EBS mount ์๋๋ก ์ด๋ํ๋ค. ์ด ์ค์ ์์ด EC2๋ฅผ ๊ต์ฒดํ๋ฉด named
volume๋ ํจ๊ป ์์ ์ ์๋ค. Prod data volume์ Terraform์ ์ค์๋ก ์ญ์ ๋์ง ์๋๋ก
๋ณ๋์ ๋ณดํธ ์ ์ฑ
๊ณผ ์ญ์ ์ ์๋ ์น์ธ ์ ์ฐจ๋ฅผ ๋๋ค.
์ค์ ๋น๋ฐ๋ฒํธ, JWT Secret, ์ธ๋ถ API key, ์ธ์ฆ์ private key๋ฅผ user data, Terraform
variable, tfvars, output์ ๋ฃ์ง ์๋๋ค. IaC๋ secret์ ๊ฒฝ๋ก์ ์ ๊ทผ ๊ถํ๋ง ๋ง๋ค๊ณ ,
์ค์ ๊ฐ์ ๋ฐฐํฌ ๊ณผ์ ์์ ๋ณ๋๋ก ์ฃผ์
ํ๋ค.
Dev์ Prod role์ ๋ถ๋ฆฌํ๊ณ ๊ฐ ํ๊ฒฝ์ S3 prefix์ CloudWatch log group๋ง ์ ๊ทผํ๊ฒ ํ๋ค.
| ๋ชฉ์ | ์ต์ action ๋ฒ์ |
|---|---|
| SSM ์ ์ | AWS managed policy AmazonSSMManagedInstanceCore
|
| ECR ์ธ์ฆ |
ecr:GetAuthorizationToken (Resource = *) |
| ECR pull |
ecr:BatchCheckLayerAvailability, ecr:GetDownloadUrlForLayer, ecr:BatchGetImage๋ฅผ 4๊ฐ repository ARN์ผ๋ก ์ ํ |
| DB ๋ฐฑ์ ์ ๋ก๋ |
s3:PutObject, ํ์ํ multipart action์ ์๊ธฐ ํ๊ฒฝ์ backup prefix๋ก ์ ํ |
| ๋ฐฐํฌ bundle ์กฐํ |
s3:GetObject๋ฅผ ์๊ธฐ ํ๊ฒฝ์ deployment prefix๋ก ์ ํ |
| ๋ก๊ทธ ์ ์ก |
logs:CreateLogStream, logs:DescribeLogStreams, logs:PutLogEvents๋ฅผ ์๊ธฐ ํ๊ฒฝ log group์ผ๋ก ์ ํ |
s3:*, ecr:*, logs:*์ ๊ฐ์ ๊ด๋ฒ์ ๊ถํ์ ์ฌ์ฉํ์ง ์๋๋ค.
| Role | ์ฌ์ฉ ์ฃผ์ฒด | ๊ถํ |
|---|---|---|
moyeota-ci-ecr-push |
FE/BE/AI/CLOUD ์ด๋ฏธ์ง workflow | ECR ์ธ์ฆ๊ณผ ๋์ repository push |
moyeota-cd-dev |
CLOUD Dev environment | Dev deployment prefix upload, Dev EC2์ SSM command ์คํยท๊ฒฐ๊ณผ ์กฐํ |
moyeota-cd-prod |
CLOUD Prod environment | Prod deployment prefix upload, Prod EC2์ SSM command ์คํยท๊ฒฐ๊ณผ ์กฐํ |
OIDC provider๋ https://token.actions.githubusercontent.com, audience๋
sts.amazonaws.com์ ์ฌ์ฉํ๋ค. Trust policy์ sub ์กฐ๊ฑด์ ์กฐ์ง ์ ์ฒด wildcard๋ก
๋์ง ์๊ณ ์ค์ repository์ branch ๋๋ GitHub Environment๋ก ์ ํํ๋ค. Prod role์
GitHub์ Prod Environment ์น์ธ ์ดํ์๋ง assumeํ ์ ์๊ฒ ๋ถ๋ฆฌํ๋ค.
| ์ด๋ฆ | ์ค์ |
|---|---|
moyeota/nginx |
tag immutable, scan on push, AES256 |
moyeota/fe |
tag immutable, scan on push, AES256 |
moyeota/be |
tag immutable, scan on push, AES256 |
moyeota/ai |
tag immutable, scan on push, AES256 |
์ด๋ฏธ์ง๋ dev-<sha7>, rc-v<version>-<sha7>, prod-v<version>-<sha7> tag๋ก pushํ๋
๋ฐฐํฌ manifest์๋ tag๊ฐ ์๋ @sha256:<digest>๋ฅผ ์ ์ฅํ๋ค. MySQL๋ floating tag๊ฐ
์๋ digest๋ฅผ ์ฌ์ฉํ๋ค.
๋ฒํท ์ด๋ฆ์ ์ ์ญ ์ ์ผ์ฑ์ด ํ์ํ๋ฏ๋ก AWS account ID ๋๋ ๋ณ๋ suffix๋ฅผ ํฌํจํ๋ค.
| ๋ ผ๋ฆฌ ์ด๋ฆ | ์ด๋ฆ ์์ | Prefix | ์ด๊ธฐ lifecycle |
|---|---|---|---|
| Deployment | moyeota-<account-id>-deployments |
dev/, prod/
|
7์ผ ํ ์ญ์ |
| DB backup | moyeota-<account-id>-backups |
dev/mysql/, prod/mysql/
|
Dev 7์ผ, Prod 30์ผ |
| User upload | moyeota-<account-id>-uploads |
dev/, prod/
|
์๋ ์ญ์ ์์ |
์ธ ๋ฒํท ๋ชจ๋ Public Access Block, server-side encryption, versioning์ ํ์ฑํํ๋ค. ์ฌ์ฉ์ ํ์ผ ๋ฒํท์ public ACL์ ์ฌ์ฉํ์ง ์๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ช URL ๋๋ ์ดํ ๋์ ํ CloudFront๋ฅผ ํตํด ์ ๊ณตํ๋ค. DB backup๊ณผ ์ฌ์ฉ์ ํ์ผ์ IAM policy์์๋ prefix๋ฅผ ๋ถ๋ฆฌํ๋ค.
/moyeota/dev/nginx
/moyeota/dev/frontend
/moyeota/dev/backend
/moyeota/dev/mysql
/moyeota/dev/ai
/moyeota/prod/nginx
/moyeota/prod/frontend
/moyeota/prod/backend
/moyeota/prod/mysql
/moyeota/prod/ai
IaC๋ log group๊ณผ retention์ ๋จผ์ ์์ฑํ๋ค. Compose๋ ์๋น์ค๋ณ awslogs driver๋ฅผ
์ฌ์ฉํ๊ฑฐ๋ CloudWatch Agent๊ฐ Docker log๋ฅผ ์๋น์ค๋ณ๋ก ๊ตฌ๋ถํด ์ ์กํ๋๋ก ํ์ ์ค์ ์ด
ํ์ํ๋ค. ํ์ฌ์ ๋ก์ปฌ json-file rotation๋ง์ผ๋ก๋ EC2 ์ฅ์ ํ ๋ก๊ทธ๋ฅผ ๋ณด์กดํ ์ ์๋ค.
| ๋ณ์ | ์์ | ์ํ |
|---|---|---|
hosted_zone_name |
example.com |
๊ฒฐ์ ํ์ |
prod_fqdn |
app.example.com |
๊ฒฐ์ ํ์ |
dev_fqdn |
dev.example.com |
๊ฒฐ์ ํ์ |
| Prod record | A -> Prod EIP |
์ด๊ธฐ ๊ถ์ฅ |
| Dev record | A -> Dev EIP |
์ด๊ธฐ ๊ถ์ฅ |
ALB ์์ด EC2 Nginx์์ TLS๋ฅผ ์ข ๋ฃํ๋ฏ๋ก Route 53 record๋ง ๋ง๋๋ ๊ฒ์ผ๋ก ์ธ์ฆ์๊ฐ ์ค์น๋์ง๋ ์๋๋ค. Certbot/ACME ์ฌ์ฉ, ์ธ๋ถ์์ ๋ฐ๊ธํ ์ธ์ฆ์ ๋ฐฐํฌ, ๋๋ ํฅํ ALB์ ACM ์ฌ์ฉ ์ค ํ๋๋ฅผ ๋ณ๋ ๊ฒฐ์ ํด์ผ ํ๋ค. ์ธ์ฆ์ private key๋ Terraform state์ ๋ฃ์ง ์๋๋ค.
์๋ ๊ฐ์ ์ค์ Secret์ ํฌํจํ์ง ์๋ root module ์ ๋ ฅ์ ์์๋ค.
project_name = "moyeota"
aws_region = "ap-northeast-2"
network = {
vpc_cidr = "10.20.0.0/16"
prod = {
subnet_cidr = "10.20.10.0/24"
availability_zone = "ap-northeast-2a"
}
dev = {
subnet_cidr = "10.20.20.0/24"
availability_zone = "ap-northeast-2a"
}
}
environments = {
dev = {
instance_type = "t3.medium"
root_volume_size_gib = 30
data_volume_size_gib = 30
log_retention_days = 14
backup_retention_days = 7
public_ingress_cidrs = ["<DEV_QA_PUBLIC_IP>/32"]
ssh_ingress_cidrs = ["<ADMIN_PUBLIC_IP>/32"]
ssh_enabled = true
}
prod = {
instance_type = "t3.large"
root_volume_size_gib = 30
data_volume_size_gib = 50
log_retention_days = 30
backup_retention_days = 30
public_ingress_cidrs = ["0.0.0.0/0"]
ssh_ingress_cidrs = []
ssh_enabled = false
}
}
ecr_repositories = ["moyeota/nginx", "moyeota/fe", "moyeota/be", "moyeota/ai"]<DEV_QA_PUBLIC_IP>์ <ADMIN_PUBLIC_IP>๋ placeholder์ด๋ฏ๋ก ๊ทธ๋๋ก applyํ ์ ์๊ฒ
validation์ ์ถ๊ฐํ๋ค.
infra/
โโโ bootstrap/ # remote state bucket์ ์ ๊ธ
โโโ modules/
โ โโโ network/
โ โโโ compute/
โ โโโ iam-ec2/
โ โโโ ecr/
โ โโโ s3/
โ โโโ observability/
โ โโโ github-oidc/
โโโ live/
โโโ shared/ # VPC, ECR, OIDC, ๊ณต์ฉ bucket
โโโ dev/ # Dev EC2, EIP, SG, IAM, logs
โโโ prod/ # Prod EC2, EIP, SG, IAM, logs
Dev์ Prod state๋ฅผ ๋ถ๋ฆฌํด Dev ๋ณ๊ฒฝ์ด Prod ๋ฆฌ์์ค๋ฅผ ํจ๊ป ์์ ํ๊ฑฐ๋ ์ญ์ ํ๋ ์ํ์ ์ค์ธ๋ค. Prod state, S3 backup bucket๊ณผ data EBS์๋ ์ญ์ ๋ฐฉ์ง์ ๋ณ๋ ์น์ธ ์ ์ฐจ๋ฅผ ๋๋ค.
- AWS account ID์ Terraform ์คํ role
- VPC CIDR์ด ํ๊ตยทํ์ฌยทVPN ๋คํธ์ํฌ์ ์ถฉ๋ํ์ง ์๋์ง
- ์ฌ์ฉํ Availability Zone
- Dev/QA public CIDR๊ณผ ์ด์์ SSH CIDR
- Dev SSH public key ๋๋ ๊ธฐ์กด EC2 Key Pair ์ด๋ฆ
- ์ค์ ๋๋ฉ์ธ๊ณผ Route 53 hosted zone ID
- Nginx TLS ์ธ์ฆ์ ๋ฐ๊ธยท๊ฐฑ์ ๋ฐฉ์
- FE, BE, AI, CLOUD์ ์ ํํ GitHub repository ์ด๋ฆ๊ณผ ํ์ฉ branch/environment
- ์ค์ S3 bucket ์ด๋ฆ ๋๋ ์ด๋ฆ suffix
- DB backup ์ฃผ๊ธฐ, RPO, ๋ณด์กด๊ธฐ๊ฐ๊ณผ ์ ๊ธฐ ๋ณต๊ตฌ ํ๋ จ ์ ์ฐจ
- ์ฌ์ฉ์ ํ์ผ์ ๋ณด์กดยท์ญ์ ยทCORS ์ ์ฑ
- CloudWatch ๋ก๊ทธ ๋ณด์กด๊ธฐ๊ฐ๊ณผ ์๋ ์์ ๋์
- Dev/Prod ์ธ์คํด์ค์ data EBS์ ์ต์ข ์ฉ๋
- FastAPI ํ์ฑํ ์ฌ๋ถ์ ํ์ฑํ ์ CPUยท๋ฉ๋ชจ๋ฆฌ ์ธก์ ๊ฐ
- EC2 ๊ต์ฒด ์ MySQL data volume์ ์ฌ์ฐ๊ฒฐํ๊ณ ๋ณต๊ตฌํ๋ runbook
-
terraform fmt,validate์ ์ ์ ๋ณด์ ๊ฒ์ฌ๋ฅผ ํต๊ณผํ๋ค. - plan์ NAT Gateway, ALB, RDS, Prod SSH ingress๊ฐ ์์ด์ผ ํ๋ค.
- Dev์ 80/443/22 source์
0.0.0.0/0๊ฐ ์์ด์ผ ํ๋ค. - Prod์๋ 80/443 ingress๋ง ์๊ณ ์ด์ ์ ์์ SSM์ผ๋ก ๊ฐ๋ฅํด์ผ ํ๋ค.
- EC2์์ ECR pull, S3 backup upload, CloudWatch log ์ ์ก์ด ์ต์ ๊ถํ์ผ๋ก ๋์ํ๋ค.
- ๋ด๋ถ ์๋น์ค ํฌํธ
3000,8080,8000,3306์ ํธ์คํธ๋ Security Group์ ๊ณต๊ฐ๋์ง ์๋๋ค. - EC2๋ฅผ ๊ต์ฒดํด๋ ๋ณ๋ data EBS์ S3 backup์ ์ด์ฉํด MySQL์ ๋ณต๊ตฌํ ์ ์์ด์ผ ํ๋ค.
- Dev์ Prod์ IAM role, S3 prefix, log group, state๊ฐ ์๋ก ๋ถ๋ฆฌ๋์ด์ผ ํ๋ค.
- ๋ฐฐํฌ manifest์ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฏธ์ง๋ ECR digest๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
- ์ธ์คํด์ค ํ์ ์ ์ค์ ๋ถํ ํ ์คํธ ํ ํ์ ํ๊ณ , AI ํ์ฑํ ์ ๋ค์ ๊ฒ์ฆํ๋ค.