From 9a7e75865a7d57eee99a22f4d4acba5638a3ae54 Mon Sep 17 00:00:00 2001 From: P82288200 Date: Fri, 20 Jun 2025 05:56:38 +0000 Subject: [PATCH] feat : initial commit --- HealthSync_BE/container/Dockerfile | 24 +++ HealthSync_BE/container/Dockerfile.backup | 120 +++++++++++++ HealthSync_BE/health-deployment.yaml | 43 +++++ .../manifest/configmap/common-configmap.yaml | 60 +++++++ .../manifest/deployment/goal-deployment.yaml | 64 +++++++ .../deployment/health-deployment.yaml | 56 ++++++ .../manifest/deployment/user-deployment.yaml | 42 +++++ HealthSync_BE/manifest/ingress/ingress.yaml | 55 ++++++ .../manifest/secret/common-secret.yaml | 46 +++++ HealthSync_BE/manifest/service/services.yaml | 38 ++++ .../container/Dockerfile-healthsync-front | 32 ++++ HealthSync_FE/container/nginx.conf | 50 ++++++ .../configmap/frontend-configmap.yaml | 16 ++ .../deployment/frontend-deployment.yaml | 41 +++++ .../manifest/ingress/frontend-ingress.yaml | 21 +++ .../manifest/service/frontend-service.yaml | 15 ++ .../kustomization.yaml.backup | 52 ++++++ .../intelligence-service-configmap.yaml | 51 ++++++ .../intelligence-service-deployment.yaml | 168 ++++++++++++++++++ .../hpa/intelligence-service-hpa.yaml | 44 +++++ .../ingress/intelligence-service-ingress.yaml | 32 ++++ .../secret/intelligence-service-secret.yaml | 29 +++ .../service/intelligence-service-service.yaml | 26 +++ .../configmap/motivator-configmap.yaml | 31 ++++ .../manifest/cronjob/motivator-cronjob.yaml | 48 +++++ .../manifest/secret/motivator-secret.yaml | 15 ++ HealthSync_Motivator/test-job.yaml | 39 ++++ README.md | 2 + 28 files changed, 1260 insertions(+) create mode 100644 HealthSync_BE/container/Dockerfile create mode 100644 HealthSync_BE/container/Dockerfile.backup create mode 100644 HealthSync_BE/health-deployment.yaml create mode 100644 HealthSync_BE/manifest/configmap/common-configmap.yaml create mode 100644 HealthSync_BE/manifest/deployment/goal-deployment.yaml create mode 100644 HealthSync_BE/manifest/deployment/health-deployment.yaml create mode 100644 HealthSync_BE/manifest/deployment/user-deployment.yaml create mode 100644 HealthSync_BE/manifest/ingress/ingress.yaml create mode 100644 HealthSync_BE/manifest/secret/common-secret.yaml create mode 100644 HealthSync_BE/manifest/service/services.yaml create mode 100644 HealthSync_FE/container/Dockerfile-healthsync-front create mode 100644 HealthSync_FE/container/nginx.conf create mode 100644 HealthSync_FE/manifest/configmap/frontend-configmap.yaml create mode 100644 HealthSync_FE/manifest/deployment/frontend-deployment.yaml create mode 100644 HealthSync_FE/manifest/ingress/frontend-ingress.yaml create mode 100644 HealthSync_FE/manifest/service/frontend-service.yaml create mode 100644 HealthSync_Intelligence/kustomization.yaml.backup create mode 100644 HealthSync_Intelligence/manifest/configmap/intelligence-service-configmap.yaml create mode 100644 HealthSync_Intelligence/manifest/deployment/intelligence-service-deployment.yaml create mode 100644 HealthSync_Intelligence/manifest/hpa/intelligence-service-hpa.yaml create mode 100644 HealthSync_Intelligence/manifest/ingress/intelligence-service-ingress.yaml create mode 100644 HealthSync_Intelligence/manifest/secret/intelligence-service-secret.yaml create mode 100644 HealthSync_Intelligence/manifest/service/intelligence-service-service.yaml create mode 100644 HealthSync_Motivator/manifest/configmap/motivator-configmap.yaml create mode 100644 HealthSync_Motivator/manifest/cronjob/motivator-cronjob.yaml create mode 100644 HealthSync_Motivator/manifest/secret/motivator-secret.yaml create mode 100644 HealthSync_Motivator/test-job.yaml create mode 100644 README.md diff --git a/HealthSync_BE/container/Dockerfile b/HealthSync_BE/container/Dockerfile new file mode 100644 index 0000000..d467db7 --- /dev/null +++ b/HealthSync_BE/container/Dockerfile @@ -0,0 +1,24 @@ +# Build stage +FROM openjdk:21-jdk-slim AS builder +ARG BUILD_LIB_DIR +ARG ARTIFACTORY_FILE +COPY ${BUILD_LIB_DIR}/${ARTIFACTORY_FILE} app.jar + +# Run stage +FROM openjdk:21-jdk-slim +ENV USERNAME k8s +ENV ARTIFACTORY_HOME /home/${USERNAME} +ENV JAVA_OPTS="" + +# Add a non-root user +RUN adduser --system --group ${USERNAME} && \ + mkdir -p ${ARTIFACTORY_HOME} && \ + chown ${USERNAME}:${USERNAME} ${ARTIFACTORY_HOME} + +WORKDIR ${ARTIFACTORY_HOME} +COPY --from=builder app.jar app.jar +RUN chown ${USERNAME}:${USERNAME} app.jar + +USER ${USERNAME} +ENTRYPOINT [ "sh", "-c" ] +CMD ["java ${JAVA_OPTS} -jar app.jar"] diff --git a/HealthSync_BE/container/Dockerfile.backup b/HealthSync_BE/container/Dockerfile.backup new file mode 100644 index 0000000..89d98d3 --- /dev/null +++ b/HealthSync_BE/container/Dockerfile.backup @@ -0,0 +1,120 @@ +# HealthSync Backend 통합 Dockerfile +# 전체 멀티프로젝트를 한 번에 빌드하고 특정 서비스를 선택 실행 + +# ============================================================================= +# Build Stage: 전체 멀티프로젝트 빌드 +# ============================================================================= +FROM openjdk:21-jdk-slim AS builder + +# 빌드에 필요한 패키지 설치 +RUN apt-get update && apt-get install -y \ + curl \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /workspace + +# Gradle Wrapper 및 설정 파일 복사 +COPY gradle/ gradle/ +COPY gradlew . +COPY gradle.properties . +COPY settings.gradle . +COPY build.gradle . + +# 각 서비스 소스코드 복사 +COPY common/ common/ +COPY api-gateway/ api-gateway/ +COPY user-service/ user-service/ +COPY health-service/ health-service/ +COPY intelligence-service/ intelligence-service/ +COPY goal-service/ goal-service/ +COPY motivator-service/ motivator-service/ + +# Gradle 실행 권한 부여 +RUN chmod +x gradlew + +# 전체 프로젝트 빌드 (테스트 제외) +RUN ./gradlew clean build -x test + +# 빌드된 JAR 파일들 확인 +RUN find . -name "*.jar" -type f + +# ============================================================================= +# Runtime Stage: 실행 환경 +# ============================================================================= +FROM openjdk:21-jdk-slim + +# 런타임 사용자 생성 +RUN addgroup --system --gid 1001 healthsync && \ + adduser --system --uid 1001 --gid 1001 healthsync + +# 작업 디렉토리 설정 +WORKDIR /app + +# 빌드된 JAR 파일들 복사 +COPY --from=builder /workspace/api-gateway/build/libs/*.jar ./jars/api-gateway.jar +COPY --from=builder /workspace/user-service/build/libs/*.jar ./jars/user-service.jar +COPY --from=builder /workspace/health-service/build/libs/*.jar ./jars/health-service.jar +COPY --from=builder /workspace/intelligence-service/build/libs/*.jar ./jars/intelligence-service.jar +COPY --from=builder /workspace/goal-service/build/libs/*.jar ./jars/goal-service.jar +COPY --from=builder /workspace/motivator-service/build/libs/*.jar ./jars/motivator-service.jar + +# 실행 스크립트 생성 +RUN cat > /app/start-service.sh << 'EOF' +#!/bin/bash + +SERVICE_NAME=${SERVICE_NAME:-user-service} +JAVA_OPTS=${JAVA_OPTS:-"-Xms256m -Xmx1024m"} + +echo "Starting HealthSync ${SERVICE_NAME}..." +echo "Java Options: ${JAVA_OPTS}" + +case ${SERVICE_NAME} in + "api-gateway") + exec java ${JAVA_OPTS} -jar /app/jars/api-gateway.jar + ;; + "user-service") + exec java ${JAVA_OPTS} -jar /app/jars/user-service.jar + ;; + "health-service") + exec java ${JAVA_OPTS} -jar /app/jars/health-service.jar + ;; + "intelligence-service") + exec java ${JAVA_OPTS} -jar /app/jars/intelligence-service.jar + ;; + "goal-service") + exec java ${JAVA_OPTS} -jar /app/jars/goal-service.jar + ;; + "motivator-service") + exec java ${JAVA_OPTS} -jar /app/jars/motivator-service.jar + ;; + *) + echo "Error: Unknown service name '${SERVICE_NAME}'" + echo "Available services: api-gateway, user-service, health-service, intelligence-service, goal-service, motivator-service" + exit 1 + ;; +esac +EOF + +# 스크립트 실행 권한 부여 +RUN chmod +x /app/start-service.sh + +# 디렉토리 소유자 변경 +RUN chown -R healthsync:healthsync /app + +# 사용자 변경 +USER healthsync + +# 헬스체크 스크립트 생성 +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD curl -f http://localhost:${SERVER_PORT:-8080}/actuator/health || exit 1 + +# 기본 포트 노출 (환경변수로 오버라이드 가능) +EXPOSE 8080 8081 8082 8083 8084 8085 + +# 환경변수 기본값 설정 +ENV SERVICE_NAME=user-service +ENV JAVA_OPTS="-Xms256m -Xmx1024m" +ENV SPRING_PROFILES_ACTIVE=docker + +# 실행 명령 +ENTRYPOINT ["/app/start-service.sh"] diff --git a/HealthSync_BE/health-deployment.yaml b/HealthSync_BE/health-deployment.yaml new file mode 100644 index 0000000..22718e5 --- /dev/null +++ b/HealthSync_BE/health-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: health-service + namespace: team1tier-healthsync-ns +spec: + replicas: 2 + selector: + matchLabels: + app: health-service + template: + metadata: + labels: + app: health-service + spec: + imagePullSecrets: + - name: acr-secret + containers: + - name: health-service + image: acrhealthsync01.azurecr.io/team1tier/health-service:1.0.0 + imagePullPolicy: Always + ports: + - containerPort: 8082 + envFrom: + - configMapRef: + name: common-config + - configMapRef: + name: health-config + - secretRef: + name: common-secret + - secretRef: + name: database-secret + - secretRef: + name: redis-secret + - secretRef: + name: health-db-secret + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi diff --git a/HealthSync_BE/manifest/configmap/common-configmap.yaml b/HealthSync_BE/manifest/configmap/common-configmap.yaml new file mode 100644 index 0000000..6042c45 --- /dev/null +++ b/HealthSync_BE/manifest/configmap/common-configmap.yaml @@ -0,0 +1,60 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: common-config + namespace: team1tier-healthsync-ns +data: + ALLOWED_ORIGINS: "http://20.249.193.105" + DDL_AUTO: "update" + SHOW_SQL: "false" + LOG_LEVEL: "INFO" + WEB_LOG_LEVEL: "INFO" + GOOGLE_REDIRECT_ID : http://team1tier.20.214.196.128.nip.io/login/oauth2/code/google + GOOGLE_CLIENT_ID: 198383870460-s1s72vgu91nq9qvg5dai28vafj7mlag1.apps.googleusercontent.com + GOOGLE_CLIENT_SECRET: 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 + OAUTH2_REDIRECT_URL : http://team1tier.20.214.196.128.nip.io/login +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: user-config + namespace: team1tier-healthsync-ns +data: + SERVER_PORT: "8081" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: health-config + namespace: team1tier-healthsync-ns +data: + SERVER_PORT: "8082" + USER_SERVICE_URL: "http://user-service:80" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: goal-config + namespace: team1tier-healthsync-ns +data: + SERVER_PORT: "8084" + USER_SERVICE_URL: "http://user-service:80" + INTELLIGENCE_SERVICE_URL: "http://team1tier.20.214.196.128.nip.io" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: redis-config + namespace: team1tier-healthsync-ns +data: + # Azure Cache for Redis 설정 + REDIS_HOST: "redis-digitalgarage-01.redis.cache.windows.net" + REDIS_PORT: "6380" # SSL 포트 + REDIS_SSL: "true" # SSL 활성화 + REDIS_TIMEOUT: "2000" + REDIS_DATABASE: "0" + # Connection Pool 설정 + REDIS_LETTUCE_POOL_MAX_ACTIVE: "8" + REDIS_LETTUCE_POOL_MAX_IDLE: "8" + REDIS_LETTUCE_POOL_MIN_IDLE: "0" +--- diff --git a/HealthSync_BE/manifest/deployment/goal-deployment.yaml b/HealthSync_BE/manifest/deployment/goal-deployment.yaml new file mode 100644 index 0000000..a94ca4e --- /dev/null +++ b/HealthSync_BE/manifest/deployment/goal-deployment.yaml @@ -0,0 +1,64 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: goal-service + namespace: team1tier-healthsync-ns +spec: + revisionHistoryLimit: 3 + replicas: 2 + selector: + matchLabels: + app: goal-service + template: + metadata: + labels: + app: goal-service + spec: + imagePullSecrets: + - name: acr-secret + containers: + - name: goal-service + image: acrhealthsync01.azurecr.io/team1tier/goal-service:1.0.8 + imagePullPolicy: Always + ports: + - containerPort: 8084 + envFrom: + - configMapRef: + name: common-config + - configMapRef: + name: goal-config + - configMapRef: + name: redis-config + - secretRef: + name: common-secret + - secretRef: + name: database-secret + - secretRef: + name: redis-secret + - secretRef: + name: goal-db-secret + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi + # startupProbe: + # httpGet: + # path: /actuator/health + # port: 8084 + # failureThreshold: 30 + # periodSeconds: 10 + # livenessProbe: + # httpGet: + # path: /actuator/health + # port: 8084 + # initialDelaySeconds: 60 + # periodSeconds: 15 + # readinessProbe: + # httpGet: + # path: /actuator/health + # port: 8084 + # initialDelaySeconds: 10 + # periodSeconds: 5 diff --git a/HealthSync_BE/manifest/deployment/health-deployment.yaml b/HealthSync_BE/manifest/deployment/health-deployment.yaml new file mode 100644 index 0000000..9a08f8e --- /dev/null +++ b/HealthSync_BE/manifest/deployment/health-deployment.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: health-service + namespace: team1tier-healthsync-ns +spec: + revisionHistoryLimit: 3 + replicas: 2 + selector: + matchLabels: + app: health-service + template: + metadata: + labels: + app: health-service + spec: + imagePullSecrets: + - name: acr-secret + containers: + - name: health-service + image: acrhealthsync01.azurecr.io/team1tier/health-service:1.0.13 + imagePullPolicy: Always + ports: + - containerPort: 8082 + env: + - name: SPRING_DATA_REDIS_HOST + value: "redis-digitalgarage-01.redis.cache.windows.net" + - name: SPRING_DATA_REDIS_PORT + value: "6380" + - name: SPRING_DATA_REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: redis-secret + key: REDIS_PASSWORD + - name: SPRING_DATA_REDIS_SSL_ENABLED + value: "true" + - name: SPRING_DATA_REDIS_TIMEOUT + value: "2000ms" + - name: DB_URL + value: "jdbc:postgresql://psql-digitalgarage-01.postgres.database.azure.com:5432/healthsync_db" + - name: DB_USERNAME + value: "team1tier" + - name: DB_PASSWORD + value: "Hi5Jessica!" + - name: JWT_SECRET + valueFrom: + secretKeyRef: + name: common-secret + key: JWT_SECRET + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi diff --git a/HealthSync_BE/manifest/deployment/user-deployment.yaml b/HealthSync_BE/manifest/deployment/user-deployment.yaml new file mode 100644 index 0000000..01325ec --- /dev/null +++ b/HealthSync_BE/manifest/deployment/user-deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: user-service + namespace: team1tier-healthsync-ns +spec: + revisionHistoryLimit: 3 + replicas: 1 + selector: + matchLabels: + app: user-service + template: + metadata: + labels: + app: user-service + spec: + imagePullSecrets: + - name: acr-secret + containers: + - name: user-service + image: acrhealthsync01.azurecr.io/team1tier/user-service:1.0.11 + imagePullPolicy: Always + ports: + - containerPort: 8081 + envFrom: + - configMapRef: + name: common-config + - configMapRef: + name: user-config + - secretRef: + name: database-secret + - secretRef: + name: redis-secret + - secretRef: + name: user-db-secret + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi diff --git a/HealthSync_BE/manifest/ingress/ingress.yaml b/HealthSync_BE/manifest/ingress/ingress.yaml new file mode 100644 index 0000000..8d08d32 --- /dev/null +++ b/HealthSync_BE/manifest/ingress/ingress.yaml @@ -0,0 +1,55 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: healthsync-ingress + namespace: team1tier-healthsync-ns + annotations: + kubernetes.io/ingress.class: nginx +spec: + ingressClassName: nginx + rules: + - host: team1tier.20.214.196.128.nip.io + http: + paths: + - path: /login/oauth2 + pathType: Prefix + backend: + service: + name: user-service + port: + number: 80 + - path: /api/user + pathType: Prefix + backend: + service: + name: user-service + port: + number: 80 + - path: /api/auth + pathType: Prefix + backend: + service: + name: user-service + port: + number: 80 + - path: /oauth2 + pathType: Prefix + backend: + service: + name: user-service + port: + number: 80 + - path: /api/health + pathType: Prefix + backend: + service: + name: health-service + port: + number: 80 + - path: /api/goals + pathType: Prefix + backend: + service: + name: goal-service + port: + number: 80 diff --git a/HealthSync_BE/manifest/secret/common-secret.yaml b/HealthSync_BE/manifest/secret/common-secret.yaml new file mode 100644 index 0000000..feda3bc --- /dev/null +++ b/HealthSync_BE/manifest/secret/common-secret.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: database-secret + namespace: team1tier-healthsync-ns +type: Opaque +stringData: + DB_USERNAME: "team1tier" + DB_PASSWORD: "Hi5Jessica!" +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret + namespace: team1tier-healthsync-ns +type: Opaque +stringData: + REDIS_PASSWORD: "HUezXQsxbphIeBy8FV9JDA3WaZDwOozGEAzCaByUk40=" +--- +apiVersion: v1 +kind: Secret +metadata: + name: user-db-secret + namespace: team1tier-healthsync-ns +type: Opaque +stringData: + DB_URL: "jdbc:postgresql://psql-digitalgarage-01.postgres.database.azure.com:5432/healthsync_db" +--- +apiVersion: v1 +kind: Secret +metadata: + name: health-db-secret + namespace: team1tier-healthsync-ns +type: Opaque +stringData: + DB_URL: "jdbc:postgresql://psql-digitalgarage-01.postgres.database.azure.com:5432/healthsync_db" +--- +apiVersion: v1 +kind: Secret +metadata: + name: goal-db-secret + namespace: team1tier-healthsync-ns +type: Opaque +stringData: + DB_URL: "jdbc:postgresql://psql-digitalgarage-01.postgres.database.azure.com:5432/healthsync_db" diff --git a/HealthSync_BE/manifest/service/services.yaml b/HealthSync_BE/manifest/service/services.yaml new file mode 100644 index 0000000..a60647c --- /dev/null +++ b/HealthSync_BE/manifest/service/services.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Service +metadata: + name: user-service + namespace: team1tier-healthsync-ns +spec: + selector: + app: user-service + ports: + - port: 80 + targetPort: 8081 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: health-service + namespace: team1tier-healthsync-ns +spec: + selector: + app: health-service + ports: + - port: 80 + targetPort: 8082 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: goal-service + namespace: team1tier-healthsync-ns +spec: + selector: + app: goal-service + ports: + - port: 80 + targetPort: 8084 + type: ClusterIP diff --git a/HealthSync_FE/container/Dockerfile-healthsync-front b/HealthSync_FE/container/Dockerfile-healthsync-front new file mode 100644 index 0000000..11cb654 --- /dev/null +++ b/HealthSync_FE/container/Dockerfile-healthsync-front @@ -0,0 +1,32 @@ +# Node.js Multi-stage build for React +FROM node:18-alpine AS builder + +WORKDIR /app +COPY package*.json ./ +RUN npm ci --only=production +COPY . . +RUN npm run build + +# Production stage with simple Nginx +FROM nginx:alpine + +# Copy built app +COPY --from=builder /app/build /usr/share/nginx/html + +# Create simple nginx config for React SPA +RUN echo 'server {' > /etc/nginx/conf.d/default.conf && \ + echo ' listen 80;' >> /etc/nginx/conf.d/default.conf && \ + echo ' server_name localhost;' >> /etc/nginx/conf.d/default.conf && \ + echo ' root /usr/share/nginx/html;' >> /etc/nginx/conf.d/default.conf && \ + echo ' index index.html;' >> /etc/nginx/conf.d/default.conf && \ + echo ' location / {' >> /etc/nginx/conf.d/default.conf && \ + echo ' try_files $uri $uri/ /index.html;' >> /etc/nginx/conf.d/default.conf && \ + echo ' }' >> /etc/nginx/conf.d/default.conf && \ + echo ' location /health {' >> /etc/nginx/conf.d/default.conf && \ + echo ' return 200 "healthy";' >> /etc/nginx/conf.d/default.conf && \ + echo ' add_header Content-Type text/plain;' >> /etc/nginx/conf.d/default.conf && \ + echo ' }' >> /etc/nginx/conf.d/default.conf && \ + echo '}' >> /etc/nginx/conf.d/default.conf + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/HealthSync_FE/container/nginx.conf b/HealthSync_FE/container/nginx.conf new file mode 100644 index 0000000..8143514 --- /dev/null +++ b/HealthSync_FE/container/nginx.conf @@ -0,0 +1,50 @@ +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; + + location / { + try_files $uri $uri/ /index.html; + } + + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + } +} diff --git a/HealthSync_FE/manifest/configmap/frontend-configmap.yaml b/HealthSync_FE/manifest/configmap/frontend-configmap.yaml new file mode 100644 index 0000000..6266a60 --- /dev/null +++ b/HealthSync_FE/manifest/configmap/frontend-configmap.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: frontend-config + namespace: team1tier-healthsync-front-ns +data: + runtime-env.js: | + window.__runtime_config__ = { + GOOGLE_CLIENT_ID: '198383870460-s1s72vgu91nq9qvg5dai28vafj7mlag1.apps.googleusercontent.com', + AUTH_URL: 'http://team1tier.20.214.196.128.nip.io/api/auth', + HEALTH_URL: 'http://team1tier.20.214.196.128.nip.io/api/health', + INTELLIGENCE_URL: 'http://team1tier.20.214.196.128.nip.io/api/intelligence', + GOAL_URL: 'http://team1tier.20.214.196.128.nip.io/api/goals', + MOTIVATOR_URL: 'http://team1tier.20.214.196.128.nip.io/api/motivator', + USER_URL: 'http://team1tier.20.214.196.128.nip.io/api/user' + }; diff --git a/HealthSync_FE/manifest/deployment/frontend-deployment.yaml b/HealthSync_FE/manifest/deployment/frontend-deployment.yaml new file mode 100644 index 0000000..e5943f4 --- /dev/null +++ b/HealthSync_FE/manifest/deployment/frontend-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: healthsync-front + namespace: team1tier-healthsync-front-ns + labels: + app: healthsync-front +spec: + revisionHistoryLimit: 3 + replicas: 1 + selector: + matchLabels: + app: healthsync-front + template: + metadata: + labels: + app: healthsync-front + spec: + imagePullSecrets: + - name: acr-secret + containers: + - name: healthsync-front + image: acrhealthsync01.azurecr.io/team1tier/healthsync-front:1.0.23 + imagePullPolicy: Always + ports: + - containerPort: 80 + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi + volumeMounts: + - name: runtime-config + mountPath: /usr/share/nginx/html/runtime-env.js + subPath: runtime-env.js + volumes: + - name: runtime-config + configMap: + name: frontend-config diff --git a/HealthSync_FE/manifest/ingress/frontend-ingress.yaml b/HealthSync_FE/manifest/ingress/frontend-ingress.yaml new file mode 100644 index 0000000..5ed0f57 --- /dev/null +++ b/HealthSync_FE/manifest/ingress/frontend-ingress.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: healthsync-frontend-ingress + namespace: team1tier-healthsync-front-ns + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/ssl-redirect: "false" +spec: + ingressClassName: nginx + rules: + - host: team1tier.20.214.196.128.nip.io + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: healthsync-front-service + port: + number: 80 diff --git a/HealthSync_FE/manifest/service/frontend-service.yaml b/HealthSync_FE/manifest/service/frontend-service.yaml new file mode 100644 index 0000000..836b1e9 --- /dev/null +++ b/HealthSync_FE/manifest/service/frontend-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: healthsync-front-service + namespace: team1tier-healthsync-front-ns + labels: + app: healthsync-front +spec: + type: LoadBalancer + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + app: healthsync-front diff --git a/HealthSync_Intelligence/kustomization.yaml.backup b/HealthSync_Intelligence/kustomization.yaml.backup new file mode 100644 index 0000000..2be442a --- /dev/null +++ b/HealthSync_Intelligence/kustomization.yaml.backup @@ -0,0 +1,52 @@ +# ================================================== +# deployment/manifest/kustomization.yaml +# ================================================== +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: team1tier-healthsync-intelligence-ns + +resources: + - configmap/intelligence-service-configmap.yaml + - secret/intelligence-service-secret.yaml + - deployment/intelligence-service-deployment.yaml + - service/intelligence-service-service.yaml + - hpa/intelligence-service-hpa.yaml + - ingress/intelligence-service-ingress.yaml + +# 이미지 자동 치환 (빌드 스크립트에서 설정) +images: + - name: intelligence-service + newName: acrhealthsync01.azurecr.io/team1tier/intelligence-service + newTag: "1.0.0" + +# 공통 라벨 +commonLabels: + app: intelligence-service + team: team1tier + environment: production + +# 네임스페이스 설정 +namespace: team1tier-healthsync-intelligence-ns + +# 변수 치환 (ConfigMap Generator 사용 가능) +configMapGenerator: +- name: build-info + literals: + - build.version=1.0.0 + - build.timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + +# Patch 설정 (환경별 설정 오버라이드) +patchesStrategicMerge: +- |- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: intelligence-service + namespace: team1tier-healthsync-intelligence-ns + spec: + template: + metadata: + annotations: + build.version: "1.0.0" + deployment.timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ") diff --git a/HealthSync_Intelligence/manifest/configmap/intelligence-service-configmap.yaml b/HealthSync_Intelligence/manifest/configmap/intelligence-service-configmap.yaml new file mode 100644 index 0000000..c073bb1 --- /dev/null +++ b/HealthSync_Intelligence/manifest/configmap/intelligence-service-configmap.yaml @@ -0,0 +1,51 @@ +# ================================================== +# deployment/manifest/configmap/intelligence-service-configmap.yaml +# ================================================== +apiVersion: v1 +kind: ConfigMap +metadata: + name: intelligence-service-configmap + namespace: team1tier-healthsync-intelligence-ns + labels: + app: intelligence-service + component: config +data: + # 서비스 기본 설정 + APP_NAME: "HealthSync Intelligence Service" + APP_VERSION: "1.0.0" + DEBUG: "false" + HOST: "0.0.0.0" + PORT: "8083" + API_V1_PREFIX: "/api/intelligence" + CORS_ORIGINS: '["*"]' + + # 로깅 설정 + LOG_LEVEL: "INFO" + + # 토큰 설정 + ALGORITHM: "HS256" + ACCESS_TOKEN_EXPIRE_MINUTES: "30" + + # Claude AI 설정 + CLAUDE_MODEL: "claude-3-5-sonnet-20241022" + CLAUDE_MAX_TOKENS: "1500" + CLAUDE_TEMPERATURE: "0.7" + CLAUDE_TIMEOUT: "30" + CLAUDE_API_BASE_URL: "https://api.anthropic.com" + + # 다른 마이크로서비스 URL + USER_SERVICE_URL: "http://user-service:8081" + HEALTH_SERVICE_URL: "http://health-service:8082" + + # Redis 설정 + REDIS_HOST: "redis-digitalgarage-01.redis.cache.windows.net" + REDIS_PORT: "6380" + REDIS_DB: "0" + REDIS_SSL: "true" + + # PostgreSQL 설정 + DB_HOST: "psql-digitalgarage-01.postgres.database.azure.com" + DB_PORT: "5432" + DB_NAME: "healthsync_db" + DB_MIN_SIZE: "1" + DB_MAX_SIZE: "10" diff --git a/HealthSync_Intelligence/manifest/deployment/intelligence-service-deployment.yaml b/HealthSync_Intelligence/manifest/deployment/intelligence-service-deployment.yaml new file mode 100644 index 0000000..71107b4 --- /dev/null +++ b/HealthSync_Intelligence/manifest/deployment/intelligence-service-deployment.yaml @@ -0,0 +1,168 @@ +# ================================================== +# deployment/manifest/deployment/intelligence-service-deployment.yaml +# ================================================== +apiVersion: apps/v1 +kind: Deployment +metadata: + name: intelligence-service + namespace: team1tier-healthsync-intelligence-ns + labels: + app: intelligence-service + component: backend + tier: api +spec: + revisionHistoryLimit: 3 + replicas: 2 + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + selector: + matchLabels: + app: intelligence-service + template: + metadata: + labels: + app: intelligence-service + component: backend + environment: production + team: team1tier + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8083" + prometheus.io/path: "/metrics" + spec: + # Image Pull Secret + imagePullSecrets: + - name: acr-secret + + # 보안 컨텍스트 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + + containers: + - name: intelligence-service + # 이미지는 Kustomize에서 자동으로 치환됨 + image: acrhealthsync01.azurecr.io/team1tier/intelligence-service:1.3.3 + imagePullPolicy: Always + + ports: + - name: http + containerPort: 8083 + protocol: TCP + + # 환경변수 설정 + envFrom: + - configMapRef: + name: intelligence-service-configmap + - secretRef: + name: intelligence-service-secret + + # 추가 환경변수 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + + # 리소스 제한 + resources: + requests: + cpu: "200m" + memory: "512Mi" + ephemeral-storage: "1Gi" + limits: + cpu: "1000m" + memory: "1Gi" + ephemeral-storage: "2Gi" + + # Startup Probe: 초기 시작 확인 (최대 3분 대기) + # startupProbe: + # httpGet: + # path: /api/v1/health/status + # port: http + # scheme: HTTP + # initialDelaySeconds: 30 + # periodSeconds: 10 + # timeoutSeconds: 5 + # failureThreshold: 18 # 30초 + (18 * 10초) = 최대 3분 + # successThreshold: 1 + + # Readiness Probe: 트래픽 수신 준비 확인 + # readinessProbe: + # httpGet: + # path: /api/v1/health/status + # port: http + # scheme: HTTP + # initialDelaySeconds: 5 + # periodSeconds: 5 + # timeoutSeconds: 3 + # failureThreshold: 3 + # successThreshold: 1 + + # Liveness Probe: 서비스 생존 확인 + # livenessProbe: + # httpGet: + # path: /api/v1/health/status + # port: http + # scheme: HTTP + # initialDelaySeconds: 60 + # periodSeconds: 10 + # timeoutSeconds: 5 + # failureThreshold: 3 + # successThreshold: 1 + + # 보안 컨텍스트 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 1000 + capabilities: + drop: + - ALL + + # 볼륨 마운트 (로그 수집용) + volumeMounts: + - name: tmp-volume + mountPath: /tmp + - name: cache-volume + mountPath: /app/cache + + # 볼륨 정의 + volumes: + - name: tmp-volume + emptyDir: {} + - name: cache-volume + emptyDir: {} + + # DNS 설정 + dnsPolicy: ClusterFirst + + # 재시작 정책 + restartPolicy: Always + + # 스케줄링 설정 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - intelligence-service + topologyKey: kubernetes.io/hostname diff --git a/HealthSync_Intelligence/manifest/hpa/intelligence-service-hpa.yaml b/HealthSync_Intelligence/manifest/hpa/intelligence-service-hpa.yaml new file mode 100644 index 0000000..10eb21c --- /dev/null +++ b/HealthSync_Intelligence/manifest/hpa/intelligence-service-hpa.yaml @@ -0,0 +1,44 @@ +# ================================================== +# deployment/manifest/hpa/intelligence-service-hpa.yaml +# ================================================== +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: intelligence-service-hpa + namespace: team1tier-healthsync-intelligence-ns + labels: + app: intelligence-service + component: autoscaler +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: intelligence-service + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 50 + periodSeconds: 60 + scaleUp: + stabilizationWindowSeconds: 60 + policies: + - type: Percent + value: 100 + periodSeconds: 30 diff --git a/HealthSync_Intelligence/manifest/ingress/intelligence-service-ingress.yaml b/HealthSync_Intelligence/manifest/ingress/intelligence-service-ingress.yaml new file mode 100644 index 0000000..9c30756 --- /dev/null +++ b/HealthSync_Intelligence/manifest/ingress/intelligence-service-ingress.yaml @@ -0,0 +1,32 @@ +# ================================================== +# deployment/manifest/ingress/intelligence-service-ingress.yaml +# ================================================== +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: intelligence-service-ingress + namespace: team1tier-healthsync-intelligence-ns + labels: + app: intelligence-service + component: ingress + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "false" + nginx.ingress.kubernetes.io/force-ssl-redirect: "false" + nginx.ingress.kubernetes.io/backend-protocol: "HTTP" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "30" + nginx.ingress.kubernetes.io/proxy-send-timeout: "30" + nginx.ingress.kubernetes.io/proxy-read-timeout: "30" + nginx.ingress.kubernetes.io/proxy-body-size: "10m" +spec: + ingressClassName: nginx + rules: + - host: team1tier.20.214.196.128.nip.io # 실제 환경에서는 실제 도메인으로 변경 + http: + paths: + - path: /api/intelligence + pathType: Prefix + backend: + service: + name: intelligence-service + port: + number: 8083 diff --git a/HealthSync_Intelligence/manifest/secret/intelligence-service-secret.yaml b/HealthSync_Intelligence/manifest/secret/intelligence-service-secret.yaml new file mode 100644 index 0000000..520f407 --- /dev/null +++ b/HealthSync_Intelligence/manifest/secret/intelligence-service-secret.yaml @@ -0,0 +1,29 @@ +# ================================================== +# deployment/manifest/secret/intelligence-service-secret.yaml +# ================================================== +apiVersion: v1 +kind: Secret +metadata: + name: intelligence-service-secret + namespace: team1tier-healthsync-intelligence-ns + labels: + app: intelligence-service + component: secret +type: Opaque +stringData: + # JWT 보안키 (openssl rand -base64 32로 생성) + SECRET_KEY: "aHVlYWx0aHN5bmMtaW50ZWxsaWdlbmNlLXNlY3JldC1rZXktMjAyNQ==" + + # Claude API 키 (실제 환경에서는 Azure Key Vault 연동 권장) + CLAUDE_API_KEY: "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" + + # 데이터베이스 접속 정보 + DB_USERNAME: "team1tier" + DB_PASSWORD: "Hi5Jessica!" + + # Redis 접속 정보 + REDIS_PASSWORD: "HUezXQsxbphIeBy8FV9JDA3WaZDwOozGEAzCaByUk40=" + + # PineCone + PINECONE_API_KEY: "pcsk_2bcssc_wVP3hmKVfo8We9Cd4mdo2PM5s4Ab7hPahxWmyG1v6AbpEhXPKuNjK2qKb9KbJJ" + PINECONE_ENVIRONMENT: "aped-4627-b74a" diff --git a/HealthSync_Intelligence/manifest/service/intelligence-service-service.yaml b/HealthSync_Intelligence/manifest/service/intelligence-service-service.yaml new file mode 100644 index 0000000..0daef69 --- /dev/null +++ b/HealthSync_Intelligence/manifest/service/intelligence-service-service.yaml @@ -0,0 +1,26 @@ +# ================================================== +# deployment/manifest/service/intelligence-service-service.yaml +# ================================================== +apiVersion: v1 +kind: Service +metadata: + name: intelligence-service + namespace: team1tier-healthsync-intelligence-ns + labels: + app: intelligence-service + component: backend + tier: api + annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "false" +spec: + type: ClusterIP + sessionAffinity: None + ports: + - name: http + port: 8083 + targetPort: http + protocol: TCP + selector: + app: intelligence-service + component: backend + diff --git a/HealthSync_Motivator/manifest/configmap/motivator-configmap.yaml b/HealthSync_Motivator/manifest/configmap/motivator-configmap.yaml new file mode 100644 index 0000000..ae796aa --- /dev/null +++ b/HealthSync_Motivator/manifest/configmap/motivator-configmap.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: motivator-config + namespace: team1tier-healthsync-motivator-ns +data: + # Application Settings + APP_NAME: "HealthSync Motivator Batch" + APP_VERSION: "1.0.0" + DEBUG: "false" + LOG_LEVEL: "INFO" + + # Database Configuration + DB_HOST: "psql-digitalgarage-01.postgres.database.azure.com" + DB_PORT: "5432" + DB_NAME: "healthsync_db" + DB_USERNAME: "team1tier" + + # Claude AI Configuration + CLAUDE_MODEL: "claude-3-5-sonnet-20241022" + CLAUDE_MAX_TOKENS: "150" + CLAUDE_TEMPERATURE: "0.7" + CLAUDE_TIMEOUT: "30" + + # Batch Configuration + BATCH_SIZE: "100" + MAX_RETRIES: "3" + + # Azure Service Bus Configuration + AZURE_SERVICEBUS_NAMESPACE: "sb-healthsync.servicebus.windows.net" + AZURE_SERVICEBUS_QUEUE_NAME: "healthsync-notifications" diff --git a/HealthSync_Motivator/manifest/cronjob/motivator-cronjob.yaml b/HealthSync_Motivator/manifest/cronjob/motivator-cronjob.yaml new file mode 100644 index 0000000..b97daec --- /dev/null +++ b/HealthSync_Motivator/manifest/cronjob/motivator-cronjob.yaml @@ -0,0 +1,48 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: healthsync-motivator-batch + namespace: team1tier-healthsync-motivator-ns + labels: + app: healthsync-motivator + type: batch +spec: + # 10분마다 실행 + schedule: "0 */10 * * *" + timeZone: "Asia/Seoul" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + template: + metadata: + labels: + app: healthsync-motivator-batch + spec: + imagePullSecrets: + - name: acr-secret + restartPolicy: OnFailure + containers: + - name: motivator-batch + image: acrhealthsync01.azurecr.io/team1tier/motivator-service:1.1.1 + imagePullPolicy: Always + command: ["python", "app/batch_runner.py"] + envFrom: + - configMapRef: + name: motivator-config + - secretRef: + name: motivator-secret + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi + # 배치 실행 타임아웃 설정 + env: + - name: PYTHONPATH + value: "/app" + - name: PYTHONUNBUFFERED + value: "1" diff --git a/HealthSync_Motivator/manifest/secret/motivator-secret.yaml b/HealthSync_Motivator/manifest/secret/motivator-secret.yaml new file mode 100644 index 0000000..84f1a1e --- /dev/null +++ b/HealthSync_Motivator/manifest/secret/motivator-secret.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: + name: motivator-secret + namespace: team1tier-healthsync-motivator-ns +type: Opaque +stringData: + # Database Password + DB_PASSWORD: "Hi5Jessica!" + + # Claude AI API Key (실제 키로 교체 필요) + CLAUDE_API_KEY: "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" + + # Azure Service Bus Connection String (실제 연결 문자열로 교체 필요) + AZURE_SERVICEBUS_CONNECTION_STRING: "Endpoint=sb://sb-healthsync.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Zur5rLIi8MNQ8sk3T/TvsdVu+i02bbxaE+ASbCAXvZI=" diff --git a/HealthSync_Motivator/test-job.yaml b/HealthSync_Motivator/test-job.yaml new file mode 100644 index 0000000..91da1ab --- /dev/null +++ b/HealthSync_Motivator/test-job.yaml @@ -0,0 +1,39 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: healthsync-motivator-manual + namespace: team1tier-healthsync-motivator-ns + labels: + app: healthsync-motivator + type: manual +spec: + template: + metadata: + labels: + app: healthsync-motivator-manual + spec: + imagePullSecrets: + - name: acr-secret + restartPolicy: Never + containers: + - name: motivator-batch + image: acrhealthsync01.azurecr.io/team1tier/motivator-service:1.1.1 + imagePullPolicy: Always + command: ["python", "app/batch_runner.py"] + envFrom: + - configMapRef: + name: motivator-config + - secretRef: + name: motivator-secret + resources: + requests: + cpu: 256m + memory: 256Mi + limits: + cpu: 1024m + memory: 1024Mi + env: + - name: PYTHONPATH + value: "/app" + - name: PYTHONUNBUFFERED + value: "1" diff --git a/README.md b/README.md new file mode 100644 index 0000000..dcff40b --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# HealthSync_Manifest +ArgoCD용 Manifest 파일입니다.