
Dailyge Infra ์ ์ฅ์ ์
๋๋ค.
์๋น์ค ์๊ฐ๋ ํด๋น ๋งํฌ๋ฅผ ์ฐธ์กฐํด์ฃผ์ธ์. ๐
- Skills
- CI/CD
- Architecture
- Contents
- Modules
์๋น์ค ๊ตฌ์ถ์ ์ํด AWS๋ฅผ ํ์ฉํ์ผ๋ฉฐ, Terraform์ ์ฌ์ฉํด ์์์ ํ๋ก๋น์ ๋ ํ์ต๋๋ค. Terraform์ผ๋ก ๊ด๋ฆฌ๋๋ ์์์ Route53, CloudFront, S3, ALB, ECS, EC2(Application), RD ์ด๋ฉฐ, ์ผ๋ถ ์์๋ค์ ์ค์นํ์ผ๋ก ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ชจ๋ํฐ๋ง์ Prometheus์ Grafana๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, ์ด์ ๋ฐ ์์คํ ๋ก๊ทธ๋ ๋ชจ๋ AWS CloudWatch๋ก ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค.
์ด์ ๊ณผ์ ์์ ๋ฐ์ํ๋ ์ด์๋ Grafana Alert ๋๋ AWS Lambda๋ฅผ ํตํด ์ฌ๋์ผ๋ก ๋ณด๊ณ ๋ฐ๊ณ ์์ผ๋ฉฐ, Lambda์ ๊ฐ์ ์ผ๋ถ ์๋น์ค๋ Python์ ์ฌ์ฉ ์ค์ ๋๋ค.
PR์ด ์์ฑ๋๋ฉด ์๋์ผ๋ก ์ ์ ๋ถ์์ ์์ํ๋ฉฐ, Slack์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ๋ฐ์ต๋๋ค. ํ์ ๊ฐ ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ๊ฑฐ์น ํ, dev ๋ธ๋์น๋ก ๋ณํฉ์ด ๋๋ฉด ๊ฐ๋ฐ ์๋ฒ๋ก ๋ฐฐํฌ๊ฐ ๋๋ฉฐ, ์ธ์ ํ ์คํธ๊ฐ ์์๋ฉ๋๋ค. ์๋ ์ธ์ ํ ์คํธ ์ธ์๋ QA๋ฅผ ์งํํ๋ฉฐ ๊ธฐ๋ฅ์ ๋์ ์ ๋ฌด, ๋ฒ๊ทธ ๋ฆฌํฌํ ์ ํฉ๋๋ค. main ๋ธ๋์น๋ก ๋ณํฉ์ด ๋๋ฉด ์์ฉ ์๋ฒ๋ก ๋ฐฐํฌ๊ฐ ๋๋ฉฐ, ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ๋ฐ์ต๋๋ค.
ํ ์คํธ, ๋ฐฐํฌ ๊ฒฐ๊ณผ ๋ฐ ๋น์ฉ์ ์ฌ๋์ ํตํด ํ์ธํ๊ณ ์์ต๋๋ค.
์ ์ ์์์ S3์ CloudFront๋ฅผ, ์๋ฒ ์ค์ผ์คํธ๋ ์ด์ ์ AWS ECS๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ๊ฐ ๋ฆฌ์์ค๋ VPC ๋ด๋ถ ๋ณ๋์ ์๋ธ๋ท(Public/Private)์ ์กด์ฌํ๋ฉฐ, ALB์ NAT๋ฅผ ํตํด ์ธ๋ถ์ ํต์ ํฉ๋๋ค. ๋ถํ ํ ์คํธ๋ฅผ ํ ๋๋ terraform์ ํตํด ์๋ฒ๋ฅผ ๋์ ์ผ๋ก ํ์ฅํ๊ณ ์์ผ๋ฉฐ, ํ์์์๋ ์ต์ ์ธ์คํด์ค๋ง ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
์๋ธ ๋๋ฉ์ธ์ ์ ๊ทน ํ์ฉํ๊ณ ์์ผ๋ฉฐ, ์๋ธ ๋๋ฉ์ธ ๊ฐ ์ฟ ํค๋ฅผ ๊ณต์ ํด ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๊ฐ๋ฐ ์๋ฒ, ๋ชจ๋ํฐ๋ง ์๋ฒ์ ๊ฐ์ ์๋ธ ๋๋ฉ์ธ์ ๋ํ ์ ๊ทผ์ WAF ๋ฐ Security Group์ผ๋ก ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค.
- Resource ๊ด๋ฆฌ
- Config ๊ด๋ฆฌ
- Server
- RateLimiter
- Monitoring
- Log
- DB ๋ฐฑ์
ํ๋ก๋น์ ๋์ ํ, ๋ณ๊ฒฝ๋ ์ผ์ด ์ ์ ์์
๋ค, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ์ด ๋ณ๊ฒฝ๋์ด์ ์ ๋๋ ์์
๋ค์ ignore_changes๋ฅผ ํตํด ํ
๋ผํผ ๋ผ์ดํ์ฌ์ดํด์์ ์ ์ธํ ํ, ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค.
resource "aws_cloudfront_distribution" "s3_distribution_tasks_dev" {
......
lifecycle {
ignore_changes = all
}
}
Git Submodule๊ณผ AWS Secret Manager๋ฅผ ์ฌ์ฉํด ํ๊ฒฝ ๋ณ์๋ฅผ ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค.
์ธ๋ถ์ ๋ ธ์ถ๋๋ ๊ฐ๋ค์ ์ํธํ๋ ์ํ๋ก ๋ ธ์ถ๋ฉ๋๋ค.
env:
dev
profile:
email: ENC(EoatZjyTeks503/9neDp3JfrFlhWwAiRvlYd77599hM=)
nickname: ENC(VA1R4pL0mo0xHTfV68j+3xQrJbffCBTb)
spring:
cloud:
aws:
region:
static: ap-northeast-2
credentials:
access-key: ENC(5vaRGdYWZUJsFEFF5P8A06TkwwNl5eapE)
secret-key: ENC(JdK2itnFEFDKOdRu7A7zcXmLpOZwbSEWRUwq)
liquibase:
enabled: true
change-log: db/rdb/changelog/changelog-master.yaml
datasource:
url: ENC(qmiZS71LFX29baI8nNpBKhLlLmsJop5vaRGdYWZUJsFEFF5P8A06TkwwNl5eapyY6/vlVdD6zCLkE8qlJdK2itnMByBKOdRu7A7zcXmLpOZwbSEWRUwqGbRvspsUPEFO/sS0PAqBF25vddL6GJ11onkUFqJZ0hPJt3Qr6toHqXcTH7yZNHlrTMLb2xrPlWU)
username: ENC(KHdUpehLSIMFEEyDjj8P/+w==)
password: ENC(/KquPoFfhpYAFEFSsumXHPpsdkquc4M)
driver-class-name: com.mysql.cj.jdbc.Driver
......
๋ฆฌ์์ค ๋ฐ ์คํ ์ค์ผ์ผ๋ง์ ์กฐ๊ธ ๋ ์ธ๋ฐํ๊ฒ ์ ์ดํ๊ธฐ ์ํด Fargate ๋์ EC2๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, ๋ฐฐํฌ ๋ฐ ํฌํธ ์ถฉ๋ ๋ฐฉ์ง๋ฅผ ์ํด ECS ๋์ ํฌํธ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
Route53์์ WAF๋ก ์ผ์ ์๊ฐ ๋์ ์ต๋ ์ฌ์ฉ์ ์์ฒญ์ ์ ํํ๊ณ ์์ผ๋ฉฐ, ๋ชจ๋ํฐ๋ง ์๋ฒ, ๊ด๋ฆฌ์ API ๋ฑ ํน์ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ALB์ WAF, Security Group์ผ๋ก ์ ํํ๊ณ ์์ต๋๋ค.
ํ์์๋ ๋ถ๋น 1,000ํ ์ด์์ผ ๋, IP ๊ธฐ๋ฐ์ผ๋ก API ์์ฒญ ์ ํ์ ๊ฑธ๊ณ ์์ผ๋ฉฐ, ๋ถํ ํ ์คํธ๋ฅผ ํ ๋, ์ด๋ฅผ ํด์ ํฉ๋๋ค.
๋ชจ๋ํฐ๋ง์ Prometheus์ Grafana๋ฅผ CloudWatch์ ์ฐ๋ํด ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ์๋ฆผ์ ๋ฐ๊ณ ์์ต๋๋ค. ๋ชจ๋ํฐ๋ง ์ค์ธ ๋ฆฌ์์ค๋ EC2 ์๋ฒ, ์ ํ๋ฆฌ์ผ์ด์ ์งํ, RDS, Redis, MongoDB์ด๋ฉฐ, CPU/๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ฅ , Slow Query ๋ฑ์ ์ฒดํฌํ๊ณ ์์ต๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค์ด๋ ๊ฒฝ์ฐ, ์๋์ผ๋ก ํ ๋คํ๋ฅผ ์์ฑํ ํ, ์ด๋ฅผ ์ ์ ์ ์ฅ์๋ก ์ ๋ก๋ํ๊ณ ์๋ฆผ์ ๋ณด๋ด๊ณ ์์ต๋๋ค.
์คํ ์ค์ผ์ผ๋ง์ CPU ์ฌ์ฉ๋ฅ ์ด 75% ์ด์์ผ ๋, 1๋ถ ์ด์ ์ง์๋๋ฉด ๋์ํฉ๋๋ค. ์ด๋ CloudWatch์ ์ฐ๋ํ๊ณ ์์ผ๋ฉฐ, ์ด ๋ถ๋ถ์ ํ ๋ผํผ์ด ์๋ ์ค์นํ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค.
resource "aws_appautoscaling_policy" "dailyge_api_scale_out_policy" {
name = "dailyge-api-scale-out-policy"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.dailyge_api_ecs_scaling_target.resource_id
scalable_dimension = aws_appautoscaling_target.dailyge_api_ecs_scaling_target.scalable_dimension
service_namespace = aws_appautoscaling_target.dailyge_api_ecs_scaling_target.service_namespace
target_tracking_scaling_policy_configuration {
target_value = 75.0
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
scale_in_cooldown = 60
scale_out_cooldown = 60
}
}
๋น์ผ ๋ก๊ทธ๋ CloudWatch๋ก ๊ด๋ฆฌํ๊ณ ์์ผ๋ฉฐ, ํ๋ฃจ๊ฐ ์ง๋ ๋ก๊ทธ๋ S3๋ก ์ ์ก ํ, ์ ๊ฑฐํ๊ณ ์์ต๋๋ค.
{
"server": "dailyge-api",
"path": "/api/monthly-tasks",
"method": "POST",
"traceId": "40cfde91-c912-4f3a-9b02-d45b3c066edb",
"ip": "127.0.0.1",
"layer": "ENTRANCE",
"visitor": "{ "userId":null, "role":"GUEST" }",
"time": "2024-08-06T07:29:48.745",
"duration": "0ms",
"context": {
"args": null,
"result": null
}
}
๋ก๊ทธ๋ ์์ฒญ ๊ฒฝ๋ก, ๋ฉ์๋, IP ์ฃผ์(Origin), ํ๋ผ๋ฏธํฐ, ์๋ต ์๊ฐ ๋ฑ์ ๋จ๊ธฐ๊ณ ์์ต๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋งค์ผ ์๋ฒฝ 3์๋ง๋ค ์ค๋ ์ท์ ์์ฑํด ๋ฐฑ์ ํ๊ณ ์์ต๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ ํ, AWS UI๋ฅผ ํตํด ์ค์ ์ ๊ด๋ฆฌํ๊ณ ์์ผ๋ฉฐ, Import๋ฅผ ํตํด ์ฑํฌ๋ฅผ ๋ง์ถ๊ณ ์์ต๋๋ค.
modules ๋ด๋ถ์ ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ธฐ์ค์ผ๋ก ํ์ผ์ ๊ตฌ๋ถํ๊ณ ์์ต๋๋ค. ๋ช ์์ ์ผ๋ก dev, prod ํจํค์ง๋ฅผ ๋๋์์ง๋ง, ํ๋ก์ ํธ ๊ท๋ชจ๊ฐ ์๊ธฐ ๋๋ฌธ์ dev ํ๋๋ง ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
$ tree -L 5
.
โโโ dev
โย ย โโโ graph.png
โย ย โโโ main.tf
โย ย โโโ modules
โย ย โย ย โโโ acm
โย ย โย ย โโโ cloudfront
โย ย โย ย โย ย โโโ main.tf
โย ย โย ย โย ย โโโ outputs.tf
โย ย โย ย โย ย โโโ variables.tf
|
โ ......
|
โย ย โโโ provider.tf
โย ย โโโ variables.tf
......
Atlantis๋ ๋ณ๋์ ์๋ฒ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์, ํ๋ก์ ํธ ๊ท๋ชจ๋ฅผ ๊ณ ๋ คํด ์ฌ์ฉํ์ง ์์์ต๋๋ค.

Leave a Reply