From f46b47d1e7b5763e3a98ed3a7765cf4caf9c48f1 Mon Sep 17 00:00:00 2001 From: mason Date: Mon, 6 Apr 2026 23:16:30 +0900 Subject: [PATCH 1/2] modified --- terraform/eks_and_iam.tf | 4 ++-- terraform/providers.tf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform/eks_and_iam.tf b/terraform/eks_and_iam.tf index ab42f87..31cdef2 100644 --- a/terraform/eks_and_iam.tf +++ b/terraform/eks_and_iam.tf @@ -62,8 +62,8 @@ resource "aws_eks_node_group" "main" { instance_types = ["t3.medium"] scaling_config { desired_size = 2 - max_size = 10 - min_size = 1 + max_size = 2 + min_size = 2 } depends_on = [ aws_iam_role_policy_attachment.node_policy, diff --git a/terraform/providers.tf b/terraform/providers.tf index f23a584..994f5dd 100644 --- a/terraform/providers.tf +++ b/terraform/providers.tf @@ -7,7 +7,7 @@ terraform { } # [참고] backend_resources.tf를 먼저 apply 한 후, 생성된 S3 버킷 이름을 확인하고 주석을 해제하세요. # backend "s3" { - # bucket = "data-engineer-tf-state-여기에_생성된_랜덤문자열_입력" + # bucket = "data-engineer-tf-state-gx5de6" # key = "global/s3/terraform.tfstate" # region = "eu-west-1" # 단일 리전 # dynamodb_table = "data-engineer-tf-locks" From 9a8f40f2208a679db6072d74875074385ba6c441 Mon Sep 17 00:00:00 2001 From: mason Date: Mon, 6 Apr 2026 23:53:47 +0900 Subject: [PATCH 2/2] build github actions --- README.md | 2 + app/draw_winner.py | 50 +++++++++++++++++++++ app/templates/index.html | 91 +++++++++++++++++++++++++++++++++++++++ app/templates/login.html | 77 +++++++++++++++++++++++++++++++++ app/templates/mypage.html | 45 +++++++++++++++++++ app/templates/signup.html | 73 +++++++++++++++++++++++++++++++ k8s/base/cronjob.yaml | 20 +++++++++ k8s/base/deployment.yaml | 22 +++++----- k8s/base/hpa.yaml | 39 +++++++++++++++++ k8s/base/ingress.yaml | 23 ++++++++++ k8s/base/service.yaml | 4 +- 11 files changed, 433 insertions(+), 13 deletions(-) create mode 100644 README.md create mode 100644 app/draw_winner.py create mode 100644 app/templates/index.html create mode 100644 app/templates/login.html create mode 100644 app/templates/mypage.html create mode 100644 app/templates/signup.html create mode 100644 k8s/base/cronjob.yaml create mode 100644 k8s/base/hpa.yaml create mode 100644 k8s/base/ingress.yaml diff --git a/README.md b/README.md new file mode 100644 index 0000000..214125f --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# asac_de2_infra_1st +ASAC 데이터 엔지니어 2기 인프라 프로젝트 1조 diff --git a/app/draw_winner.py b/app/draw_winner.py new file mode 100644 index 0000000..7aac063 --- /dev/null +++ b/app/draw_winner.py @@ -0,0 +1,50 @@ +import pymysql +import os +import random +from datetime import datetime + +# DB 설정 (기존 환경변수 활용) +DB_CONFIG = { + "host": os.environ.get('DB_WRITER_HOST'), + "user": os.environ.get('DB_USER', 'admin'), + "password": os.environ.get('DB_PASSWORD'), + "database": os.environ.get('DB_NAME', 'raffle_db'), + "cursorclass": pymysql.cursors.DictCursor +} + +def run_draw(): + conn = pymysql.connect(**DB_CONFIG) + try: + with conn.cursor() as cursor: + # 1. 추첨 대상 찾기 (종료시간 지남 + 아직 추첨 안 됨) + cursor.execute(""" + SELECT id, title FROM raffle_items + WHERE end_time <= NOW() AND is_drawn = FALSE + """) + items_to_draw = cursor.fetchall() + + for item in items_to_draw: + # 2. 해당 상품 응모자 중 랜덤 1명 추출 + cursor.execute("SELECT user_id FROM raffle_entries WHERE item_id = %s", (item['id'],)) + entries = cursor.fetchall() + + if entries: + winner = random.choice(entries) + # 3. 당첨자 기록 및 추첨 완료 처리 + cursor.execute(""" + UPDATE raffle_items + SET winner_id = %s, is_drawn = TRUE + WHERE id = %s + """, (winner['user_id'], item['id'])) + print(f"[{datetime.now()}] {item['title']} 추첨 완료! 당첨자 ID: {winner['user_id']}") + else: + # 응모자가 없는 경우에도 종료 처리는 해야 함 + cursor.execute("UPDATE raffle_items SET is_drawn = TRUE WHERE id = %s", (item['id'],)) + print(f"[{datetime.now()}] {item['title']} 응모자 없음 처리.") + + conn.commit() + finally: + conn.close() + +if __name__ == "__main__": + run_draw() \ No newline at end of file diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..f12051e --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,91 @@ + + + + + + ASACDE RAFFLE + + + + + + +
+
+

WEEKLY
DROP LIST

+

04.01 - 04.30 LIMITED EDITION

+
+
+ +
+
+
+ +
+

🔥 지금 가장 핫한 래플

+
+ {% for item in items %} +
+
+ +
DRAW
+
+

{{ item.title }}

+

{{ item.description }}

+
--:--:--:--
+ +
+ {% endfor %} +
+
+ + + + diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..3e381f9 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,77 @@ + + + + + KREAM Style Login + + + + +
+ + +
+

로그인

+ +
+
+ + +
+ +
+ + +
+ +
+ +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/app/templates/mypage.html b/app/templates/mypage.html new file mode 100644 index 0000000..7eda6b7 --- /dev/null +++ b/app/templates/mypage.html @@ -0,0 +1,45 @@ + + + + + My Page + + + +
+
+

MY PAGE

+ HOME ⬅️ +
+ +
+
+
+
+

{{ user_id }}

+

PRO MEMBER

+
+
+ +

나의 응모 내역

+
+ {% if not history %} +

응모 내역이 없습니다.

+ {% else %} + {% for item in history %} +
+
+

{{ item.title }}

+

{{ item.apply_date }}

+
+ + {{ item.status }} + +
+ {% endfor %} + {% endif %} +
+
+
+ + \ No newline at end of file diff --git a/app/templates/signup.html b/app/templates/signup.html new file mode 100644 index 0000000..6e28191 --- /dev/null +++ b/app/templates/signup.html @@ -0,0 +1,73 @@ + + + + + KREAM Style Signup + + + + +
+ + +
+

회원가입

+ +
+
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+ 이미 회원이신가요? 로그인 +
+
+
+ + + + \ No newline at end of file diff --git a/k8s/base/cronjob.yaml b/k8s/base/cronjob.yaml new file mode 100644 index 0000000..2de1bdc --- /dev/null +++ b/k8s/base/cronjob.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: raffle-draw-job +spec: + schedule: "* * * * *" # 매 1분마다 실행 + jobTemplate: + spec: + template: + spec: + containers: + - name: draw-worker + image: 486053612615.dkr.ecr.eu-west-2.amazonaws.com/my-raffle-app:v1 + command: ["python", "draw_winner.py"] + envFrom: + - configMapRef: + name: raffle-config + - secretRef: + name: raffle-secret + restartPolicy: OnFailure \ No newline at end of file diff --git a/k8s/base/deployment.yaml b/k8s/base/deployment.yaml index 7e7b49b..20a9c19 100644 --- a/k8s/base/deployment.yaml +++ b/k8s/base/deployment.yaml @@ -13,15 +13,15 @@ spec: app: data-pipeline-app spec: containers: - - name: app - image: data-pipeline-app:latest + - name: app-pipeline-app + image: data-pipeline-app + imagePullPolicy: Always ports: - - containerPort: 8000 - readinessProbe: - httpGet: - path: /health - port: 8000 - livenessProbe: - httpGet: - path: /health - port: 8000 + - containerPort: 8080 + resources: + requests: + cpu: "200m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" diff --git a/k8s/base/hpa.yaml b/k8s/base/hpa.yaml new file mode 100644 index 0000000..07d4137 --- /dev/null +++ b/k8s/base/hpa.yaml @@ -0,0 +1,39 @@ +# V1 오토스케일러 +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: raffle-hpa-v1 +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: raffle-app-v1 + minReplicas: 2 + maxReplicas: 20 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 +--- +# V2 오토스케일러 +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: raffle-hpa-v2 +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: raffle-app-v2 + minReplicas: 2 + maxReplicas: 20 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 diff --git a/k8s/base/ingress.yaml b/k8s/base/ingress.yaml new file mode 100644 index 0000000..f4d7302 --- /dev/null +++ b/k8s/base/ingress.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: raffle-ingress + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + # 카나리아 가중치 설정 (현재 v1: 100%, v2: 0%) + alb.ingress.kubernetes.io/actions.canary-routing: > + {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"raffle-svc-v1","servicePort":"80","weight":100},{"serviceName":"raffle-svc-v2","servicePort":"80","weight":0}]}} +spec: + ingressClassName: alb + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: canary-routing + port: + name: use-annotation diff --git a/k8s/base/service.yaml b/k8s/base/service.yaml index ca4d85c..0f5baa8 100644 --- a/k8s/base/service.yaml +++ b/k8s/base/service.yaml @@ -7,5 +7,5 @@ spec: app: data-pipeline-app ports: - port: 80 - targetPort: 8000 - type: ClusterIP + targetPort: 8080 + protocol: TCP