From 8eecd9e76cd2d6c8aae16c251a202eb65b9502c6 Mon Sep 17 00:00:00 2001 From: mrangjw <157506327+mrangjw@users.noreply.github.com> Date: Mon, 16 Mar 2026 14:00:17 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20#1=20=EC=9D=B8=ED=94=84=EB=9D=BC=20?= =?UTF-8?q?=EB=B3=B4=EC=9D=BC=EB=9F=AC=ED=94=8C=EB=A0=88=EC=9D=B4=ED=8A=B8?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Docker Compose 로컬 개발 환경 (전체 + 인프라 전용) - Kubernetes 매니페스트 (namespace, configmap, ingress, 서비스별 deployment/service) - GitHub Actions CI 워크플로우 스켈레톤 - DB 초기화 스크립트 (서비스별 5개 DB 자동 생성) --- .github/workflows/ci.yml | 115 +++++++++ .gitignore | 65 +++++ docker-compose.infra.yml | 134 ++++++++++ docker-compose.yml | 323 +++++++++++++++++++++++++ k8s/auth-service/deployment.yml | 57 +++++ k8s/auth-service/service.yml | 18 ++ k8s/configmap.yml | 41 ++++ k8s/event-service/deployment.yml | 57 +++++ k8s/event-service/service.yml | 18 ++ k8s/gateway/deployment.yml | 54 +++++ k8s/gateway/service.yml | 18 ++ k8s/ingress.yml | 28 +++ k8s/namespace.yml | 7 + k8s/payment-service/deployment.yml | 57 +++++ k8s/payment-service/service.yml | 18 ++ k8s/reservation-service/deployment.yml | 57 +++++ k8s/reservation-service/service.yml | 18 ++ k8s/user-service/deployment.yml | 57 +++++ k8s/user-service/service.yml | 18 ++ scripts/init-db.sh | 69 ++++++ 20 files changed, 1229 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 docker-compose.infra.yml create mode 100644 docker-compose.yml create mode 100644 k8s/auth-service/deployment.yml create mode 100644 k8s/auth-service/service.yml create mode 100644 k8s/configmap.yml create mode 100644 k8s/event-service/deployment.yml create mode 100644 k8s/event-service/service.yml create mode 100644 k8s/gateway/deployment.yml create mode 100644 k8s/gateway/service.yml create mode 100644 k8s/ingress.yml create mode 100644 k8s/namespace.yml create mode 100644 k8s/payment-service/deployment.yml create mode 100644 k8s/payment-service/service.yml create mode 100644 k8s/reservation-service/deployment.yml create mode 100644 k8s/reservation-service/service.yml create mode 100644 k8s/user-service/deployment.yml create mode 100644 k8s/user-service/service.yml create mode 100755 scripts/init-db.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..18f4bcc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,115 @@ +name: CI Pipeline + +# ============================================================================= +# OpenTraum — CI/CD Template +# ============================================================================= +# Skeleton workflow for building, testing, and publishing Docker images. +# Each microservice repository should copy and customize this template. +# ============================================================================= + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +env: + JAVA_VERSION: "21" + DOCKER_REGISTRY: ghcr.io + IMAGE_PREFIX: opentraum + +jobs: + # --------------------------------------------------------------------------- + # Build & Test + # --------------------------------------------------------------------------- + build: + name: Build & Test + runs-on: ubuntu-latest + + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: temurin + cache: gradle + + - name: Grant execute permission for Gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build -x test + + - name: Run tests + run: ./gradlew test + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results + path: build/reports/tests/ + retention-days: 7 + + # --------------------------------------------------------------------------- + # Docker Build & Push (only on main/develop push) + # --------------------------------------------------------------------------- + docker: + name: Docker Build & Push + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'push' + + permissions: + contents: read + packages: write + + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: temurin + cache: gradle + + - name: Grant execute permission for Gradlew + run: chmod +x gradlew + + - name: Build JAR + run: ./gradlew bootJar + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.DOCKER_REGISTRY }}/${{ github.repository }} + tags: | + type=ref,event=branch + type=sha,prefix= + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e3ca66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# ========================= +# OS Generated Files +# ========================= +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# ========================= +# IDE / Editor +# ========================= +.idea/ +.vscode/ +*.iml +*.swp +*.swo +*~ + +# ========================= +# Environment & Secrets +# ========================= +.env +.env.* +!.env.example +*.pem +*.key +*.crt +*.p12 +*.jks + +# ========================= +# Docker +# ========================= +docker-compose.override.yml + +# ========================= +# Kubernetes Secrets +# ========================= +k8s/*-secret.yml +k8s/**/secret.yml +k8s/secrets/ + +# ========================= +# Terraform (future) +# ========================= +.terraform/ +*.tfstate +*.tfstate.* +*.tfvars +!*.tfvars.example + +# ========================= +# Logs +# ========================= +*.log +logs/ + +# ========================= +# Misc +# ========================= +tmp/ +temp/ diff --git a/docker-compose.infra.yml b/docker-compose.infra.yml new file mode 100644 index 0000000..71c2f03 --- /dev/null +++ b/docker-compose.infra.yml @@ -0,0 +1,134 @@ +version: "3.9" + +# ============================================================================= +# OpenTraum — Infrastructure Only +# ============================================================================= +# Usage: docker compose -f docker-compose.infra.yml up -d +# Run only infrastructure services (PostgreSQL, Redis, Kafka) +# Use this when running microservices locally via IDE (IntelliJ, VS Code, etc.) +# ============================================================================= + +services: + # --------------------------------------------------------------------------- + # PostgreSQL 16 + # --------------------------------------------------------------------------- + postgres: + image: postgres:16-alpine + container_name: opentraum-postgres + restart: unless-stopped + ports: + - "5432:5432" + environment: + POSTGRES_USER: opentraum + POSTGRES_PASSWORD: opentraum + POSTGRES_DB: opentraum + volumes: + - postgres-data:/var/lib/postgresql/data + - ./scripts/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + healthcheck: + test: ["CMD-SHELL", "pg_isready -U opentraum -d opentraum"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + networks: + - opentraum-net + + # --------------------------------------------------------------------------- + # Redis 7 + # --------------------------------------------------------------------------- + redis: + image: redis:7-alpine + container_name: opentraum-redis + restart: unless-stopped + ports: + - "6379:6379" + command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru + volumes: + - redis-data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + networks: + - opentraum-net + + # --------------------------------------------------------------------------- + # Zookeeper (Kafka dependency) + # --------------------------------------------------------------------------- + zookeeper: + image: confluentinc/cp-zookeeper:7.6.0 + container_name: opentraum-zookeeper + restart: unless-stopped + ports: + - "2181:2181" + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + volumes: + - zookeeper-data:/var/lib/zookeeper/data + - zookeeper-logs:/var/lib/zookeeper/log + healthcheck: + test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + networks: + - opentraum-net + + # --------------------------------------------------------------------------- + # Kafka + # --------------------------------------------------------------------------- + kafka: + image: confluentinc/cp-kafka:7.6.0 + container_name: opentraum-kafka + restart: unless-stopped + ports: + - "9092:9092" + - "29092:29092" + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" + volumes: + - kafka-data:/var/lib/kafka/data + depends_on: + zookeeper: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "kafka-broker-api-versions --bootstrap-server localhost:9092"] + interval: 15s + timeout: 10s + retries: 5 + start_period: 60s + networks: + - opentraum-net + +# ============================================================================= +# Networks & Volumes +# ============================================================================= +networks: + opentraum-net: + driver: bridge + name: opentraum-net + +volumes: + postgres-data: + name: opentraum-postgres-data + redis-data: + name: opentraum-redis-data + zookeeper-data: + name: opentraum-zookeeper-data + zookeeper-logs: + name: opentraum-zookeeper-logs + kafka-data: + name: opentraum-kafka-data diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5d6be53 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,323 @@ +version: "3.9" + +# ============================================================================= +# OpenTraum — Full Local Development Environment +# ============================================================================= +# Usage: docker compose up -d +# All microservices + infrastructure for full integration testing +# ============================================================================= + +services: + # --------------------------------------------------------------------------- + # Infrastructure + # --------------------------------------------------------------------------- + postgres: + image: postgres:16-alpine + container_name: opentraum-postgres + restart: unless-stopped + ports: + - "5432:5432" + environment: + POSTGRES_USER: opentraum + POSTGRES_PASSWORD: opentraum + POSTGRES_DB: opentraum + volumes: + - postgres-data:/var/lib/postgresql/data + - ./scripts/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + healthcheck: + test: ["CMD-SHELL", "pg_isready -U opentraum -d opentraum"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + networks: + - opentraum-net + + redis: + image: redis:7-alpine + container_name: opentraum-redis + restart: unless-stopped + ports: + - "6379:6379" + command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru + volumes: + - redis-data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + networks: + - opentraum-net + + zookeeper: + image: confluentinc/cp-zookeeper:7.6.0 + container_name: opentraum-zookeeper + restart: unless-stopped + ports: + - "2181:2181" + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + volumes: + - zookeeper-data:/var/lib/zookeeper/data + - zookeeper-logs:/var/lib/zookeeper/log + healthcheck: + test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + networks: + - opentraum-net + + kafka: + image: confluentinc/cp-kafka:7.6.0 + container_name: opentraum-kafka + restart: unless-stopped + ports: + - "9092:9092" + - "29092:29092" + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" + volumes: + - kafka-data:/var/lib/kafka/data + depends_on: + zookeeper: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "kafka-broker-api-versions --bootstrap-server localhost:9092"] + interval: 15s + timeout: 10s + retries: 5 + start_period: 60s + networks: + - opentraum-net + + # --------------------------------------------------------------------------- + # Microservices + # --------------------------------------------------------------------------- + gateway: + image: opentraum/gateway:latest + container_name: opentraum-gateway + restart: unless-stopped + build: + context: ../OpenTraum-gateway + dockerfile: Dockerfile + ports: + - "8080:8080" + environment: + SPRING_PROFILES_ACTIVE: local + SPRING_CLOUD_GATEWAY_ROUTES: "" + AUTH_SERVICE_URL: http://auth-service:8081 + USER_SERVICE_URL: http://user-service:8082 + EVENT_SERVICE_URL: http://event-service:8083 + RESERVATION_SERVICE_URL: http://reservation-service:8084 + PAYMENT_SERVICE_URL: http://payment-service:8085 + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: 6379 + depends_on: + redis: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 60s + networks: + - opentraum-net + + auth-service: + image: opentraum/auth-service:latest + container_name: opentraum-auth-service + restart: unless-stopped + build: + context: ../OpenTraum-auth-service + dockerfile: Dockerfile + ports: + - "8081:8081" + environment: + SPRING_PROFILES_ACTIVE: local + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/opentraum_auth + SPRING_DATASOURCE_USERNAME: opentraum + SPRING_DATASOURCE_PASSWORD: opentraum + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: 6379 + SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:29092 + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + kafka: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8081/actuator/health || exit 1"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 60s + networks: + - opentraum-net + + user-service: + image: opentraum/user-service:latest + container_name: opentraum-user-service + restart: unless-stopped + build: + context: ../OpenTraum-user-service + dockerfile: Dockerfile + ports: + - "8082:8082" + environment: + SPRING_PROFILES_ACTIVE: local + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/opentraum_user + SPRING_DATASOURCE_USERNAME: opentraum + SPRING_DATASOURCE_PASSWORD: opentraum + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: 6379 + SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:29092 + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + kafka: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8082/actuator/health || exit 1"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 60s + networks: + - opentraum-net + + event-service: + image: opentraum/event-service:latest + container_name: opentraum-event-service + restart: unless-stopped + build: + context: ../OpenTraum-event-service + dockerfile: Dockerfile + ports: + - "8083:8083" + environment: + SPRING_PROFILES_ACTIVE: local + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/opentraum_event + SPRING_DATASOURCE_USERNAME: opentraum + SPRING_DATASOURCE_PASSWORD: opentraum + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: 6379 + SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:29092 + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + kafka: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8083/actuator/health || exit 1"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 60s + networks: + - opentraum-net + + reservation-service: + image: opentraum/reservation-service:latest + container_name: opentraum-reservation-service + restart: unless-stopped + build: + context: ../OpenTraum-reservation-service + dockerfile: Dockerfile + ports: + - "8084:8084" + environment: + SPRING_PROFILES_ACTIVE: local + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/opentraum_reservation + SPRING_DATASOURCE_USERNAME: opentraum + SPRING_DATASOURCE_PASSWORD: opentraum + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: 6379 + SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:29092 + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + kafka: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8084/actuator/health || exit 1"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 60s + networks: + - opentraum-net + + payment-service: + image: opentraum/payment-service:latest + container_name: opentraum-payment-service + restart: unless-stopped + build: + context: ../OpenTraum-payment-service + dockerfile: Dockerfile + ports: + - "8085:8085" + environment: + SPRING_PROFILES_ACTIVE: local + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/opentraum_payment + SPRING_DATASOURCE_USERNAME: opentraum + SPRING_DATASOURCE_PASSWORD: opentraum + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: 6379 + SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:29092 + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + kafka: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8085/actuator/health || exit 1"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 60s + networks: + - opentraum-net + +# ============================================================================= +# Networks & Volumes +# ============================================================================= +networks: + opentraum-net: + driver: bridge + name: opentraum-net + +volumes: + postgres-data: + name: opentraum-postgres-data + redis-data: + name: opentraum-redis-data + zookeeper-data: + name: opentraum-zookeeper-data + zookeeper-logs: + name: opentraum-zookeeper-logs + kafka-data: + name: opentraum-kafka-data diff --git a/k8s/auth-service/deployment.yml b/k8s/auth-service/deployment.yml new file mode 100644 index 0000000..a4c9178 --- /dev/null +++ b/k8s/auth-service/deployment.yml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: auth-service + namespace: opentraum + labels: + app: auth-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: auth +spec: + replicas: 1 + selector: + matchLabels: + app: auth-service + template: + metadata: + labels: + app: auth-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: auth + spec: + containers: + - name: auth-service + image: opentraum/auth-service:latest + ports: + - containerPort: 8081 + protocol: TCP + envFrom: + - configMapRef: + name: opentraum-config + env: + - name: SPRING_DATASOURCE_URL + value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_auth" + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /actuator/health + port: 8081 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health + port: 8081 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/auth-service/service.yml b/k8s/auth-service/service.yml new file mode 100644 index 0000000..7209148 --- /dev/null +++ b/k8s/auth-service/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: auth-service + namespace: opentraum + labels: + app: auth-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: auth +spec: + type: ClusterIP + selector: + app: auth-service + ports: + - name: http + port: 8081 + targetPort: 8081 + protocol: TCP diff --git a/k8s/configmap.yml b/k8s/configmap.yml new file mode 100644 index 0000000..c5e0ddd --- /dev/null +++ b/k8s/configmap.yml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: opentraum-config + namespace: opentraum + labels: + app.kubernetes.io/part-of: opentraum +data: + # --------------------------------------------------------------------------- + # Database + # --------------------------------------------------------------------------- + SPRING_DATASOURCE_HOST: "opentraum-postgres" + SPRING_DATASOURCE_PORT: "5432" + SPRING_DATASOURCE_USERNAME: "opentraum" + + # --------------------------------------------------------------------------- + # Redis + # --------------------------------------------------------------------------- + SPRING_DATA_REDIS_HOST: "opentraum-redis" + SPRING_DATA_REDIS_PORT: "6379" + + # --------------------------------------------------------------------------- + # Kafka + # --------------------------------------------------------------------------- + SPRING_KAFKA_BOOTSTRAP_SERVERS: "opentraum-kafka:9092" + + # --------------------------------------------------------------------------- + # Service Discovery (internal K8s DNS) + # --------------------------------------------------------------------------- + AUTH_SERVICE_URL: "http://auth-service.opentraum.svc.cluster.local:8081" + USER_SERVICE_URL: "http://user-service.opentraum.svc.cluster.local:8082" + EVENT_SERVICE_URL: "http://event-service.opentraum.svc.cluster.local:8083" + RESERVATION_SERVICE_URL: "http://reservation-service.opentraum.svc.cluster.local:8084" + PAYMENT_SERVICE_URL: "http://payment-service.opentraum.svc.cluster.local:8085" + + # --------------------------------------------------------------------------- + # Spring Common + # --------------------------------------------------------------------------- + SPRING_PROFILES_ACTIVE: "prod" + SERVER_SHUTDOWN: "graceful" + SPRING_LIFECYCLE_TIMEOUT_PER_SHUTDOWN_PHASE: "30s" diff --git a/k8s/event-service/deployment.yml b/k8s/event-service/deployment.yml new file mode 100644 index 0000000..6034129 --- /dev/null +++ b/k8s/event-service/deployment.yml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: event-service + namespace: opentraum + labels: + app: event-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: event +spec: + replicas: 1 + selector: + matchLabels: + app: event-service + template: + metadata: + labels: + app: event-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: event + spec: + containers: + - name: event-service + image: opentraum/event-service:latest + ports: + - containerPort: 8083 + protocol: TCP + envFrom: + - configMapRef: + name: opentraum-config + env: + - name: SPRING_DATASOURCE_URL + value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_event" + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /actuator/health + port: 8083 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health + port: 8083 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/event-service/service.yml b/k8s/event-service/service.yml new file mode 100644 index 0000000..b586a2f --- /dev/null +++ b/k8s/event-service/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: event-service + namespace: opentraum + labels: + app: event-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: event +spec: + type: ClusterIP + selector: + app: event-service + ports: + - name: http + port: 8083 + targetPort: 8083 + protocol: TCP diff --git a/k8s/gateway/deployment.yml b/k8s/gateway/deployment.yml new file mode 100644 index 0000000..152ec03 --- /dev/null +++ b/k8s/gateway/deployment.yml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway + namespace: opentraum + labels: + app: gateway + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: gateway +spec: + replicas: 1 + selector: + matchLabels: + app: gateway + template: + metadata: + labels: + app: gateway + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: gateway + spec: + containers: + - name: gateway + image: opentraum/gateway:latest + ports: + - containerPort: 8080 + protocol: TCP + envFrom: + - configMapRef: + name: opentraum-config + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /actuator/health + port: 8080 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/gateway/service.yml b/k8s/gateway/service.yml new file mode 100644 index 0000000..2203124 --- /dev/null +++ b/k8s/gateway/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: gateway + namespace: opentraum + labels: + app: gateway + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: gateway +spec: + type: ClusterIP + selector: + app: gateway + ports: + - name: http + port: 8080 + targetPort: 8080 + protocol: TCP diff --git a/k8s/ingress.yml b/k8s/ingress.yml new file mode 100644 index 0000000..cf832c3 --- /dev/null +++ b/k8s/ingress.yml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: opentraum-ingress + namespace: opentraum + 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-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 + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: gateway + port: + number: 8080 diff --git a/k8s/namespace.yml b/k8s/namespace.yml new file mode 100644 index 0000000..73177a0 --- /dev/null +++ b/k8s/namespace.yml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: opentraum + labels: + app.kubernetes.io/part-of: opentraum + environment: production diff --git a/k8s/payment-service/deployment.yml b/k8s/payment-service/deployment.yml new file mode 100644 index 0000000..e80f423 --- /dev/null +++ b/k8s/payment-service/deployment.yml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: payment-service + namespace: opentraum + labels: + app: payment-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: payment +spec: + replicas: 1 + selector: + matchLabels: + app: payment-service + template: + metadata: + labels: + app: payment-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: payment + spec: + containers: + - name: payment-service + image: opentraum/payment-service:latest + ports: + - containerPort: 8085 + protocol: TCP + envFrom: + - configMapRef: + name: opentraum-config + env: + - name: SPRING_DATASOURCE_URL + value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_payment" + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /actuator/health + port: 8085 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health + port: 8085 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/payment-service/service.yml b/k8s/payment-service/service.yml new file mode 100644 index 0000000..60c187a --- /dev/null +++ b/k8s/payment-service/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: payment-service + namespace: opentraum + labels: + app: payment-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: payment +spec: + type: ClusterIP + selector: + app: payment-service + ports: + - name: http + port: 8085 + targetPort: 8085 + protocol: TCP diff --git a/k8s/reservation-service/deployment.yml b/k8s/reservation-service/deployment.yml new file mode 100644 index 0000000..809643d --- /dev/null +++ b/k8s/reservation-service/deployment.yml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: reservation-service + namespace: opentraum + labels: + app: reservation-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: reservation +spec: + replicas: 1 + selector: + matchLabels: + app: reservation-service + template: + metadata: + labels: + app: reservation-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: reservation + spec: + containers: + - name: reservation-service + image: opentraum/reservation-service:latest + ports: + - containerPort: 8084 + protocol: TCP + envFrom: + - configMapRef: + name: opentraum-config + env: + - name: SPRING_DATASOURCE_URL + value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_reservation" + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /actuator/health + port: 8084 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health + port: 8084 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/reservation-service/service.yml b/k8s/reservation-service/service.yml new file mode 100644 index 0000000..1886d56 --- /dev/null +++ b/k8s/reservation-service/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: reservation-service + namespace: opentraum + labels: + app: reservation-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: reservation +spec: + type: ClusterIP + selector: + app: reservation-service + ports: + - name: http + port: 8084 + targetPort: 8084 + protocol: TCP diff --git a/k8s/user-service/deployment.yml b/k8s/user-service/deployment.yml new file mode 100644 index 0000000..00f5522 --- /dev/null +++ b/k8s/user-service/deployment.yml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: user-service + namespace: opentraum + labels: + app: user-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: user +spec: + replicas: 1 + selector: + matchLabels: + app: user-service + template: + metadata: + labels: + app: user-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: user + spec: + containers: + - name: user-service + image: opentraum/user-service:latest + ports: + - containerPort: 8082 + protocol: TCP + envFrom: + - configMapRef: + name: opentraum-config + env: + - name: SPRING_DATASOURCE_URL + value: "jdbc:postgresql://opentraum-postgres:5432/opentraum_user" + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /actuator/health + port: 8082 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /actuator/health + port: 8082 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + restartPolicy: Always diff --git a/k8s/user-service/service.yml b/k8s/user-service/service.yml new file mode 100644 index 0000000..0e994b4 --- /dev/null +++ b/k8s/user-service/service.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: user-service + namespace: opentraum + labels: + app: user-service + app.kubernetes.io/part-of: opentraum + app.kubernetes.io/component: user +spec: + type: ClusterIP + selector: + app: user-service + ports: + - name: http + port: 8082 + targetPort: 8082 + protocol: TCP diff --git a/scripts/init-db.sh b/scripts/init-db.sh new file mode 100755 index 0000000..5319f92 --- /dev/null +++ b/scripts/init-db.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# ============================================================================= +# OpenTraum — PostgreSQL Initialization Script +# ============================================================================= +# This script is executed automatically by PostgreSQL on first startup. +# It creates separate databases for each microservice following the +# database-per-service pattern in MSA. +# ============================================================================= + +set -e + +echo "=========================================" +echo " OpenTraum: Initializing databases..." +echo "=========================================" + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + + -- Auth Service Database + CREATE DATABASE opentraum_auth + OWNER = opentraum + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.utf8' + LC_CTYPE = 'en_US.utf8'; + + -- User Service Database + CREATE DATABASE opentraum_user + OWNER = opentraum + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.utf8' + LC_CTYPE = 'en_US.utf8'; + + -- Event Service Database + CREATE DATABASE opentraum_event + OWNER = opentraum + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.utf8' + LC_CTYPE = 'en_US.utf8'; + + -- Reservation Service Database + CREATE DATABASE opentraum_reservation + OWNER = opentraum + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.utf8' + LC_CTYPE = 'en_US.utf8'; + + -- Payment Service Database + CREATE DATABASE opentraum_payment + OWNER = opentraum + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.utf8' + LC_CTYPE = 'en_US.utf8'; + + -- Grant all privileges + 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 " - opentraum_auth" +echo " - opentraum_user" +echo " - opentraum_event" +echo " - opentraum_reservation" +echo " - opentraum_payment" +echo "========================================="