dailyge-infra



Dailyge Infra ์ €์žฅ์†Œ ์ž…๋‹ˆ๋‹ค.
์„œ๋น„์Šค ์†Œ๊ฐœ๋Š” ํ•ด๋‹น ๋งํฌ๋ฅผ ์ฐธ์กฐํ•ด์ฃผ์„ธ์š”. ๐Ÿ˜ƒ

Release Release
Release


Table of Contents.

  1. Skills
  2. CI/CD
  3. Architecture
  4. Contents
  5. Modules


1. Skills.

์„œ๋น„์Šค ๊ตฌ์ถ•์„ ์œ„ํ•ด AWS๋ฅผ ํ™œ์šฉํ–ˆ์œผ๋ฉฐ, Terraform์„ ์‚ฌ์šฉํ•ด ์ž์›์„ ํ”„๋กœ๋น„์ €๋‹ ํ–ˆ์Šต๋‹ˆ๋‹ค. Terraform์œผ๋กœ ๊ด€๋ฆฌ๋˜๋Š” ์ž์›์€ Route53, CloudFront, S3, ALB, ECS, EC2(Application), RD ์ด๋ฉฐ, ์ผ๋ถ€ ์ž์›๋“ค์€ ์„ค์น˜ํ˜•์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‹ˆํ„ฐ๋ง์€ Prometheus์™€ Grafana๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์šด์˜ ๋ฐ ์‹œ์Šคํ…œ ๋กœ๊ทธ๋Š” ๋ชจ๋‘ AWS CloudWatch๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image

์šด์˜ ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด์Šˆ๋Š” Grafana Alert ๋˜๋Š” AWS Lambda๋ฅผ ํ†ตํ•ด ์Šฌ๋ž™์œผ๋กœ ๋ณด๊ณ ๋ฐ›๊ณ  ์žˆ์œผ๋ฉฐ, Lambda์™€ ๊ฐ™์€ ์ผ๋ถ€ ์„œ๋น„์Šค๋Š” Python์„ ์‚ฌ์šฉ ์ค‘์ž…๋‹ˆ๋‹ค.


2. CI/CD

PR์ด ์ƒ์„ฑ๋˜๋ฉด ์ž๋™์œผ๋กœ ์ •์  ๋ถ„์„์„ ์‹œ์ž‘ํ•˜๋ฉฐ, Slack์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํŒ€์› ๊ฐ„ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ๊ฑฐ์นœ ํ›„, dev ๋ธŒ๋žœ์น˜๋กœ ๋ณ‘ํ•ฉ์ด ๋˜๋ฉด ๊ฐœ๋ฐœ ์„œ๋ฒ„๋กœ ๋ฐฐํฌ๊ฐ€ ๋˜๋ฉฐ, ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ์ž๋™ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์™ธ์—๋„ QA๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๊ธฐ๋Šฅ์˜ ๋™์ž‘ ์œ ๋ฌด, ๋ฒ„๊ทธ ๋ฆฌํฌํŒ…์„ ํ•ฉ๋‹ˆ๋‹ค. main ๋ธŒ๋žœ์น˜๋กœ ๋ณ‘ํ•ฉ์ด ๋˜๋ฉด ์ƒ์šฉ ์„œ๋ฒ„๋กœ ๋ฐฐํฌ๊ฐ€ ๋˜๋ฉฐ, ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ๋ฐ›์Šต๋‹ˆ๋‹ค.

image


ํ…Œ์ŠคํŠธ, ๋ฐฐํฌ ๊ฒฐ๊ณผ ๋ฐ ๋น„์šฉ์€ ์Šฌ๋ž™์„ ํ†ตํ•ด ํ™•์ธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image


3. Architecture

์ •์  ์ž์›์€ S3์™€ CloudFront๋ฅผ, ์„œ๋ฒ„ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์€ AWS ECS๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋ฆฌ์†Œ์Šค๋Š” VPC ๋‚ด๋ถ€ ๋ณ„๋„์˜ ์„œ๋ธŒ๋„ท(Public/Private)์— ์กด์žฌํ•˜๋ฉฐ, ALB์™€ NAT๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค. ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ๋Š” terraform์„ ํ†ตํ•ด ์„œ๋ฒ„๋ฅผ ๋™์ ์œผ๋กœ ํ™•์žฅํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ํ‰์ƒ์‹œ์—๋Š” ์ตœ์†Œ ์ธ์Šคํ„ด์Šค๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image


์„œ๋ธŒ ๋„๋ฉ”์ธ์„ ์ ๊ทน ํ™œ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์„œ๋ธŒ ๋„๋ฉ”์ธ ๊ฐ„ ์ฟ ํ‚ค๋ฅผ ๊ณต์œ ํ•ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ์„œ๋ฒ„, ๋ชจ๋‹ˆํ„ฐ๋ง ์„œ๋ฒ„์™€ ๊ฐ™์€ ์„œ๋ธŒ ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ์ ‘๊ทผ์€ WAF ๋ฐ Security Group์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


4. Contents

  1. Resource ๊ด€๋ฆฌ
  2. Config ๊ด€๋ฆฌ
  3. Server
  4. RateLimiter
  5. Monitoring
  6. Log
  7. DB ๋ฐฑ์—…


4-1. Resource ๊ด€๋ฆฌ

ํ”„๋กœ๋น„์ €๋‹์„ ํ›„, ๋ณ€๊ฒฝ๋  ์ผ์ด ์ ์€ ์ž์› ๋“ค, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ™์ด ๋ณ€๊ฒฝ๋˜์–ด์„  ์•ˆ ๋˜๋Š” ์ž์› ๋“ค์€ ignore_changes๋ฅผ ํ†ตํ•ด ํ…Œ๋ผํผ ๋ผ์ดํ”„์‚ฌ์ดํด์—์„œ ์ œ์™ธํ•œ ํ›„, ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

resource "aws_cloudfront_distribution" "s3_distribution_tasks_dev" {
  
  ......

  lifecycle {
    ignore_changes = all
  }
}


4-2. Config ๊ด€๋ฆฌ

Git Submodule๊ณผ AWS Secret Manager๋ฅผ ์‚ฌ์šฉํ•ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image


์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๋Š” ๊ฐ’๋“ค์€ ์•”ํ˜ธํ™”๋œ ์ƒํƒœ๋กœ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

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

    ......


4-3. Server

๋ฆฌ์†Œ์Šค ๋ฐ ์˜คํ†  ์Šค์ผ€์ผ๋ง์„ ์กฐ๊ธˆ ๋” ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด Fargate ๋Œ€์‹  EC2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๋ฐฐํฌ ๋ฐ ํฌํŠธ ์ถฉ๋Œ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ECS ๋™์  ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image


4-4. RateLimiter

Route53์—์„œ WAF๋กœ ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ์ตœ๋Œ€ ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ œํ•œํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๋ชจ๋‹ˆํ„ฐ๋ง ์„œ๋ฒ„, ๊ด€๋ฆฌ์ž API ๋“ฑ ํŠน์ • ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ ‘๊ทผ์€ ALB์™€ WAF, Security Group์œผ๋กœ ์ œํ•œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image

ํ‰์†Œ์—๋Š” ๋ถ„๋‹น 1,000ํšŒ ์ด์ƒ์ผ ๋•Œ, IP ๊ธฐ๋ฐ˜์œผ๋กœ API ์š”์ฒญ ์ œํ•œ์„ ๊ฑธ๊ณ  ์žˆ์œผ๋ฉฐ, ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ, ์ด๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.


4-5. Monitoring

๋ชจ๋‹ˆํ„ฐ๋ง์€ Prometheus์™€ Grafana๋ฅผ CloudWatch์™€ ์—ฐ๋™ํ•ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‹ˆํ„ฐ๋ง ์ค‘์ธ ๋ฆฌ์†Œ์Šค๋Š” EC2 ์„œ๋ฒ„, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง€ํ‘œ, RDS, Redis, MongoDB์ด๋ฉฐ, CPU/๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ , Slow Query ๋“ฑ์„ ์ฒดํฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

image

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค์šด๋  ๊ฒฝ์šฐ, ์ž๋™์œผ๋กœ ํž™ ๋คํ”„๋ฅผ ์ƒ์„ฑํ•œ ํ›„, ์ด๋ฅผ ์ •์  ์ €์žฅ์†Œ๋กœ ์—…๋กœ๋“œํ•˜๊ณ  ์•Œ๋ฆผ์„ ๋ณด๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


์˜คํ†  ์Šค์ผ€์ผ๋ง์€ 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
  }
}


4-6. Log

๋‹น์ผ ๋กœ๊ทธ๋Š” 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), ํŒŒ๋ผ๋ฏธํ„ฐ, ์‘๋‹ต ์‹œ๊ฐ„ ๋“ฑ์„ ๋‚จ๊ธฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


4-7. DB ๋ฐฑ์—…

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋งค์ผ ์ƒˆ๋ฒฝ 3์‹œ๋งˆ๋‹ค ์Šค๋ƒ…์ƒท์„ ์ƒ์„ฑํ•ด ๋ฐฑ์—…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑ ํ›„, AWS UI๋ฅผ ํ†ตํ•ด ์„ค์ •์„ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, Import๋ฅผ ํ†ตํ•ด ์‹ฑํฌ๋ฅผ ๋งž์ถ”๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


5. Modules

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๋Š” ๋ณ„๋„์˜ ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๋ฅผ ๊ณ ๋ คํ•ด ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

Visit original content creator repository https://github.com/dailyge/dailyge-infra

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *