diff --git a/Dockerfile_server b/Dockerfile_server index b556442..0d5e2f8 100644 --- a/Dockerfile_server +++ b/Dockerfile_server @@ -1,10 +1,10 @@ -FROM openjdk:17-jdk-alpine -MAINTAINER [AutoFlow] - -RUN apk --no-cache add tzdata && cp /usr/share/zoneinfo/Asia/Seoul /etc/localtime - -RUN mkdir /server -ADD build/libs/autoflow-0.0.1-SNAPSHOT.jar /server/autoflow-0.0.1-SNAPSHOT.jar - -WORKDIR /server -ENTRYPOINT ["java", "-jar", "autoflow-0.0.1-SNAPSHOT.jar"] \ No newline at end of file +FROM openjdk:17-jdk-alpine +MAINTAINER [AutoFlow] + +RUN apk --no-cache add tzdata && cp /usr/share/zoneinfo/Asia/Seoul /etc/localtime + +RUN mkdir /server +COPY build/libs/*.jar /server/app.jar + +WORKDIR /server +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/kubernetes-aws.yaml b/kubernetes-aws.yaml index c74033e..8a96919 100644 --- a/kubernetes-aws.yaml +++ b/kubernetes-aws.yaml @@ -2,7 +2,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: autoflow-server - namespace: autoflow + namespace: etri spec: replicas: 1 selector: @@ -13,17 +13,16 @@ spec: labels: app: autoflow-server spec: + nodeSelector: + nodegroup: cpu containers: - name: autoflow-server - # [수정] 외부 레지스트리 주소를 제거하고 로컬 태그만 사용 image: autoflow-server:latest - # [추가] 외부에서 이미지를 다운로드하지 않고 로컬 이미지를 사용하도록 강제 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 env: - name: RDS_HOSTNAME - # [수정 필요] Outpost 내부 RDS의 Private IP 또는 DNS를 입력하세요. value: "INTERNAL_RDS_IP_HERE" - name: RDS_USERNAME value: "admin" @@ -38,8 +37,19 @@ spec: name: autoflow-secrets key: jwt-secret - name: S3_BUCKET_NAME - # [수정 필요] Outpost 내 생성한 S3 버킷 명을 입력하세요. value: "autoflow-outpost-bucket" + livenessProbe: + httpGet: + path: /autoflow-server-mgmt/actuator/health + port: 8080 + initialDelaySeconds: 60 + periodSeconds: 15 + readinessProbe: + httpGet: + path: /autoflow-server-mgmt/actuator/health + port: 8080 + initialDelaySeconds: 60 + periodSeconds: 15 volumeMounts: - name: storage-volume mountPath: /app/storage @@ -52,10 +62,11 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: autoflow-storage-pvc - namespace: autoflow + namespace: etri spec: accessModes: - ReadWriteOnce + storageClassName: gp2 resources: requests: storage: 10Gi @@ -64,13 +75,45 @@ apiVersion: v1 kind: Service metadata: name: autoflow-server-svc - namespace: autoflow + namespace: etri spec: - # Outpost EKS 환경에 따라 LoadBalancer 또는 NodePort를 선택하세요. - type: LoadBalancer selector: app: autoflow-server ports: - protocol: TCP port: 80 targetPort: 8080 + type: ClusterIP +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: autoflow-server-ingress + namespace: etri + annotations: + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/backend-protocol: HTTP + # [수정 필요] 실제 서브넷 ID 및 보안 그룹 ID 입력 필요 + alb.ingress.kubernetes.io/subnets: subnet-xxxx, subnet-yyyy + alb.ingress.kubernetes.io/group.name: etri-group + alb.ingress.kubernetes.io/security-groups: sg-xxxx + alb.ingress.kubernetes.io/customer-owned-ipv4-pool: ipv4pool-xxxx + alb.ingress.kubernetes.io/healthcheck-protocol: HTTP + alb.ingress.kubernetes.io/healthcheck-path: /autoflow-server-mgmt/actuator/health + alb.ingress.kubernetes.io/healthcheck-interval-seconds: "15" + alb.ingress.kubernetes.io/healthy-threshold-count: "2" + alb.ingress.kubernetes.io/unhealthy-threshold-count: "3" + alb.ingress.kubernetes.io/success-codes: "200" +spec: + ingressClassName: alb + rules: + - http: + paths: + - path: /autoflow-server-mgmt + pathType: Prefix + backend: + service: + name: autoflow-server-svc + port: + number: 80 diff --git a/src/main/java/kr/re/etri/autoflow/controller/StorageTestController.java b/src/main/java/kr/re/etri/autoflow/controller/StorageTestController.java new file mode 100644 index 0000000..c76467f --- /dev/null +++ b/src/main/java/kr/re/etri/autoflow/controller/StorageTestController.java @@ -0,0 +1,47 @@ +package kr.re.etri.autoflow.controller; + +import kr.re.etri.autoflow.service.storage.StorageProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/test/storage") +@RequiredArgsConstructor +public class StorageTestController { + + private final StorageProvider storageProvider; + + @GetMapping("/info") + public ResponseEntity> getInfo() { + Map info = new HashMap<>(); + info.put("providerClass", storageProvider.getClass().getSimpleName()); + return ResponseEntity.ok(info); + } + + @PostMapping("/upload") + public ResponseEntity testUpload(@RequestParam("file") MultipartFile file) { + try (InputStream is = file.getInputStream()) { + String objectName = "test/" + file.getOriginalFilename(); + storageProvider.uploadFileToDefault(objectName, is, file.getContentType(), file.getSize()); + return ResponseEntity.ok("Upload successful: " + objectName); + } catch (Exception e) { + return ResponseEntity.internalServerError().body("Upload failed: " + e.getMessage()); + } + } + + @GetMapping("/url") + public ResponseEntity getUrl(@RequestParam("name") String name) { + try { + String url = storageProvider.getFileUrl(null, name, null); + return ResponseEntity.ok(url); + } catch (Exception e) { + return ResponseEntity.internalServerError().body("Failed to get URL: " + e.getMessage()); + } + } +} diff --git a/src/main/java/kr/re/etri/autoflow/security/WebSecurityConfig.java b/src/main/java/kr/re/etri/autoflow/security/WebSecurityConfig.java index 6f79fd6..29492f6 100644 --- a/src/main/java/kr/re/etri/autoflow/security/WebSecurityConfig.java +++ b/src/main/java/kr/re/etri/autoflow/security/WebSecurityConfig.java @@ -110,9 +110,11 @@ public class WebSecurityConfig { // extends WebSecurityConfigurerAdapter { .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> - auth.anyRequest().permitAll() // 모든 요청 허용 + auth.requestMatchers("/actuator/**").permitAll() // Actuator endpoints + .anyRequest().permitAll() // 모든 요청 허용 ); + http.authenticationProvider(authenticationProvider()); http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 98e6c66..13eee16 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,88 +1,93 @@ -#????? ?? ?? -server.port = 8080 - -spring.profiles.active=local - -spring.datasource.url=jdbc:mariadb://192.168.10.143:3306/autoflow -spring.datasource.driver-class-name=org.mariadb.jdbc.Driver -spring.datasource.username=cuuva -spring.datasource.password=cuuva - -spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect - -spring.jpa.defer-datasource-initialization=true - -#spring.batch.jdbc.schema=classpath:org/springframework/batch/core/schema-mariadb.sql -#spring.batch.jdbc.initialize-schema=always - -# App Properties -cuuva.app.jwtCookieName=cuuva-jwt -cuuva.app.jwtRefreshCookieName=cuuva-jwt-refresh -cuuva.app.jwtSecret= 275511b31c520562d69802ce4a913773102563891563a24062f44b3f312ca2bd034440e81836d1b4ccf4195f43db4c81a4e489a41f1ae0967afe468c9a361f4d - -## For test -cuuva.app.jwtExpirationMs= 900000 -cuuva.app.jwtRefreshExpirationMs= 8640000 - -spring.jpa.show-sql=true - -spring.jpa.properties.hibernate.format_sql=true - -logging.level.org.hibernate.type.descriptor.sql=TRACE - -logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE - -spring.datasource.hikari.connection-timeout=30000 -spring.datasource.hikari.idle-timeout=60000 -spring.datasource.hikari.max-lifetime=1800000 - -springdoc.api-docs.enabled=true -springdoc.api-docs.path=/v3/api-docs - -springdoc.swagger-ui.path=/swagger-ui -springdoc.swagger-ui.config-url=/autoflow-server-mgmt/v3/api-docs/swagger-config -springdoc.swagger-ui.url=/autoflow-server-mgmt/v3/api-docs -springdoc.swagger-ui.doc-expansion=none -springdoc.swagger-ui.disable-swagger-default-url=true - -spring.servlet.multipart.max-file-size=500MB -spring.servlet.multipart.max-request-size=500MB - -springdoc.swagger-ui.tags-sorter=alpha - -# Storage Provider (minio, s3, or filesystem) -storage.provider=minio - -# Local FileSystem ?? -storage.local.base-path=/app/storage -storage.local.default-bucket=mlpipeline - -# MinIO ?? -minio.endpoint=http://192.168.10.135:31795 -minio.access-key=minio -minio.secret-key=minio123 -minio.bucket=mlpipeline - -# Kubeflow -kubeflow.url=http://192.168.10.135:32473/ - -# MLflow -mlflow.url=http://192.168.10.135:30128/ -mlflow.user=user -mlflow.password=WjWjIi13KEkO - -server.servlet.encoding.charset=UTF-8 -server.servlet.encoding.enabled=true -server.servlet.encoding.force=true - -spring.servlet.multipart.enabled=true - -#OTA?? -external.auth.signin-url=https://a659120d3e2ff43ff94087b29396fd96-1057696791.ap-northeast-2.elb.amazonaws.com/api/datamanager/user/signin -external.auth.edge-search-url=https://a659120d3e2ff43ff94087b29396fd96-1057696791.ap-northeast-2.elb.amazonaws.com/api/datamanager/edge-pkg/search -external.auth.sw-search-url=https://a659120d3e2ff43ff94087b29396fd96-1057696791.ap-northeast-2.elb.amazonaws.com/api/datamanager/advehicle-pkg/search - -cloud.aws.region.static=ap-northeast-2 -cloud.aws.credentials.access-key=AKIA2UC3EPERDDR4UOWN -cloud.aws.credentials.secret-key=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 -cloud.aws.s3.bucket=mlpipeline \ No newline at end of file +#????? ?? ?? +server.port = 8080 + +spring.profiles.active=local + +spring.datasource.url=jdbc:mariadb://192.168.10.143:3306/autoflow +spring.datasource.driver-class-name=org.mariadb.jdbc.Driver +spring.datasource.username=cuuva +spring.datasource.password=cuuva + +spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect + +spring.jpa.defer-datasource-initialization=true + +#spring.batch.jdbc.schema=classpath:org/springframework/batch/core/schema-mariadb.sql +#spring.batch.jdbc.initialize-schema=always + +# App Properties +cuuva.app.jwtCookieName=cuuva-jwt +cuuva.app.jwtRefreshCookieName=cuuva-jwt-refresh +cuuva.app.jwtSecret= 275511b31c520562d69802ce4a913773102563891563a24062f44b3f312ca2bd034440e81836d1b4ccf4195f43db4c81a4e489a41f1ae0967afe468c9a361f4d + +## For test +cuuva.app.jwtExpirationMs= 900000 +cuuva.app.jwtRefreshExpirationMs= 8640000 + +spring.jpa.show-sql=true + +spring.jpa.properties.hibernate.format_sql=true + +logging.level.org.hibernate.type.descriptor.sql=TRACE + +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE + +spring.datasource.hikari.connection-timeout=30000 +spring.datasource.hikari.idle-timeout=60000 +spring.datasource.hikari.max-lifetime=1800000 + +springdoc.api-docs.enabled=true +springdoc.api-docs.path=/v3/api-docs + +springdoc.swagger-ui.path=/swagger-ui +springdoc.swagger-ui.config-url=/autoflow-server-mgmt/v3/api-docs/swagger-config +springdoc.swagger-ui.url=/autoflow-server-mgmt/v3/api-docs +springdoc.swagger-ui.doc-expansion=none +springdoc.swagger-ui.disable-swagger-default-url=true + +spring.servlet.multipart.max-file-size=500MB +spring.servlet.multipart.max-request-size=500MB + +springdoc.swagger-ui.tags-sorter=alpha + +# Storage Provider (minio, s3, or filesystem) +storage.provider=minio + +# Local FileSystem ?? +storage.local.base-path=/app/storage +storage.local.default-bucket=mlpipeline + +# MinIO ?? +minio.endpoint=http://192.168.10.135:31795 +minio.access-key=minio +minio.secret-key=minio123 +minio.bucket=mlpipeline + +# Kubeflow +kubeflow.url=http://192.168.10.135:32473/ + +# MLflow +mlflow.url=http://192.168.10.135:30128/ +mlflow.user=user +mlflow.password=WjWjIi13KEkO + +server.servlet.encoding.charset=UTF-8 +server.servlet.encoding.enabled=true +server.servlet.encoding.force=true + +spring.servlet.multipart.enabled=true + +#OTA?? +external.auth.signin-url=https://a659120d3e2ff43ff94087b29396fd96-1057696791.ap-northeast-2.elb.amazonaws.com/api/datamanager/user/signin +external.auth.edge-search-url=https://a659120d3e2ff43ff94087b29396fd96-1057696791.ap-northeast-2.elb.amazonaws.com/api/datamanager/edge-pkg/search +external.auth.sw-search-url=https://a659120d3e2ff43ff94087b29396fd96-1057696791.ap-northeast-2.elb.amazonaws.com/api/datamanager/advehicle-pkg/search + +cloud.aws.region.static=ap-northeast-2 +cloud.aws.credentials.access-key=AKIA2UC3EPERDDR4UOWN +cloud.aws.credentials.secret-key=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 +cloud.aws.s3.bucket=mlpipeline + +# Spring Actuator Configuration +management.endpoints.web.exposure.include=health +management.endpoint.health.show-details=always +management.health.defaults.enabled=true \ No newline at end of file