# 백엔드 배포 가이드 [요청사항] - 백엔드 서비스를 쿠버네티스에 배포하기 위한 매니페스트 파일 작성 - 매니페스트 파일 작성까지만 하고 실제 배포는 수행방법만 가이드 - '[결과파일]'에 수행한 명령어를 포함하여 배포 가이드 레포트 생성 [작업순서] - 실행정보 확인 프롬프트의 '[실행정보]'섹션에서 아래정보를 확인 - {ACR명}: 컨테이너 레지스트리 이름 - {k8s명}: Kubernetes 클러스터 이름 - {네임스페이스}: 배포할 네임스페이스 - {파드수}: 생성할 파드수 - {리소스(CPU)}: 요청값/최대값 - {리소스(메모리)}: 요청값/최대값 예시) ``` [실행정보] - ACR명: acrdigitalgarage01 - k8s명: aks-digitalgarage-01 - 네임스페이스: tripgen - 파드수: 2 - 리소스(CPU): 256m/1024m - 리소스(메모리): 256Mi/1024Mi ``` - 시스템명과 서비스명 확인 settings.gradle에서 확인. - 시스템명: rootProject.name - 서비스명: include 'common'하위의 include문 뒤의 값임 예시) include 'common'하위의 4개가 서비스명임. ``` rootProject.name = 'tripgen' include 'common' include 'user-service' include 'location-service' include 'ai-service' include 'trip-service' ``` - 매니페스트 작성 주의사항 - namespace는 명시: {네임스페이스}값 이용 - Database와 Redis의 Host명은 Service 객체 이름으로 함 - 공통 Secret의 JWT_SECRET 값은 반드시 openssl명령으로 생성하여 지정 - 매니페스트 파일 안에 환경변수를 사용하지 말고 실제 값을 지정 예) host: "tripgen.${INGRESS_IP}.nip.io" => host: "tripgen.4.1.2.3.nip.io" - Secret 매니페스트에서 'data' 대신 'stringData'를 사용 - 객체이름 네이밍룰 - 공통 ConfigMap: cm-common - 공통 Secret: secret-common - 서비스별 ConfigMap: cm-{서비스명} - 서비스별 Secret: secret-{서비스명} - Ingress: {시스템명} - Service: {서비스명} - Deployment: {서비스명} - 공통 매니페스트 작성: deployment/k8s/common/ 디렉토리 하위에 작성 - Image Pull Secret 매니페스트 작성: secret-imagepull.yaml - name: {시스템명} - USERNAME과 PASSWORD을 아래 명령으로 구하여 매니페스트 파일 작성 ``` USERNAME=$(az acr credential show -n ${ACR명} --query "username" -o tsv) PASSWORD=$(az acr credential show -n ${ACR명} --query "passwords[0].value" -o tsv) ``` - USERNAME과 PASSWORD의 실제 값을 매니페스트에 지정 - Ingress 매니페스트 작성: ingress.yaml - **중요**: Ingress Host는 반드시 아래 명령으로 실제 External IP를 확인하여 사용할 것. {Ingress External IP}는 실제 확인한 EXTERNAL-IP값. ``` kubectl get svc ingress-nginx-controller -n ingress-nginx ``` 출력 예시: EXTERNAL-IP 컬럼에서 실제 IP 확인 (예:20.214.196.128) - ingressClassName: nginx - host: {시스템명}-api.{Ingress External IP}.nip.io **잘못된 예**: tripgen-api.임의IP.nip.io ❌ **올바른 예**: tripgen-api.20.214.196.128.nip.io ✅ - path: 각 서비스 별 Controller 클래스의 '@RequestMapping'과 클래스 내 메소드의 매핑정보를 읽어 지정 - pathType: Prefix - backend.service.name: {서비스명} - backend.service.port.number: 80 - **중요**: annotation에 'nginx.ingress.kubernetes.io/rewrite-target' 설정 절대 하지 말것. - 공통 ConfigMap과 Secret 매니페스트 작성 - 각 서비스의 실행 프로파일({서비스명}/.run/{서비스명}.run.xml)을 읽어 공통된 환경변수를 추출. - 보안이 필요한 환경변수(암호, 인증토큰 등)는 Secret 매니페스트로 작성: secret-common.yaml(name:cm-common) - 그 외 일반 환경변수 매니페스트 작성: cm-common.yaml(name:secret-common) - Redis HOST명은 IP가 아닌 Service 객체명으로 함. 아래 명령으로 'redis'가 포함된 서비스 객체를 찾고 'ClusterIP'유형인 서비스명을 Host명으로 사용 ``` kubectl get svc | grep redis ``` - REDIS_DATABASE는 각 서비스별 ConfigMap에 지정 - 주의) Database는 공통 ConfigMap/Secret으로 작성 금지 - 공통 ConfigMap에 CORS_ALLOWED_ORIGINS 설정: 'http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://{시스템명}.{Ingress External IP}.nip.io' - 서비스별 매니페스트 작성: deployment/k8s/{서비스명}/ 디렉토리 하위에 작성 - ConfigMap과 Secret 매니페스트 작성 - 각 서비스의 실행 프로파일({서비스명}/.run/{서비스명}.run.xml)을 읽어 환경변수를 추출. - cm-common.yaml과 secret-common.yaml에 있는 공통 환경변수는 중복해서 작성하면 안됨 - 보안이 필요한 환경변수(암호, 인증토큰 등)는 Secret 매니페스트로 작성: secret-{서비스명}.yaml(name:cm-{서비스명}) - 그 외 일반 환경변수 매니페스트 작성: cm-{서비스명}.yaml(name:secret-{서비스명}) - Database HOST명은 IP가 아닌 Service 객체명으로 함. 아래 명령으로 '{서비스명}'과 'db'가 포함된 서비스 객체를 찾고 'ClusterIP'유형인 서비스명을 Host명으로 사용 ``` kubectl get svc | grep {서비스명} ``` - REDIS_DATABASE는 실행 프로파일에 지정된 값으로 서비스별 ConfigMap에 지정 - Service 매니페스트 작성 - name: {서비스명} - port: 80 - targetPort: 실행 프로파일의 SERVER_PORT값 - type: ClusterIP - Deployment 매니페스트 작성 - name: {서비스명} - replicas: {파드수} - ImagePullPolicy: Always - ImagePullSecrets: {시스템명} - image: {ACR명}.azurecr.io/{시스템명}/{서비스명}:latest - ConfigMap과 Secret은 'env'대신에 'envFrom'을 사용하여 지정 - envFrom: - configMapRef: 공통 ConfigMap 'cm-common'과 각 서비스 ConfigMap 'cm-{서비스명}'을 지정 - secretRef: 공통 Secret 'secret-common'과 각 서비스 Secret 'secret-{서비스명}'을 지정 - resources: - {리소스(CPU)}: 요청값/최대값 - {리소스(메모리)}: 요청값/최대값 - Probe: - Startup Probe: Actuator '/actuator/health'로 지정 - Readiness Probe: Actuator '/actuator/health/rediness'로 지정 - Liveness Probe: Actuator '/actuator/health/liveness'로 지정 - initialDelaySeconds, periodSeconds, failureThreshold를 Probe에 맞게 적절히 지정 - 체크 리스트로 수행결과 검증: 반드시 수행하고 그 결과를 배포 가이드에 포함 - 객체이름 네이밍룰 준수 여부 - Redis Host명을 ClusterIP 타입의 Service 객체로 했는가? 'kubectl get svc | grep redis' 명령으로 재확인 - Database Host명을 ClusterIP타입의 Service 객체로 했는가? 'kubectl get svc | grep {서비스명}' 명령으로 재확인 - Secret 매니페스트에서 'data' 대신 'stringData'를 사용 했는가? - JWT_SECRET을 openssl 명령으로 생성해서 지정했는가? - 매니페스트 파일 안에 환경변수를 사용하지 않고 실제 값을 지정 했는가? - Image Pull Secret에 USERNAME과 PASSWORD의 실제 값을 매니페스트에 지정 했는가? - Image명이 '{ACR명}.azurecr.io/{시스템명}/{서비스명}:latest' 형식인지 재확인 - Ingress Controller External IP 확인 및 매니페스트에 반영 확인 kubectl get svc ingress-nginx-controller -n ingress-nginx EXTERNAL-IP 컬럼의 실제 값이 ingress.yaml의 host에 정확하게 설정되었는지 재확인할 것 - Ingress 매니페스트의 각 서비스 backend.service.port.number와 Service 매니페스트의 port가 "80"으로 동일한가 ? - Ingress의 path는 각 서비스 별 Controller 클래스의 '@RequestMapping'과 클래스 내 메소드의 매핑정보를 읽어 지정했는가? - 보안이 필요한 환경변수는 Secret 매니페스트로 지정했는가? - REDIS_DATABASE는 각 서비스마다 다르게 지정했는가? - ConfigMap과 Secret은 'env'대신에 'envFrom'을 사용하였는가? - (중요) 실행 프로파일 매핑 테이블로 누락된 환경변수 체크 - **필수**: 각 서비스의 실행 프로파일({서비스명}/.run/{서비스명}.run.xml)에 정의된 **전체 환경변수를 빠짐없이 체크** - **체크 방법**: 1. 각 {서비스명}.run.xml 파일에서 `` 형태로 정의된 **모든** 환경변수 추출 2. 추출된 환경변수 **전체**를 대상으로 매핑 테이블 작성 (일부만 하면 안됨) 3. 서비스명 | 환경변수 | 지정 객체명 | 환경변수값 컬럼으로 **전체 환경변수** 체크 - **매핑 테이블 예시** (전체 환경변수 기준): ``` user-service | SERVER_PORT | cm-user-service | 8081 user-service | DB_HOST | secret-user-service | user-db-service user-service | DB_PASSWORD | secret-user-service | tripgen_user_123 user-service | REDIS_DATABASE | cm-user-service | 0 user-service | JWT_SECRET | secret-common | (base64 encoded) user-service | CACHE_TTL | cm-user-service | 1800 location-service | SERVER_PORT | cm-location-service | 8082 location-service | GOOGLE_API_KEY | secret-location-service | (base64 encoded) location-service | REDIS_DATABASE | cm-location-service | 1 ai-service | CLAUDE_API_KEY | secret-ai-service | (base64 encoded) ai-service | SERVER_PORT | cm-ai-service | 8084 ... (실행프로파일의 모든 환경변수 나열) ``` - **주의**: 일부 환경변수만 체크하면 누락 발생, 반드시 **실행프로파일 전체** 환경변수 대상으로 수행 - 누락된 환경변수가 발견되면 해당 ConfigMap/Secret에 추가 - 배포 가이드 작성 - 배포가이드 검증 결과 - 사전확인 방법 가이드 - Azure 로그인 상태 확인 ``` az account show ``` - AKS Credential 확인: ``` kubectl cluster-info ``` - namespace 존재 확인 ``` kubectl get ns {네임스페이스} ``` - 매니페스트 적용 가이드 ``` kubectl apply -f deployment/k8s/common kubectl apply -f deployment/k8s/{서비스명} ``` - 객체 생성 확인 가이드 [결과파일] - 배포방법 가이드: deployment/k8s/deploy-k8s-guide.md - 공통 매니페스트 파일: deployment/k8s/common/* - 서비스별 매니페스트 파일: deployment/k8s/{서비스명}/*