From 0707f2fa8f1e7bbf29ea909ef5d48acf8e89dc65 Mon Sep 17 00:00:00 2001 From: Suhyen Im Date: Fri, 3 Apr 2026 17:25:56 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20#8=20EKS=20=EB=B0=B0=ED=8F=AC?= =?UTF-8?q?=EC=9A=A9=20K8s=20=EB=A7=A4=EB=8B=88=ED=8E=98=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=A0=84=EC=B2=B4=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- k8s/auth-service/deployment.yml | 34 ++++++-- k8s/configmap.yml | 25 ++++++ k8s/event-service/deployment.yml | 34 ++++++-- k8s/gateway/deployment.yml | 29 ++++++- k8s/ingress.yml | 16 ++-- k8s/kafka/service.yml | 18 +++++ k8s/kafka/statefulset.yml | 102 ++++++++++++++++++++++++ k8s/payment-service/deployment.yml | 36 +++++++-- k8s/pdb.yml | 42 ++++++++++ k8s/postgres/init-db-configmap.yml | 29 +++++++ k8s/postgres/service.yml | 17 ++++ k8s/postgres/statefulset.yml | 104 +++++++++++++++++++++++++ k8s/redis/deployment.yml | 71 +++++++++++++++++ k8s/redis/service.yml | 17 ++++ k8s/reservation-service/deployment.yml | 49 ++++++++++-- k8s/secrets.yml | 16 ++++ k8s/user-service/deployment.yml | 34 ++++++-- k8s/web/deployment.yml | 53 +++++++++++++ k8s/web/service.yml | 17 ++++ 19 files changed, 703 insertions(+), 40 deletions(-) create mode 100644 k8s/kafka/service.yml create mode 100644 k8s/kafka/statefulset.yml create mode 100644 k8s/pdb.yml create mode 100644 k8s/postgres/init-db-configmap.yml create mode 100644 k8s/postgres/service.yml create mode 100644 k8s/postgres/statefulset.yml create mode 100644 k8s/redis/deployment.yml create mode 100644 k8s/redis/service.yml create mode 100644 k8s/secrets.yml create mode 100644 k8s/web/deployment.yml create mode 100644 k8s/web/service.yml diff --git a/k8s/auth-service/deployment.yml b/k8s/auth-service/deployment.yml index a4c9178..b947c33 100644 --- a/k8s/auth-service/deployment.yml +++ b/k8s/auth-service/deployment.yml @@ -19,24 +19,46 @@ spec: app.kubernetes.io/part-of: opentraum app.kubernetes.io/component: auth spec: + terminationGracePeriodSeconds: 35 + imagePullSecrets: + - name: harbor-registry-secret + securityContext: + runAsNonRoot: true + fsGroup: 1000 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/part-of: opentraum containers: - name: auth-service - image: opentraum/auth-service:latest + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-auth-service:latest ports: - containerPort: 8081 protocol: TCP + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false envFrom: - configMapRef: name: opentraum-config + - secretRef: + name: opentraum-secrets env: - - name: SPRING_DATASOURCE_URL - value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_auth" + - name: DB_NAME + value: "opentraum_auth" + - name: SPRING_R2DBC_URL + value: "r2dbc:postgresql://opentraum-postgres:5432/opentraum_auth" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: - memory: "128Mi" - cpu: "250m" - limits: memory: "256Mi" + cpu: "150m" + limits: + memory: "512Mi" cpu: "500m" livenessProbe: httpGet: diff --git a/k8s/configmap.yml b/k8s/configmap.yml index c5e0ddd..c9500f3 100644 --- a/k8s/configmap.yml +++ b/k8s/configmap.yml @@ -12,17 +12,23 @@ data: SPRING_DATASOURCE_HOST: "opentraum-postgres" SPRING_DATASOURCE_PORT: "5432" SPRING_DATASOURCE_USERNAME: "opentraum" + DB_HOST: "opentraum-postgres" + DB_PORT: "5432" + DB_USERNAME: "opentraum" # --------------------------------------------------------------------------- # Redis # --------------------------------------------------------------------------- SPRING_DATA_REDIS_HOST: "opentraum-redis" SPRING_DATA_REDIS_PORT: "6379" + REDIS_HOST: "opentraum-redis" + REDIS_PORT: "6379" # --------------------------------------------------------------------------- # Kafka # --------------------------------------------------------------------------- SPRING_KAFKA_BOOTSTRAP_SERVERS: "opentraum-kafka:9092" + KAFKA_BOOTSTRAP_SERVERS: "opentraum-kafka:9092" # --------------------------------------------------------------------------- # Service Discovery (internal K8s DNS) @@ -33,6 +39,25 @@ data: RESERVATION_SERVICE_URL: "http://reservation-service.opentraum.svc.cluster.local:8084" PAYMENT_SERVICE_URL: "http://payment-service.opentraum.svc.cluster.local:8085" + # --------------------------------------------------------------------------- + # Gateway Route Override (prod profile 보완) + # --------------------------------------------------------------------------- + SPRING_CLOUD_GATEWAY_ROUTES_0_ID: "auth-service" + SPRING_CLOUD_GATEWAY_ROUTES_0_URI: "http://auth-service:8081" + SPRING_CLOUD_GATEWAY_ROUTES_0_PREDICATES_0: "Path=/api/v1/auth/**" + SPRING_CLOUD_GATEWAY_ROUTES_1_ID: "user-service" + SPRING_CLOUD_GATEWAY_ROUTES_1_URI: "http://user-service:8082" + SPRING_CLOUD_GATEWAY_ROUTES_1_PREDICATES_0: "Path=/api/v1/users/**,/api/v1/tenants/**" + SPRING_CLOUD_GATEWAY_ROUTES_2_ID: "event-service" + SPRING_CLOUD_GATEWAY_ROUTES_2_URI: "http://event-service:8083" + SPRING_CLOUD_GATEWAY_ROUTES_2_PREDICATES_0: "Path=/api/v1/concerts/**,/api/v1/schedules/**,/api/v1/admin/**" + SPRING_CLOUD_GATEWAY_ROUTES_3_ID: "reservation-service" + SPRING_CLOUD_GATEWAY_ROUTES_3_URI: "http://reservation-service:8084" + SPRING_CLOUD_GATEWAY_ROUTES_3_PREDICATES_0: "Path=/api/v1/reservations/**,/api/v1/queue/**,/api/v1/live/**,/api/v1/lottery/**" + SPRING_CLOUD_GATEWAY_ROUTES_4_ID: "payment-service" + SPRING_CLOUD_GATEWAY_ROUTES_4_URI: "http://payment-service:8085" + SPRING_CLOUD_GATEWAY_ROUTES_4_PREDICATES_0: "Path=/api/v1/payment/**" + # --------------------------------------------------------------------------- # Spring Common # --------------------------------------------------------------------------- diff --git a/k8s/event-service/deployment.yml b/k8s/event-service/deployment.yml index 6034129..502b4f7 100644 --- a/k8s/event-service/deployment.yml +++ b/k8s/event-service/deployment.yml @@ -19,24 +19,46 @@ spec: app.kubernetes.io/part-of: opentraum app.kubernetes.io/component: event spec: + terminationGracePeriodSeconds: 35 + imagePullSecrets: + - name: harbor-registry-secret + securityContext: + runAsNonRoot: true + fsGroup: 1000 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/part-of: opentraum containers: - name: event-service - image: opentraum/event-service:latest + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-event-service:latest ports: - containerPort: 8083 protocol: TCP + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false envFrom: - configMapRef: name: opentraum-config + - secretRef: + name: opentraum-secrets env: - - name: SPRING_DATASOURCE_URL - value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_event" + - name: DB_NAME + value: "opentraum_event" + - name: SPRING_R2DBC_URL + value: "r2dbc:postgresql://opentraum-postgres:5432/opentraum_event" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: - memory: "128Mi" - cpu: "250m" - limits: memory: "256Mi" + cpu: "150m" + limits: + memory: "512Mi" cpu: "500m" livenessProbe: httpGet: diff --git a/k8s/gateway/deployment.yml b/k8s/gateway/deployment.yml index 152ec03..ff1ad24 100644 --- a/k8s/gateway/deployment.yml +++ b/k8s/gateway/deployment.yml @@ -19,21 +19,42 @@ spec: app.kubernetes.io/part-of: opentraum app.kubernetes.io/component: gateway spec: + terminationGracePeriodSeconds: 35 + imagePullSecrets: + - name: harbor-registry-secret + securityContext: + runAsNonRoot: true + fsGroup: 1000 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/part-of: opentraum containers: - name: gateway - image: opentraum/gateway:latest + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-gateway:latest ports: - containerPort: 8080 protocol: TCP + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false envFrom: - configMapRef: name: opentraum-config + - secretRef: + name: opentraum-secrets + env: + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: - memory: "128Mi" - cpu: "250m" - limits: memory: "256Mi" + cpu: "150m" + limits: + memory: "512Mi" cpu: "500m" livenessProbe: httpGet: diff --git a/k8s/ingress.yml b/k8s/ingress.yml index cf832c3..af5f8ce 100644 --- a/k8s/ingress.yml +++ b/k8s/ingress.yml @@ -6,23 +6,27 @@ metadata: labels: app.kubernetes.io/part-of: opentraum annotations: - nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" - nginx.ingress.kubernetes.io/proxy-read-timeout: "60" + nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "60" - nginx.ingress.kubernetes.io/rate-limit: "100" - nginx.ingress.kubernetes.io/rate-limit-window: "1m" spec: ingressClassName: nginx rules: - - host: api.opentraum.com + - host: opentraum.52.79.80.47.nip.io http: paths: - - path: / + - path: /api pathType: Prefix backend: service: name: gateway port: number: 8080 + - path: / + pathType: Prefix + backend: + service: + name: web + port: + number: 80 diff --git a/k8s/kafka/service.yml b/k8s/kafka/service.yml new file mode 100644 index 0000000..5d51b45 --- /dev/null +++ b/k8s/kafka/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: opentraum-kafka + namespace: opentraum + labels: + app: opentraum-kafka + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: messaging +spec: + type: ClusterIP + selector: + app: opentraum-kafka + ports: + - name: client + port: 9092 + targetPort: 9092 + protocol: TCP diff --git a/k8s/kafka/statefulset.yml b/k8s/kafka/statefulset.yml new file mode 100644 index 0000000..838061e --- /dev/null +++ b/k8s/kafka/statefulset.yml @@ -0,0 +1,102 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: opentraum-kafka + namespace: opentraum + labels: + app: opentraum-kafka + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: messaging +spec: + serviceName: opentraum-kafka + replicas: 1 + selector: + matchLabels: + app: opentraum-kafka + template: + metadata: + labels: + app: opentraum-kafka + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: messaging + spec: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 50 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: In + values: + - database + - cache + topologyKey: kubernetes.io/hostname + containers: + - name: kafka + image: apache/kafka:3.7.0 + ports: + - containerPort: 9092 + name: client + protocol: TCP + env: + - name: KAFKA_NODE_ID + value: "1" + - name: KAFKA_PROCESS_ROLES + value: "broker,controller" + - name: KAFKA_CONTROLLER_QUORUM_VOTERS + value: "1@localhost:9093" + - name: KAFKA_LISTENERS + value: "PLAINTEXT://:9092,CONTROLLER://:9093" + - name: KAFKA_ADVERTISED_LISTENERS + value: "PLAINTEXT://opentraum-kafka:9092" + - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP + value: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT" + - name: KAFKA_CONTROLLER_LISTENER_NAMES + value: "CONTROLLER" + - name: KAFKA_INTER_BROKER_LISTENER_NAME + value: "PLAINTEXT" + - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR + value: "1" + - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR + value: "1" + - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR + value: "1" + - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE + value: "true" + - name: CLUSTER_ID + value: "MkU3OEVBNTcwNTJENDM2Qk" + resources: + requests: + memory: "384Mi" + cpu: "200m" + limits: + memory: "512Mi" + cpu: "500m" + volumeMounts: + - name: kafka-data + mountPath: /tmp/kraft-combined-logs + livenessProbe: + tcpSocket: + port: 9092 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + tcpSocket: + port: 9092 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + volumeClaimTemplates: + - metadata: + name: kafka-data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: ebs-sc + resources: + requests: + storage: 5Gi diff --git a/k8s/payment-service/deployment.yml b/k8s/payment-service/deployment.yml index e80f423..a73e77d 100644 --- a/k8s/payment-service/deployment.yml +++ b/k8s/payment-service/deployment.yml @@ -19,24 +19,48 @@ spec: app.kubernetes.io/part-of: opentraum app.kubernetes.io/component: payment spec: + terminationGracePeriodSeconds: 35 + imagePullSecrets: + - name: harbor-registry-secret + securityContext: + runAsNonRoot: true + fsGroup: 1000 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/part-of: opentraum containers: - name: payment-service - image: opentraum/payment-service:latest + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-payment-service:latest ports: - containerPort: 8085 protocol: TCP + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false envFrom: - configMapRef: name: opentraum-config + - secretRef: + name: opentraum-secrets env: - - name: SPRING_DATASOURCE_URL - value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_payment" + - name: DB_NAME + value: "opentraum_payment" + - name: SPRING_R2DBC_URL + value: "r2dbc:postgresql://opentraum-postgres:5432/opentraum_payment" + - name: JAVA_OPTS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: - memory: "128Mi" - cpu: "250m" - limits: memory: "256Mi" + cpu: "150m" + limits: + memory: "512Mi" cpu: "500m" livenessProbe: httpGet: diff --git a/k8s/pdb.yml b/k8s/pdb.yml new file mode 100644 index 0000000..10c5e26 --- /dev/null +++ b/k8s/pdb.yml @@ -0,0 +1,42 @@ +--- +# Gateway — 트래픽 진입점이므로 롤링 업데이트 시 최소 가용성 보장 +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: gateway-pdb + namespace: opentraum + labels: + app.kubernetes.io/part-of: opentraum +spec: + maxUnavailable: 0 + selector: + matchLabels: + app: gateway +--- +# PostgreSQL — 데이터 유실 방지, eviction 차단 +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: postgres-pdb + namespace: opentraum + labels: + app.kubernetes.io/part-of: opentraum +spec: + maxUnavailable: 0 + selector: + matchLabels: + app: opentraum-postgres +--- +# Kafka — 메시지 유실 방지 +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: kafka-pdb + namespace: opentraum + labels: + app.kubernetes.io/part-of: opentraum +spec: + maxUnavailable: 0 + selector: + matchLabels: + app: opentraum-kafka diff --git a/k8s/postgres/init-db-configmap.yml b/k8s/postgres/init-db-configmap.yml new file mode 100644 index 0000000..d191a7a --- /dev/null +++ b/k8s/postgres/init-db-configmap.yml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-init-db + namespace: opentraum + labels: + app.kubernetes.io/part-of: opentraum +data: + init-db.sh: | + #!/bin/bash + set -e + echo "=========================================" + echo " OpenTraum: Initializing databases..." + echo "=========================================" + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE opentraum_auth OWNER = opentraum ENCODING = 'UTF8'; + CREATE DATABASE opentraum_user OWNER = opentraum ENCODING = 'UTF8'; + CREATE DATABASE opentraum_event OWNER = opentraum ENCODING = 'UTF8'; + CREATE DATABASE opentraum_reservation OWNER = opentraum ENCODING = 'UTF8'; + CREATE DATABASE opentraum_payment OWNER = opentraum ENCODING = 'UTF8'; + GRANT ALL PRIVILEGES ON DATABASE opentraum_auth TO opentraum; + GRANT ALL PRIVILEGES ON DATABASE opentraum_user TO opentraum; + GRANT ALL PRIVILEGES ON DATABASE opentraum_event TO opentraum; + GRANT ALL PRIVILEGES ON DATABASE opentraum_reservation TO opentraum; + GRANT ALL PRIVILEGES ON DATABASE opentraum_payment TO opentraum; + EOSQL + echo "=========================================" + echo " OpenTraum: All databases created!" + echo "=========================================" diff --git a/k8s/postgres/service.yml b/k8s/postgres/service.yml new file mode 100644 index 0000000..598f8eb --- /dev/null +++ b/k8s/postgres/service.yml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: opentraum-postgres + namespace: opentraum + labels: + app: opentraum-postgres + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: database +spec: + type: ClusterIP + selector: + app: opentraum-postgres + ports: + - port: 5432 + targetPort: 5432 + protocol: TCP diff --git a/k8s/postgres/statefulset.yml b/k8s/postgres/statefulset.yml new file mode 100644 index 0000000..6b71bb5 --- /dev/null +++ b/k8s/postgres/statefulset.yml @@ -0,0 +1,104 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: opentraum-postgres + namespace: opentraum + labels: + app: opentraum-postgres + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: database +spec: + serviceName: opentraum-postgres + replicas: 1 + selector: + matchLabels: + app: opentraum-postgres + template: + metadata: + labels: + app: opentraum-postgres + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: database + spec: + # Node 2 (거의 비어있음)에 배치 선호 + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + preference: + matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - ap-northeast-2b + # Redis, Kafka와 같은 노드 선호 (인프라끼리 모음) + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 50 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: In + values: + - cache + - messaging + topologyKey: kubernetes.io/hostname + containers: + - name: postgres + image: postgres:16-alpine + ports: + - containerPort: 5432 + protocol: TCP + env: + - name: POSTGRES_USER + value: "opentraum" + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: opentraum-secrets + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: "opentraum" + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + resources: + requests: + memory: "384Mi" + cpu: "200m" + limits: + memory: "512Mi" + cpu: "500m" + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + - name: init-db + mountPath: /docker-entrypoint-initdb.d + livenessProbe: + exec: + command: ["pg_isready", "-U", "opentraum"] + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + exec: + command: ["pg_isready", "-U", "opentraum"] + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + volumes: + - name: init-db + configMap: + name: postgres-init-db + defaultMode: 0755 + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: ebs-sc + resources: + requests: + storage: 5Gi diff --git a/k8s/redis/deployment.yml b/k8s/redis/deployment.yml new file mode 100644 index 0000000..6059b43 --- /dev/null +++ b/k8s/redis/deployment.yml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: opentraum-redis + namespace: opentraum + labels: + app: opentraum-redis + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: cache +spec: + replicas: 1 + selector: + matchLabels: + app: opentraum-redis + template: + metadata: + labels: + app: opentraum-redis + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: cache + spec: + # 인프라끼리 모아서 배치 + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 50 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: In + values: + - database + - messaging + topologyKey: kubernetes.io/hostname + containers: + - name: redis + image: redis:7-alpine + ports: + - containerPort: 6379 + protocol: TCP + command: + - redis-server + - --appendonly + - "yes" + - --maxmemory + - 128mb + - --maxmemory-policy + - allkeys-lru + resources: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "192Mi" + cpu: "200m" + livenessProbe: + exec: + command: ["redis-cli", "ping"] + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + readinessProbe: + exec: + command: ["redis-cli", "ping"] + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/redis/service.yml b/k8s/redis/service.yml new file mode 100644 index 0000000..9883754 --- /dev/null +++ b/k8s/redis/service.yml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: opentraum-redis + namespace: opentraum + labels: + app: opentraum-redis + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: cache +spec: + type: ClusterIP + selector: + app: opentraum-redis + ports: + - port: 6379 + targetPort: 6379 + protocol: TCP diff --git a/k8s/reservation-service/deployment.yml b/k8s/reservation-service/deployment.yml index 809643d..873825d 100644 --- a/k8s/reservation-service/deployment.yml +++ b/k8s/reservation-service/deployment.yml @@ -19,24 +19,61 @@ spec: app.kubernetes.io/part-of: opentraum app.kubernetes.io/component: reservation spec: + terminationGracePeriodSeconds: 35 + imagePullSecrets: + - name: harbor-registry-secret + securityContext: + runAsNonRoot: true + fsGroup: 1000 + # reservation ↔ event 자주 통신하므로 같은 노드 선호 + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 80 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - event-service + topologyKey: kubernetes.io/hostname + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/part-of: opentraum containers: - name: reservation-service - image: opentraum/reservation-service:latest + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-reservation-service:cfb2847 ports: - containerPort: 8084 protocol: TCP + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false envFrom: - configMapRef: name: opentraum-config + - secretRef: + name: opentraum-secrets env: - - name: SPRING_DATASOURCE_URL - value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_reservation" + - name: DB_NAME + value: "opentraum_reservation" + - name: SPRING_R2DBC_URL + value: "r2dbc:postgresql://opentraum-postgres:5432/opentraum_reservation" + - name: JAVA_OPTS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: - memory: "128Mi" - cpu: "250m" - limits: memory: "256Mi" + cpu: "150m" + limits: + memory: "512Mi" cpu: "500m" livenessProbe: httpGet: diff --git a/k8s/secrets.yml b/k8s/secrets.yml new file mode 100644 index 0000000..aebece1 --- /dev/null +++ b/k8s/secrets.yml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Secret +metadata: + name: opentraum-secrets + namespace: opentraum + labels: + app.kubernetes.io/part-of: opentraum +type: Opaque +stringData: + DB_USERNAME: "opentraum" + DB_PASSWORD: "opentraum" + POSTGRES_PASSWORD: "opentraum" + SPRING_R2DBC_USERNAME: "opentraum" + SPRING_R2DBC_PASSWORD: "opentraum" + JWT_SECRET: "opentraum-default-jwt-secret-key-must-be-at-least-256-bits-long-for-hs256" + # REDIS_PASSWORD 미설정 — Redis에 비밀번호 없으므로 환경변수를 주입하지 않음 diff --git a/k8s/user-service/deployment.yml b/k8s/user-service/deployment.yml index 00f5522..393271e 100644 --- a/k8s/user-service/deployment.yml +++ b/k8s/user-service/deployment.yml @@ -19,24 +19,46 @@ spec: app.kubernetes.io/part-of: opentraum app.kubernetes.io/component: user spec: + terminationGracePeriodSeconds: 35 + imagePullSecrets: + - name: harbor-registry-secret + securityContext: + runAsNonRoot: true + fsGroup: 1000 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/part-of: opentraum containers: - name: user-service - image: opentraum/user-service:latest + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-user-service:latest ports: - containerPort: 8082 protocol: TCP + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false envFrom: - configMapRef: name: opentraum-config + - secretRef: + name: opentraum-secrets env: - - name: SPRING_DATASOURCE_URL - value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_user" + - name: DB_NAME + value: "opentraum_user" + - name: SPRING_R2DBC_URL + value: "r2dbc:postgresql://opentraum-postgres:5432/opentraum_user" + - name: JAVA_TOOL_OPTIONS + value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" resources: requests: - memory: "128Mi" - cpu: "250m" - limits: memory: "256Mi" + cpu: "150m" + limits: + memory: "512Mi" cpu: "500m" livenessProbe: httpGet: diff --git a/k8s/web/deployment.yml b/k8s/web/deployment.yml new file mode 100644 index 0000000..1753b6f --- /dev/null +++ b/k8s/web/deployment.yml @@ -0,0 +1,53 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web + namespace: opentraum + labels: + app: web + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: frontend +spec: + replicas: 1 + selector: + matchLabels: + app: web + template: + metadata: + labels: + app: web + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: frontend + spec: + imagePullSecrets: + - name: harbor-registry-secret + containers: + - name: web + image: amdp-registry.skala-ai.com/skala26a-cloud/opentraum-web:latest + ports: + - containerPort: 80 + protocol: TCP + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "200m" + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 10 + periodSeconds: 15 + timeoutSeconds: 3 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/web/service.yml b/k8s/web/service.yml new file mode 100644 index 0000000..5a7d1b5 --- /dev/null +++ b/k8s/web/service.yml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: web + namespace: opentraum + labels: + app: web + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: frontend +spec: + type: ClusterIP + selector: + app: web + ports: + - port: 80 + targetPort: 80 + protocol: TCP From 0252de29ea2fe66e5c1fbe8942981db0a9d53b65 Mon Sep 17 00:00:00 2001 From: Suhyen Im Date: Fri, 3 Apr 2026 19:41:33 +0900 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20gitignore=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + k8s/secrets.yml | 16 ---------------- 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 k8s/secrets.yml diff --git a/.gitignore b/.gitignore index 9e3ca66..bcf93ff 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ docker-compose.override.yml k8s/*-secret.yml k8s/**/secret.yml k8s/secrets/ +k8s/secrets.yml # ========================= # Terraform (future) diff --git a/k8s/secrets.yml b/k8s/secrets.yml deleted file mode 100644 index aebece1..0000000 --- a/k8s/secrets.yml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: opentraum-secrets - namespace: opentraum - labels: - app.kubernetes.io/part-of: opentraum -type: Opaque -stringData: - DB_USERNAME: "opentraum" - DB_PASSWORD: "opentraum" - POSTGRES_PASSWORD: "opentraum" - SPRING_R2DBC_USERNAME: "opentraum" - SPRING_R2DBC_PASSWORD: "opentraum" - JWT_SECRET: "opentraum-default-jwt-secret-key-must-be-at-least-256-bits-long-for-hs256" - # REDIS_PASSWORD 미설정 — Redis에 비밀번호 없으므로 환경변수를 주입하지 않음