Compare commits

...

10 Commits

Author SHA1 Message Date
hiondal
58434ff276 migration 2025-06-24 12:32:11 +07:00
hiondal
650e5e6c81 release 2025-06-19 09:59:32 +09:00
hiondal
7de30c4b3a release 2025-06-19 09:58:49 +09:00
Ubuntu
73f282e40c release 2025-05-30 02:03:55 +00:00
Ubuntu
34335abc92 add CI/CD files 2025-05-29 02:22:44 +00:00
Ubuntu
647dd96b47 release 2025-05-28 13:23:34 +00:00
Ubuntu
f3a6d06577 Add CI/CD 2025-05-28 13:02:57 +00:00
Ubuntu
b60030173b release 2025-05-28 07:41:53 +00:00
Ubuntu
27af87cf7e release 2025-05-27 02:17:35 +00:00
Ubuntu
c6fb780653 release 2025-05-27 02:16:46 +00:00
11 changed files with 263 additions and 277 deletions

15
.dockerignore Normal file
View File

@ -0,0 +1,15 @@
images
node_modules
npm-debug.log
build
.git
.github
coverage
.env*
.cache
dist
logs
**/*.log
**/.DS_Store

219
README.md
View File

@ -1,8 +1,8 @@
# 마이구독 서비스 (LifeSub) # 마이구독 서비스 (LifeSub)
## 1. 소개 ## 1. 소개
마이구독은 다양한, 증가하는 생활 구독 서비스를 한 곳에서 편리하게 관리할 수 있는 애플리케이션입니다. 사용자가 구독 중인 서비스를 한눈에 확인하고, 월별 구독료를 관리하며, 새로운 구독 서비스를 추천받을 수 있습니다. 마이구독은 다양한, 증가하는 생활 구독 서비스를 한 곳에서 편리하게 관리할 수 있는 애플리케이션입니다.
사용자가 구독 중인 서비스를 한눈에 확인하고, 월별 구독료를 관리하며, 새로운 구독 서비스를 추천받을 수 있습니다.
### 1.1 핵심 기능 ### 1.1 핵심 기능
- **구독 관리**: 다양한 구독 서비스를 한 곳에서 관리 - **구독 관리**: 다양한 구독 서비스를 한 곳에서 관리
@ -40,116 +40,8 @@
- **Message Queue**: RabbitMQ - **Message Queue**: RabbitMQ
- **기타**: Redis - **기타**: Redis
## 3. 프론트엔드 (lifesub-web) ## 3. 백킹 서비스 설치
1. Database 설치
### 3.1 주요 화면
- **로그인 화면**: 사용자 인증
- **메인 대시보드**: 월별 구독료 및 구독 서비스 목록, 추천 카테고리 표시
- **구독 서비스 목록**: 카테고리별 구독 서비스 브라우징
- **구독 상세**: 구독 서비스 상세 정보 및 구독/취소 기능
### 3.2 API 연동
애플리케이션은 다음 백엔드 서비스와 API를 통해 통신합니다:
- `MEMBER_URL`: 인증 관련 API
- `MYSUB_URL`: 구독 관리 관련 API
- `RECOMMEND_URL`: 추천 관련 API
## 4. 백엔드 서비스
### 4.1 인증 서비스 (Member)
회원 로그인 및 로그아웃, JWT 토큰 관리를 담당합니다.
#### 4.1.1 주요 API
- `POST /login`: 로그인
- `POST /logout`: 로그아웃
### 4.2 구독 서비스 (MySub)
사용자의 구독 정보 관리 및 카테고리 관리를 담당합니다.
#### 4.2.1 주요 API
- `GET /total-fee`: 총 구독료 조회
- `GET /list`: 사용자 구독 목록 조회
- `GET /services/{id}`: 구독 서비스 상세 조회
- `POST /services/{id}/subscribe`: 구독 신청
- `DELETE /services/{id}`: 구독 취소
- `GET /categories`: 카테고리 목록 조회
- `GET /services`: 카테고리별 서비스 조회
### 4.3 추천 서비스 (Recommend)
사용자의 지출 패턴 기반 구독 서비스를 추천합니다.
#### 4.3.1 주요 API
- `GET /categories`: 추천 카테고리 조회
## 5. 개발 환경 설정
### 5.1 필수 요구사항
- Java 21 (백엔드)
- Node.js 20.x (프론트엔드)
- Docker 또는 Podman
- kubectl (Kubernetes CLI)
- Gradle (백엔드 빌드)
### 5.2 프론트엔드 개발 환경 설정
1. 저장소 클론
```bash
git clone https://github.com/your-org/lifesub-web.git
cd lifesub-web
```
2. 의존성 설치
```bash
npm install
```
3. 개발 서버 실행
```bash
npm start
```
4. 환경 설정
프로젝트에서는 `public/runtime-env.js` 파일을 통해 런타임 환경 설정을 관리합니다:
```javascript
window.__runtime_config__ = {
MEMBER_URL: 'http://localhost:8081/api/auth',
MYSUB_URL: 'http://localhost:8082/api/mysub',
RECOMMEND_URL: 'http://localhost:8083/api/recommend'
}
```
### 5.3 필요한 백킹 서비스 설치
#### 5.3.1 PostgreSQL 데이터베이스 설치
각 마이크로서비스는 별도의 PostgreSQL 데이터베이스를 사용합니다.
1. Docker로 설치
```bash
# Member 서비스용 DB
docker run -d --name member-postgres \
-e POSTGRES_DB=member \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=Passw0rd \
-p 5432:5432 \
postgres:13.2-alpine
# MySub 서비스용 DB
docker run -d --name mysub-postgres \
-e POSTGRES_DB=mysub \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=Passw0rd \
-p 5433:5432 \
postgres:13.2-alpine
# Recommend 서비스용 DB
docker run -d --name recommend-postgres \
-e POSTGRES_DB=recommend \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=Passw0rd \
-p 5434:5432 \
postgres:13.2-alpine
```
2. Kubernetes Helm Chart로 설치
```bash ```bash
# Helm 저장소 추가 # Helm 저장소 추가
helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add bitnami https://charts.bitnami.com/bitnami
@ -157,89 +49,36 @@
# Member 서비스용 DB # Member 서비스용 DB
helm install member bitnami/postgresql \ helm install member bitnami/postgresql \
--set global.postgresql.auth.postgresPassword=Passw0rd \ --set global.postgresql.auth.postgresPassword=Passw0rd \
--set global.postgresql.auth.username=admin \ --set global.postgresql.auth.username=admin \
--set global.postgresql.auth.password=Passw0rd \ --set global.postgresql.auth.password=Passw0rd \
--set global.postgresql.auth.database=member --set global.postgresql.auth.database=member
# MySub 서비스용 DB # MySub 서비스용 DB
helm install mysub bitnami/postgresql \ helm install mysub bitnami/postgresql \
--set global.postgresql.auth.postgresPassword=Passw0rd \ --set global.postgresql.auth.postgresPassword=Passw0rd \
--set global.postgresql.auth.username=admin \ --set global.postgresql.auth.username=admin \
--set global.postgresql.auth.password=Passw0rd \ --set global.postgresql.auth.password=Passw0rd \
--set global.postgresql.auth.database=mysub --set global.postgresql.auth.database=mysub
# Recommend 서비스용 DB # Recommend 서비스용 DB
helm install recommend bitnami/postgresql \ helm install recommend bitnami/postgresql \
--set global.postgresql.auth.postgresPassword=Passw0rd \ --set global.postgresql.auth.postgresPassword=Passw0rd \
--set global.postgresql.auth.username=admin \ --set global.postgresql.auth.username=admin \
--set global.postgresql.auth.password=Passw0rd \ --set global.postgresql.auth.password=Passw0rd \
--set global.postgresql.auth.database=recommend --set global.postgresql.auth.database=recommend
``` ```
#### 5.3.2 Message Queue 설치 2. Message Queue 설치
설치 방법
{MQ별 설치 방법 안내}
### 5.4 백엔드 개발 환경 설정
1. 저장소 클론
```bash
git clone https://github.com/your-org/lifesub.git
cd lifesub
```
2. 의존성 설치 및 각 서비스 개별 빌드
```bash
# 각 서비스 모듈을 개별적으로 빌드
./gradlew :member:build
./gradlew :mysub-infra:build
./gradlew :recommend:build
# 또는 테스트 스킵 옵션으로 빌드 ## 4. 빌드 및 배포
./gradlew :member:build -x test
./gradlew :mysub-infra:build -x test
./gradlew :recommend:build -x test
```
3. 각 서비스 실행 ### 4.1 프론트엔드 빌드 및 배포
```bash 1. 컨테이너 이미지 빌드
# Member 서비스 실행
java -jar member/build/libs/member.jar
# MySub 서비스 실행 (mysub-biz는 라이브러리 모듈로 mysub-infra에 포함됨)
java -jar mysub-infra/build/libs/mysub.jar
# Recommend 서비스 실행
java -jar recommend/build/libs/recommend.jar
```
4. 환경 설정
각 서비스는 `application.yml` 파일에서 설정을 관리합니다. 기본 구성:
```yaml
server:
port: 8081 # 각 서비스별로 다른 포트 사용
spring:
datasource:
url: jdbc:postgresql://localhost:5432/member # 각 서비스별 DB 이름 변경 필요
username: admin
password: Passw0rd
jwt:
secret-key: '8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ'
access-token-validity: 3600000
refresh-token-validity: 86400000
allowed-origins: http://localhost:3000
```
## 6. 빌드 및 배포
### 6.1 프론트엔드 빌드 및 배포
1. 애플리케이션 빌드
```bash
npm run build
```
2. 컨테이너 이미지 빌드
```bash ```bash
docker build \ docker build \
--build-arg PROJECT_FOLDER="." \ --build-arg PROJECT_FOLDER="." \
@ -252,17 +91,17 @@
-t {Image Registry주소}/lifesub/lifesub-web:latest . -t {Image Registry주소}/lifesub/lifesub-web:latest .
``` ```
3. 이미지 푸시 2. 이미지 푸시
```bash ```bash
docker push {Image Registry주소}/lifesub/lifesub-web:latest docker push {Image Registry주소}/lifesub/lifesub-web:latest
``` ```
4. Kubernetes 배포 3. Kubernetes 배포
```bash ```bash
kubectl apply -f deployment/manifest/ kubectl apply -f deployment/manifest/
``` ```
### 6.2 백엔드 빌드 및 배포 ### 4.2 백엔드 빌드 및 배포
1. 애플리케이션 빌드 1. 애플리케이션 빌드
```bash ```bash
# 각 서비스 모듈을 개별적으로 빌드 # 각 서비스 모듈을 개별적으로 빌드
@ -307,19 +146,18 @@
kubectl apply -f deployment/manifest/ kubectl apply -f deployment/manifest/
``` ```
### 6.3 로그인 ### 4.3 테스트
1) 프론트 페이지 주소 구하기 1) 프론트 페이지 주소 구하기
``` ```
kubens {namespace} kubens {namespace}
k get ing k get svc
``` ```
2) 로그인 2) 로그인
- ID: user01 ~ user05 - ID: user01 ~ user05
- PW: P@ssw0rd$ - PW: P@ssw0rd$
## 5. 팀
## 7. 팀
- 오유진 "피오" - Product Owner - 오유진 "피오" - Product Owner
- 강동훈 "테키" - Tech Lead - 강동훈 "테키" - Tech Lead
@ -328,3 +166,4 @@ k get ing
- 박소연 "프개" - Frontend Developer - 박소연 "프개" - Frontend Developer
- 최진우 "큐에이" - QA Engineer - 최진우 "큐에이" - QA Engineer
- 정해린 "데브옵스" - DevOps Engineer - 정해린 "데브옵스" - DevOps Engineer

View File

@ -37,14 +37,14 @@ podTemplate(
stage('Code Analysis & Quality Gate') { stage('Code Analysis & Quality Gate') {
container('node') { container('node') {
sh "npm install" sh "npm install"
sh "npm test -- --coverage --passWithNoTests" //test code 없어도 통과되게 함 sh "npm test -- --coverage --passWithNoTests"
} }
container('sonar-scanner') { container('sonar-scanner') {
withSonarQubeEnv('SonarQube') { withSonarQubeEnv('SonarQube') {
sh """ sh """
${sonarScannerHome}/bin/sonar-scanner \ ${sonarScannerHome}/bin/sonar-scanner \
-Dsonar.projectKey=lifesub-web \ -Dsonar.projectKey=lifesub-web-dg0400 \
-Dsonar.sources=src \ -Dsonar.sources=src \
-Dsonar.tests=src \ -Dsonar.tests=src \
-Dsonar.test.inclusions=src/**/*.test.js,src/**/*.test.jsx \ -Dsonar.test.inclusions=src/**/*.test.js,src/**/*.test.jsx \
@ -66,7 +66,7 @@ podTemplate(
withCredentials([azureServicePrincipal('azure-credentials')]) { withCredentials([azureServicePrincipal('azure-credentials')]) {
sh """ sh """
az login --service-principal -u \$AZURE_CLIENT_ID -p \$AZURE_CLIENT_SECRET -t \$AZURE_TENANT_ID az login --service-principal -u \$AZURE_CLIENT_ID -p \$AZURE_CLIENT_SECRET -t \$AZURE_TENANT_ID
az aks get-credentials --resource-group ictcoe-edu --name ${props.teamid}-aks --overwrite-existing az aks get-credentials --resource-group rg-digitalgarage-01 --name aks-digitalgarage-01 --overwrite-existing
kubectl create namespace ${namespace} --dry-run=client -o yaml | kubectl apply -f - kubectl create namespace ${namespace} --dry-run=client -o yaml | kubectl apply -f -
""" """
} }
@ -87,12 +87,9 @@ podTemplate(
podman build \ podman build \
--build-arg PROJECT_FOLDER="." \ --build-arg PROJECT_FOLDER="." \
--build-arg REACT_APP_MEMBER_URL="${props.react_app_member_url}" \ --build-arg BUILD_FOLDER="deployment/container" \
--build-arg REACT_APP_MYSUB_URL="${props.react_app_mysub_url}" \
--build-arg REACT_APP_RECOMMEND_URL="${props.react_app_recommend_url}" \
--build-arg BUILD_FOLDER="deployment" \
--build-arg EXPORT_PORT="${props.export_port}" \ --build-arg EXPORT_PORT="${props.export_port}" \
-f deployment/Dockerfile-lifesub-web \ -f deployment/container/Dockerfile-lifesub-web \
-t ${imagePath} . -t ${imagePath} .
podman push ${imagePath} podman push ${imagePath}
@ -108,12 +105,14 @@ podTemplate(
export lifesub_web_image_path=${props.registry}/${props.image_org}/lifesub-web:${imageTag} export lifesub_web_image_path=${props.registry}/${props.image_org}/lifesub-web:${imageTag}
export replicas=${props.replicas} export replicas=${props.replicas}
export export_port=${props.export_port} export export_port=${props.export_port}
export ingress_host=${props.ingress_host}
export resources_requests_cpu=${props.resources_requests_cpu} export resources_requests_cpu=${props.resources_requests_cpu}
export resources_requests_memory=${props.resources_requests_memory} export resources_requests_memory=${props.resources_requests_memory}
export resources_limits_cpu=${props.resources_limits_cpu} export resources_limits_cpu=${props.resources_limits_cpu}
export resources_limits_memory=${props.resources_limits_memory} export resources_limits_memory=${props.resources_limits_memory}
envsubst < deployment/${manifest}.template > deployment/${manifest} envsubst < deployment/${manifest}.template > deployment/${manifest}
echo "Generated manifest file:"
cat deployment/${manifest} cat deployment/${manifest}
""" """
} }
@ -126,10 +125,10 @@ podTemplate(
kubectl -n ${namespace} wait --for=condition=available deployment/lifesub-web --timeout=300s kubectl -n ${namespace} wait --for=condition=available deployment/lifesub-web --timeout=300s
echo "Waiting for service external IP..." echo "Waiting for service external IP..."
while [[ -z \$(kubectl -n ${namespace} get svc lifesub-web -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ]]; do while [[ -z \$(kubectl -n ${namespace} get svc lifesub-web-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ]]; do
sleep 5 sleep 5
done done
echo "Service external IP: \$(kubectl -n ${namespace} get svc lifesub-web -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" echo "Service external IP: \$(kubectl -n ${namespace} get svc lifesub-web-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
""" """
} }
} }

View File

@ -12,42 +12,34 @@ podTemplate(
containers: [ containers: [
containerTemplate(name: 'node', image: 'node:20-slim', ttyEnabled: true, command: 'cat'), containerTemplate(name: 'node', image: 'node:20-slim', ttyEnabled: true, command: 'cat'),
containerTemplate(name: 'podman', image: "mgoltzsche/podman", ttyEnabled: true, command: 'cat', privileged: true), containerTemplate(name: 'podman', image: "mgoltzsche/podman", ttyEnabled: true, command: 'cat', privileged: true),
containerTemplate(name: 'azure-cli', image: 'hiondal/azure-kubectl:latest', command: 'cat', ttyEnabled: true), containerTemplate(name: 'git', image: 'alpine/git:latest', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'envsubst', image: "hiondal/envsubst", command: 'sleep', args: '1h'), containerTemplate(name: 'sonar-scanner', image: 'sonarsource/sonar-scanner-cli:latest', command: 'cat', ttyEnabled: true)
containerTemplate(name: 'sonar-scanner', image: 'sonarsource/sonar-scanner-cli:latest', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'git', image: 'alpine/git:latest', command: 'cat', ttyEnabled: true)
], ],
volumes: [ volumes: [
emptyDirVolume(mountPath: '/root/.azure', memory: false),
emptyDirVolume(mountPath: '/opt/sonar-scanner/.sonar/cache', memory: false) emptyDirVolume(mountPath: '/opt/sonar-scanner/.sonar/cache', memory: false)
] ]
) { ) {
node(PIPELINE_ID) { node(PIPELINE_ID) {
def props def props
def imageTag = getImageTag() def imageTag = getImageTag()
def manifest = "deploy.yaml"
def namespace
def sonarScannerHome = '/opt/sonar-scanner' def sonarScannerHome = '/opt/sonar-scanner'
def MANIFEST_REPO = "https://github.com/cna-bootcamp/lifesub-manifest.git"
def MANIFEST_BRANCH = "main"
stage("Get Source") { stage("Get Source") {
checkout scm checkout scm
props = readProperties file: "deployment/deploy_env_vars" props = readProperties file: "deployment/deploy_env_vars"
namespace = "${props.namespace}"
} }
stage('Code Analysis & Quality Gate') { stage('Code Analysis & Quality Gate') {
container('node') { container('node') {
sh "npm install" sh "npm install"
sh "npm test -- --coverage --passWithNoTests" //test code 없어도 통과되게 함 sh "npm test -- --coverage --passWithNoTests"
} }
container('sonar-scanner') { container('sonar-scanner') {
withSonarQubeEnv('SonarQube') { withSonarQubeEnv('SonarQube') {
sh """ sh """
${sonarScannerHome}/bin/sonar-scanner \ ${sonarScannerHome}/bin/sonar-scanner \
-Dsonar.projectKey=lifesub-web \ -Dsonar.projectKey=lifesub-web-dg0400 \
-Dsonar.sources=src \ -Dsonar.sources=src \
-Dsonar.tests=src \ -Dsonar.tests=src \
-Dsonar.test.inclusions=src/**/*.test.js,src/**/*.test.jsx \ -Dsonar.test.inclusions=src/**/*.test.js,src/**/*.test.jsx \
@ -64,18 +56,6 @@ podTemplate(
} }
} }
stage("Setup AKS") {
container('azure-cli') {
withCredentials([azureServicePrincipal('azure-credentials')]) {
sh """
az login --service-principal -u \$AZURE_CLIENT_ID -p \$AZURE_CLIENT_SECRET -t \$AZURE_TENANT_ID
az aks get-credentials --resource-group ictcoe-edu --name ${props.teamid}-aks --overwrite-existing
kubectl create namespace ${namespace} --dry-run=client -o yaml | kubectl apply -f -
"""
}
}
}
stage('Build & Push Image') { stage('Build & Push Image') {
container('podman') { container('podman') {
withCredentials([usernamePassword( withCredentials([usernamePassword(
@ -90,12 +70,9 @@ podTemplate(
podman build \ podman build \
--build-arg PROJECT_FOLDER="." \ --build-arg PROJECT_FOLDER="." \
--build-arg REACT_APP_MEMBER_URL="${props.react_app_member_url}" \ --build-arg BUILD_FOLDER="deployment/container" \
--build-arg REACT_APP_MYSUB_URL="${props.react_app_mysub_url}" \
--build-arg REACT_APP_RECOMMEND_URL="${props.react_app_recommend_url}" \
--build-arg BUILD_FOLDER="deployment" \
--build-arg EXPORT_PORT="${props.export_port}" \ --build-arg EXPORT_PORT="${props.export_port}" \
-f deployment/Dockerfile-lifesub-web \ -f deployment/container/Dockerfile-lifesub-web \
-t ${imagePath} . -t ${imagePath} .
podman push ${imagePath} podman push ${imagePath}
@ -106,27 +83,37 @@ podTemplate(
stage('Update Manifest Repository') { stage('Update Manifest Repository') {
container('git') { container('git') {
// 임시 디렉토리 생성 withCredentials([usernamePassword(
sh "mkdir -p /tmp/manifests" credentialsId: 'github-credentials-dg0400',
usernameVariable: 'GIT_USERNAME',
// Clone manifest repository passwordVariable: 'GIT_PASSWORD'
withCredentials([usernamePassword(credentialsId: 'github-credentials', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')]) { )]) {
sh """ sh """
# Git 설정
git config --global user.name "Jenkins"
git config --global user.email "jenkins@example.com" git config --global user.email "jenkins@example.com"
git config --global user.name "Jenkins Pipeline"
git clone https://${GIT_USERNAME}:${GIT_PASSWORD}@github.com/cna-bootcamp/lifesub-manifest.git /tmp/manifests # Manifest Repository Clone
cd /tmp/manifests git clone https://\$GIT_USERNAME:\$GIT_PASSWORD@github.com/cna-bootcamp/lifesub-manifest.git
cd lifesub-manifest
# Update frontend image tag # Frontend 이미지 태그 업데이트
if [ -f lifesub-web/deployments/lifesub-web-deployment.yaml ]; then echo "Updating lifesub-web deployment with image tag: ${imageTag}"
sed -i "s|image: ${props.registry}/${props.image_org}/lifesub-web:.*|image: ${props.registry}/${props.image_org}/lifesub-web:${imageTag}|g" lifesub-web/deployments/lifesub-web-deployment.yaml
if [ -f "lifesub-web/frontend-deployment.yaml" ]; then
# 기존 이미지 태그를 새 태그로 교체
sed -i "s|image: ${props.registry}/${props.image_org}/lifesub-web:.*|image: ${props.registry}/${props.image_org}/lifesub-web:${imageTag}|g" lifesub-web/frontend-deployment.yaml
echo "Updated frontend deployment file:"
cat lifesub-web/frontend-deployment.yaml | grep "image:"
else
echo "Warning: Frontend deployment file not found"
fi fi
# Commit and push changes # 변경사항 커밋 및 푸시
git add . git add .
git commit -m "Update frontend image tag to ${imageTag}" || true git commit -m "Update frontend service image tag to ${imageTag}" || echo "No changes to commit"
git push git push origin main
""" """
} }
} }

View File

@ -1,9 +1,26 @@
# Frontend Deployment # ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-config
namespace: ${namespace}
data:
runtime-env.js: |
window.__runtime_config__ = {
MEMBER_URL: 'http://${ingress_host}/api/auth',
MYSUB_URL: 'http://${ingress_host}/api/mysub',
RECOMMEND_URL: 'http://${ingress_host}/api/recommend'
};
---
# Deployment
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: lifesub-web name: lifesub-web
namespace: ${namespace} namespace: ${namespace}
labels:
app: lifesub-web
spec: spec:
replicas: ${replicas} replicas: ${replicas}
selector: selector:
@ -14,6 +31,8 @@ spec:
labels: labels:
app: lifesub-web app: lifesub-web
spec: spec:
imagePullSecrets:
- name: acr-secret
containers: containers:
- name: lifesub-web - name: lifesub-web
image: ${lifesub_web_image_path} image: ${lifesub_web_image_path}
@ -27,18 +46,29 @@ spec:
limits: limits:
cpu: ${resources_limits_cpu} cpu: ${resources_limits_cpu}
memory: ${resources_limits_memory} memory: ${resources_limits_memory}
volumeMounts:
- name: runtime-config
mountPath: /usr/share/nginx/html/runtime-env.js
subPath: runtime-env.js
volumes:
- name: runtime-config
configMap:
name: frontend-config
--- ---
# Frontend Service # Service
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: lifesub-web name: lifesub-web-service
namespace: ${namespace} namespace: ${namespace}
spec: labels:
selector:
app: lifesub-web app: lifesub-web
spec:
type: LoadBalancer
ports: ports:
- port: 80 - port: 80
targetPort: ${export_port} targetPort: ${export_port}
type: LoadBalancer protocol: TCP
selector:
app: lifesub-web

View File

@ -1,20 +1,16 @@
# Team Settings # Team Settings
teamid=unicorn teamid=dg0400
root_project=lifesub-web root_project=lifesub-web
namespace=unicorn-lifesub-ns namespace=dg0400-lifesub-ns
# Container Registry Settings # Container Registry Settings
registry=unicorncr.azurecr.io registry=acrdigitalgarage01.azurecr.io
image_org=lifesub image_org=dg0400
# Application Settings # Application Settings
replicas=1 replicas=1
export_port=18080 export_port=18080
ingress_host=dg0400.20.214.196.128.nip.io
# Backend Service URLs
react_app_member_url=http://20.249.205.95/member
react_app_mysub_url=http://20.249.205.95/mysub
react_app_recommend_url=http://20.249.205.95/recommend
# Resource Settings # Resource Settings
resources_requests_cpu=256m resources_requests_cpu=256m

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-config
namespace: dg0400-lifesub-ns
data:
runtime-env.js: |
window.__runtime_config__ = {
MEMBER_URL: 'http://dg0400.20.214.196.128.nip.io/api/auth',
MYSUB_URL: 'http://dg0400.20.214.196.128.nip.io/api/mysub',
RECOMMEND_URL: 'http://dg0400.20.214.196.128.nip.io/api/recommend'
};

View File

@ -0,0 +1,96 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-config
namespace: dg0400-lifesub-ns
data:
runtime-env.js: |
window.__runtime_config__ = {
MEMBER_URL: 'http://dg0400.20.214.196.128.nip.io/api/auth',
MYSUB_URL: 'http://dg0400.20.214.196.128.nip.io/api/mysub',
RECOMMEND_URL: 'http://dg0400.20.214.196.128.nip.io/api/recommend'
};
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: lifesub-web
namespace: dg0400-lifesub-ns
labels:
app: lifesub-web
spec:
replicas: 2
selector:
matchLabels:
app: lifesub-web
template:
metadata:
labels:
app: lifesub-web
spec:
imagePullSecrets:
- name: acr-secret
containers:
- name: lifesub-web
image: dg0400cr.azurecr.io/dg0400/lifesub-web:1.0.0
imagePullPolicy: Always
ports:
- containerPort: 18080
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
---
apiVersion: v1
kind: Service
metadata:
name: lifesub-web-service
namespace: dg0400-lifesub-ns
labels:
app: lifesub-web
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 18080
protocol: TCP
selector:
app: lifesub-web
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
namespace: dg0400-lifesub-ns
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: dg0400.20.249.113.122.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: lifesub-web-service
port:
number: 80

View File

@ -1,8 +1,10 @@
# lifesub-web/deployment/manifest/deployments/hiondal-web-deployment.yaml
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: lifesub-web name: lifesub-web
namespace: dg0400-lifesub-ns
labels:
app: lifesub-web
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@ -14,10 +16,10 @@ spec:
app: lifesub-web app: lifesub-web
spec: spec:
imagePullSecrets: imagePullSecrets:
- name: dockerhub - name: acr-secret
containers: containers:
- name: lifesub-web - name: lifesub-web
image: dg0200cr.azurecr.io/lifesub/lifesub-web:1.0.0 image: acrdigitalgarage01.azurecr.io/dg0400/lifesub-web:1.0.0
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 18080 - containerPort: 18080
@ -28,4 +30,11 @@ spec:
limits: limits:
cpu: 1024m cpu: 1024m
memory: 1024Mi 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

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: lifesub-web-service
namespace: dg0400-lifesub-ns
labels:
app: lifesub-web
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 18080
protocol: TCP
selector:
app: lifesub-web

View File

@ -1,12 +0,0 @@
# lifesub-web/deployment/manifest/services/lifesub-web-service.yaml
apiVersion: v1
kind: Service
metadata:
name: lifesub-web
spec:
selector:
app: lifesub-web
ports:
- port: 80
targetPort: 18080
type: LoadBalancer