K8s YAML 생성
KIWI의 [서비스 관리] 페이지에서는 Kubernetes 배포에 필요한 YAML 파일을 직접 작성하지 않고, 폼에서 옵션을 선택하여 자동으로 생성할 수 있습니다. 이 가이드에서는 생성 가능한 리소스 종류(Kind)별 옵션과, 실제 프로젝트에서 YAML을 어떻게 구성하는지 예시를 통해 설명합니다.
KIWI는 입력한 옵션을 기반으로 표준 Kubernetes YAML을 자동 생성합니다. 생성된 YAML은 미리보기에서 확인하고, 필요하면 직접 편집할 수도 있습니다.
YAML 생성 페이지 진입
- [서비스 관리] 페이지에서 서비스를 선택합니다.
- 파이프라인의 Deploy 단계를 클릭합니다.
- 배포 환경 설정에서 K8s 배포를 선택하면 YAML 생성 화면이 표시됩니다.
Part 1: Kind별 옵션 설명
KIWI에서 생성할 수 있는 Kubernetes 리소스는 6가지입니다. 프로젝트 구성에 따라 필요한 Kind를 조합하여 사용합니다.
| Kind | 용도 | 필수 여부 |
|---|---|---|
| Deployment | 애플리케이션 Pod 배포 | ✅ 거의 항상 |
| Service | Pod 네트워크 접근 | ✅ 거의 항상 |
| Ingress | 외부 도메인 라우팅 | 선택 |
| ConfigMap | 설정값 분리 관리 | 선택 |
| PVC | 영구 스토리지 | 선택 |
| Job | 일회성 작업 (마이그레이션 등) | 선택 |
- Ingress Controller (권장): Service를 ClusterIP로 설정하고 Ingress를 함께 생성합니다. 도메인 기반 라우팅에 적합하며 가장 일반적인 방식입니다.
- NodePort (외부 Nginx): 외부 리버스 프록시에서 NodePort를 통해 접근합니다. Ingress가 필요 없습니다.
- LoadBalancer (외부 IP): 외부 IP를 직접 할당받습니다. 클라우드 환경에서 주로 사용하며 Ingress가 필요 없습니다.
Deployment
애플리케이션 Pod의 배포 방식을 정의합니다.
컨테이너를 직접 실행하면 장애 시 자동 복구가 되지 않습니다. Deployment는 원하는 수만큼 Pod를 유지하고, 장애가 발생하면 자동으로 재시작하며, 새 버전 배포 시 무중단 업데이트를 처리합니다.
기본 옵션
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | Deployment 리소스 이름. 예: my-app |
| 네임스페이스 | default | 배포 대상 네임스페이스 | |
| 레플리카 수 | 1 | 동시에 실행할 Pod 수. 프로덕션은 3개 이상 권장 | |
| imagePullPolicy | Always | 이미지 풀 정책. Always, IfNotPresent, Never 중 선택 | |
| 레이블 | - | key-value 쌍. Service의 selector와 매칭됨. 예: app: my-app |
컨테이너 (1개 이상 필수)
Pod 내에서 실행할 컨테이너를 정의합니다.
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | 컨테이너 식별자. 예: frontend |
| 이미지 | ✅ | - | 컨테이너 이미지 주소. 빌드 목록에서 선택 또는 직접 입력 |
| 포트 | 80 | 컨테이너가 수신하는 포트 번호 | |
| 환경 변수 | - | 직접 입력(key-value), secretKeyRef, configMapKeyRef 방식 지원 | |
| 커맨드 / Args | - | 시작 시 실행할 명령어와 인자. 예: ["node", "server.js"] | |
| 볼륨 마운트 | - | PVC를 컨테이너 내부 경로에 마운트. name, mountPath, claimName 지정 |
배포 전략
새 버전 배포 시 Pod 교체 방식을 결정합니다.
| 전략 | 설명 | 추가 옵션 |
|---|---|---|
RollingUpdate (기본) | 점진적 교체. 무중단 배포에 적합 | maxSurge (기본 1), maxUnavailable (기본 0) |
Recreate | 모든 Pod를 종료한 후 새로 생성. 다운타임 발생 가능 | - |
리소스 (선택)
Pod에 할당할 CPU와 메모리를 설정합니다.
| 구분 | 설명 | 예시 |
|---|---|---|
| requests | 최소 보장량. 스케줄링 기준이 됨 | cpu: 100m, memory: 128Mi |
| limits | 최대 상한. 초과 시 제한됨 | cpu: 500m, memory: 512Mi |
헬스체크 (선택)
Pod 상태를 확인하는 프로브를 설정합니다.
| 프로브 | 역할 | 실패 시 동작 |
|---|---|---|
| Liveness Probe | Pod가 살아있는지 확인 | Pod 재시작 |
| Readiness Probe | 트래픽을 받을 준비가 되었는지 확인 | 트래픽 차단 |
각 프로브에서 설정하는 항목:
| 옵션 | 설명 |
|---|---|
| path | 헬스체크 요청 경로. 예: /health |
| port | 헬스체크 요청 포트 |
| initialDelaySeconds | Pod 시작 후 첫 검사까지 대기 시간(초) |
| periodSeconds | 검사 주기(초) |
| timeoutSeconds | 응답 대기 시간(초) |
| failureThreshold | 연속 실패 허용 횟수 |
Service
Pod에 접근하기 위한 네트워크 엔드포인트를 정의합니다.
Pod는 재시작될 때마다 IP가 바뀝니다. Service는 고정된 주소를 제공하여 다른 Pod나 외부에서 안정적으로 접근할 수 있게 합니다.
기본 옵션
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | Service 리소스 이름. 예: my-app-svc |
| 네임스페이스 | default | 배포 대상 네임스페이스 | |
| Selector | ✅ | - | 트래픽을 전달할 Pod의 레이블. Deployment 레이블과 일치해야 함 |
타입
네트워크 노출 방식에 따라 선택합니다.
| 타입 | 설명 | 사용 시나리오 |
|---|---|---|
ClusterIP (기본) | 클러스터 내부에서만 접근 가능 | Ingress와 함께 사용 |
NodePort | 노드의 특정 포트를 통해 외부 접근 | 외부 리버스 프록시(Nginx 등)와 사용 |
LoadBalancer | 외부 IP를 할당받아 직접 노출 | 클라우드 환경에서 주로 사용 |
포트 (1개 이상)
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| name | - | 포트 식별자. 예: http | |
| protocol | TCP | 프로토콜 | |
| port | ✅ | - | Service가 수신하는 포트 |
| targetPort | ✅ | - | 트래픽을 전달할 컨테이너 포트 |
| nodePort | - | NodePort 타입일 때 노드에서 열리는 포트 |
Ingress
외부 트래픽을 클러스터 내부 Service로 라우팅하는 규칙을 정의합니다.
Service만으로는 도메인 기반 라우팅이나 HTTPS 처리가 어렵습니다. Ingress는 app.example.com 같은 도메인으로 들어오는 요청을 경로별로 적절한 Service에 전달하고, TLS 인증서도 관리합니다.
기본 옵션
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | Ingress 리소스 이름. 예: my-app-ingress |
| 네임스페이스 | default | 배포 대상 네임스페이스 | |
| Annotations | - | Ingress Controller의 세부 동작을 제어하는 key-value 쌍 |
Ingress Class
사용할 Ingress Controller를 선택합니다.
| Ingress Class | 설명 |
|---|---|
traefik (기본 권장) | 자동 인증서, 미들웨어 체인 지원 |
nginx | 커뮤니티 프로젝트. 2026년 3월 EOL 예정으로 마이그레이션 권장 |
haproxy | 고성능 로드밸런싱. 엔터프라이즈 환경에 적합 |
kong | API Gateway 통합, 플러그인 확장 지원 |
contour | Envoy 프록시 기반 CNCF 프로젝트 |
alb | AWS Application Load Balancer. AWS 클라우드 환경 전용 |
Rules (1개 이상)
도메인별 라우팅 규칙을 정의합니다.
| 옵션 | 설명 |
|---|---|
| host | 도메인명. 예: app.example.com |
| paths | 경로별 라우팅 설정. path, pathType(Prefix), serviceName, servicePort 지정 |
TLS (선택)
HTTPS를 활성화합니다. hosts(도메인 목록)와 secretName(인증서 Secret)을 지정합니다.
ConfigMap
애플리케이션의 설정값을 key-value 형태로 저장하는 리소스입니다.
환경 변수를 Deployment에 직접 입력하면 값이 YAML에 그대로 노출됩니다. ConfigMap으로 분리하면 환경별로 설정만 교체할 수 있고, 여러 Deployment에서 동일한 설정을 공유할 수 있습니다. 비밀번호나 API 키 같은 민감 정보는 ConfigMap 대신 Secret을 사용하세요.
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | ConfigMap 리소스 이름. 예: app-config |
| 네임스페이스 | default | 배포 대상 네임스페이스 | |
| 데이터 | ✅ | - | key-value 쌍. 예: DATABASE_HOST: postgres, LOG_LEVEL: info |
| 레이블 | - | key-value 쌍 |
PersistentVolumeClaim (PVC)
Pod에서 사용할 영구 스토리지를 요청하는 리소스입니다. Pod가 재시작되거나 삭제되어도 데이터가 유지됩니다.
Pod의 파일 시스템은 일시적입니다. Pod가 재시작되면 내부 데이터가 사라집니다. 데이터베이스나 업로드 파일처럼 영구 보존이 필요한 데이터는 PVC로 외부 스토리지에 저장해야 합니다.
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | PVC 리소스 이름. 예: app-data-pvc |
| 네임스페이스 | default | 배포 대상 네임스페이스 | |
| 스토리지 용량 | 10Gi | 요청할 디스크 크기 | |
| 스토리지 클래스 | nfs-client | 사용할 스토리지 프로비저너 |
스토리지 클래스 선택
nfs-client, local-path, longhorn, ceph-rbd, default 등을 선택할 수 있습니다.
접근 모드
| 모드 | 설명 | 사용 시나리오 |
|---|---|---|
ReadWriteOnce (기본) | 단일 노드에서 읽기/쓰기 | 대부분의 경우 적합 |
ReadWriteMany | 다중 노드에서 동시 읽기/쓰기 | NFS 등 공유 스토리지 필요 |
ReadOnlyMany | 다중 노드에서 읽기 전용 | 설정 파일 공유 등 |
PVC를 삭제하면 연결된 데이터가 영구적으로 손실될 수 있습니다. 삭제 전 반드시 백업 여부를 확인하세요.
Job
일회성 또는 배치 작업을 실행하는 리소스입니다. 작업이 완료되면 Pod가 종료됩니다.
DB 마이그레이션, 초기 데이터 삽입, 일회성 스크립트 실행 등 한 번 실행하고 끝나는 작업에 사용합니다. Deployment와 달리 작업 완료 후 Pod가 자동 종료됩니다.
기본 옵션
| 옵션 | 필수 | 기본값 | 설명 |
|---|---|---|---|
| 이름 | ✅ | - | Job 리소스 이름. 예: db-migrate-job |
| 네임스페이스 | default | 배포 대상 네임스페이스 | |
| 이미지 | ✅ | - | Job에서 실행할 컨테이너 이미지 |
| 커맨드 / Args | - | 실행할 명령어와 인자. 예: ["python"], ["manage.py", "migrate"] | |
| 환경 변수 | - | key-value 형태로 직접 입력 | |
| backoffLimit | 3 | 실패 시 재시도 횟수. 초과 시 Job 실패로 처리 |
Job 유형
| 유형 | 설명 |
|---|---|
| DB 마이그레이션 | 데이터베이스 스키마 변경 시 사용 |
| 초기화 작업 | 최초 데이터 세팅, 시드 데이터 삽입 등 |
| 커스텀 | 사용자 정의 일회성 작업 |
envFrom (선택)
ConfigMap 또는 Secret 전체를 환경 변수로 주입합니다.
| 참조 방식 | 설명 |
|---|---|
configMapRef | ConfigMap의 모든 키를 환경 변수로 로드 |
secretRef | Secret의 모든 키를 환경 변수로 로드 |
restartPolicy
| 정책 | 설명 |
|---|---|
OnFailure (기본) | 실패 시 동일 Pod 내에서 컨테이너를 재시작 |
Never | 실패해도 재시작하지 않고 새 Pod를 생성 |
Part 2: YAML 생성 예시
예시 1: 기본 웹 서비스 (Frontend + Backend + Database)
React 프론트엔드 + Node.js API 백엔드 + PostgreSQL 데이터베이스로 구성된 일반적인 웹 서비스입니다.
서비스 구성도
사용자 → Ingress (app.example.com)
├─ / → frontend-svc(:80) → frontend Pod (React/Nginx)
└─ /api → backend-svc(:3000) → backend Pod (Node.js)
↓
postgres-svc(:5432) → postgres Pod
생성되는 리소스
- Deployment 3개 (frontend, backend, postgres)
- Service 3개 (frontend-svc, backend-svc, postgres-svc)
- Ingress 1개 (app-ingress)
파일 구성
k8s/
├── deployment.yaml ← frontend + backend + postgres Deployment
├── service.yaml ← frontend-svc + backend-svc + postgres-svc
└── ingress.yaml ← app-ingress
YAML 생성 시 Kind별로 파일이 분리됩니다. 같은 Kind의 리소스가 여러 개이면 하나의 파일에 --- 구분자로 합쳐집니다.
Frontend — Deployment & Service
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | frontend |
| 네임스페이스 | my-web-app |
| 레플리카 | 2 |
| 이미지 | harbor.example.com/my-project/frontend:v1.0 |
| 포트 | 80 |
| 전략 | RollingUpdate (maxSurge: 1, maxUnavailable: 0) |
| 리소스 | requests: 100m/128Mi, limits: 300m/256Mi |
| Service 타입 | ClusterIP |
- 빌드된 React 앱을 Nginx로 서빙하므로 포트 80을 사용합니다.
- 프론트엔드는 정적 파일 서빙이므로 리소스를 작게 설정합니다.
생성되는 YAML 확인
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: my-web-app
labels:
app: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: harbor.example.com/my-project/frontend:v1.0
ports:
- containerPort: 80
imagePullPolicy: Always
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 300m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
namespace: my-web-app
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
Backend — Deployment & Service
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | backend |
| 네임스페이스 | my-web-app |
| 레플리카 | 2 |
| 이미지 | harbor.example.com/my-project/backend:v1.0 |
| 포트 | 3000 |
| 전략 | RollingUpdate (maxSurge: 1, maxUnavailable: 0) |
| 환경 변수 | DATABASE_HOST, DATABASE_PORT, DATABASE_NAME + Secret 참조 |
| 리소스 | requests: 200m/256Mi, limits: 500m/512Mi |
| 헬스체크 | Liveness + Readiness (/health:3000) |
| Service 타입 | ClusterIP |
DATABASE_HOST에 postgres Service 이름을 사용합니다. 같은 네임스페이스 내에서 DNS로 자동 해석됩니다.- 비밀번호는
secretKeyRef를 통해 Secret에서 가져옵니다. YAML에 직접 노출하지 않습니다. - 헬스체크를 설정하여 비정상 Pod를 자동으로 감지합니다.
생성되는 YAML 확인
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: my-web-app
labels:
app: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: harbor.example.com/my-project/backend:v1.0
ports:
- containerPort: 3000
imagePullPolicy: Always
env:
- name: DATABASE_HOST
value: postgres-svc
- name: DATABASE_PORT
value: "5432"
- name: DATABASE_NAME
value: myapp
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: backend-svc
namespace: my-web-app
spec:
type: ClusterIP
selector:
app: backend
ports:
- name: http
protocol: TCP
port: 3000
targetPort: 3000
Database — Deployment & Service
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | postgres |
| 네임스페이스 | my-web-app |
| 레플리카 | 1 |
| 이미지 | postgres:15 |
| 포트 | 5432 |
| 전략 | Recreate |
| imagePullPolicy | IfNotPresent |
| 환경 변수 | POSTGRES_DB + Secret 참조 |
| Service 타입 | ClusterIP |
- 데이터베이스는 replicas 1로 설정합니다. 데이터 정합성을 위해 단일 인스턴스로 운영합니다.
- 전략을
Recreate로 설정합니다. 데이터베이스는 동시에 여러 Pod가 같은 볼륨에 접근하면 문제가 발생할 수 있습니다. - 외부 노출이 불필요하므로
ClusterIP를 사용합니다.
생성되는 YAML 확인
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: my-web-app
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
strategy:
type: Recreate
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
ports:
- containerPort: 5432
imagePullPolicy: IfNotPresent
env:
- name: POSTGRES_DB
value: myapp
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
---
apiVersion: v1
kind: Service
metadata:
name: postgres-svc
namespace: my-web-app
spec:
type: ClusterIP
selector:
app: postgres
ports:
- name: tcp
protocol: TCP
port: 5432
targetPort: 5432
Ingress
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | app-ingress |
| 네임스페이스 | my-web-app |
| Ingress Class | traefik |
| 호스트 | app.example.com |
| TLS | app-tls-secret |
| 라우팅 | /api → backend-svc:3000, / → frontend-svc:80 |
/api경로를/보다 먼저 정의합니다. Ingress는 순서대로 매칭하므로,/api요청이 프론트엔드로 가지 않도록 합니다.- TLS를 설정하여 HTTPS를 활성화합니다.
생성되는 YAML 확인
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: my-web-app
spec:
ingressClassName: traefik
tls:
- secretName: app-tls-secret
hosts:
- app.example.com
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend-svc
port:
number: 3000
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
예시 2: 고급 프로젝트 (Volume + Job + ConfigMap)
Spring Boot API + PostgreSQL로 구성된 프로젝트에 ConfigMap으로 설정 분리, PVC로 데이터 영구 저장, Job으로 DB 마이그레이션을 추가한 예시입니다.
서비스 구성도
[ConfigMap: app-config] ← 환경 설정 (DB 접속 정보, 로그 레벨 등)
│
├── envFrom ──→ [Job: db-migrate] ← 마이그레이션 실행 후 종료
│
└── envFrom ──→ [Deployment: api-server]
│
└──→ [Service: api-svc] → [Ingress: api-ingress]
[PVC: postgres-data] ← 10Gi 영구 스토리지
│
└── mount ──→ [Deployment: postgres]
│
└──→ [Service: postgres-svc]
생성되는 리소스
- ConfigMap 1개 (app-config)
- PVC 1개 (postgres-data)
- Job 1개 (db-migrate)
- Deployment 2개 (api-server, postgres)
- Service 2개 (api-svc, postgres-svc)
- Ingress 1개 (api-ingress)
파일 구성
k8s/
├── configmap.yaml ← app-config
├── pvc.yaml ← postgres-data
├── job.yaml ← db-migrate
├── deployment.yaml ← api-server + postgres Deployment
├── service.yaml ← api-svc + postgres-svc
└── ingress.yaml ← api-ingress
ConfigMap
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | app-config |
| 네임스페이스 | my-api-project |
| 데이터 | DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, LOG_LEVEL, SERVER_PORT, SPRING_PROFILES_ACTIVE |
- DB 접속 정보, 로그 레벨, 서버 설정 등을 한곳에서 관리합니다.
- Deployment와 Job이 동일한 ConfigMap을 참조하므로 설정 불일치를 방지합니다.
생성되는 YAML 확인
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: my-api-project
labels:
app: app-config
data:
DATABASE_HOST: postgres-svc
DATABASE_PORT: "5432"
DATABASE_NAME: myapi
LOG_LEVEL: info
SERVER_PORT: "8080"
SPRING_PROFILES_ACTIVE: production
PersistentVolumeClaim
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | postgres-data |
| 네임스페이스 | my-api-project |
| 용량 | 10Gi |
| 스토리지 클래스 | nfs-client |
| 접근 모드 | ReadWriteOnce |
ReadWriteOnce로 설정합니다. 데이터베이스는 단일 노드에서만 접근하면 됩니다.nfs-client를 사용하면 NFS 서버에 데이터가 저장되어 노드 장애에도 데이터가 유지됩니다.
생성되는 YAML 확인
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
namespace: my-api-project
labels:
app: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-client
resources:
requests:
storage: 10Gi
Job — DB 마이그레이션
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | db-migrate |
| 네임스페이스 | my-api-project |
| 이미지 | harbor.example.com/my-project/api-server:v1.0 |
| 커맨드 | java -jar app.jar --spring.flyway.enabled=true --spring.main.web-application-type=none |
| envFrom | app-config (ConfigMap) + db-credentials (Secret) |
| backoffLimit | 3 |
| restartPolicy | OnFailure |
- 애플리케이션과 동일한 이미지를 사용하되, Flyway 마이그레이션만 실행하고 웹 서버는 시작하지 않습니다.
envFrom으로 ConfigMap과 Secret 전체를 환경 변수로 주입합니다. 개별 키를 하나씩 매핑할 필요가 없습니다.backoffLimit: 3으로 설정하여 DB 연결 실패 등 일시적 오류에 대비합니다.
Job은 Deployment와 동시에 생성됩니다. 마이그레이션이 완료되기 전에 애플리케이션이 시작될 수 있으므로, 애플리케이션에서 DB 연결 재시도 로직이 필요합니다. 또는 initContainers를 활용하여 마이그레이션 완료를 대기하도록 구성할 수 있습니다.
생성되는 YAML 확인
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
namespace: my-api-project
labels:
app.kubernetes.io/part-of: db-migrate
app.kubernetes.io/component: db-migrate
spec:
backoffLimit: 3
template:
spec:
restartPolicy: OnFailure
containers:
- name: db-migrate
image: harbor.example.com/my-project/api-server:v1.0
command:
- java
args:
- -jar
- app.jar
- --spring.flyway.enabled=true
- --spring.main.web-application-type=none
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-credentials
API Server — Deployment & Service
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | api-server |
| 네임스페이스 | my-api-project |
| 레플리카 | 3 |
| 이미지 | harbor.example.com/my-project/api-server:v1.0 |
| 포트 | 8080 |
| 전략 | RollingUpdate (maxSurge: 1, maxUnavailable: 0) |
| envFrom | app-config (ConfigMap) + db-credentials (Secret) |
| 리소스 | requests: 300m/512Mi, limits: 1/1Gi |
| 헬스체크 | Liveness + Readiness (/actuator/health:8080) |
| Service 타입 | ClusterIP |
envFrom으로 ConfigMap과 Secret을 통째로 주입합니다. Job과 동일한 설정을 공유합니다.- Spring Boot의 Actuator 헬스체크 엔드포인트(
/actuator/health)를 사용합니다. - JVM 기반 애플리케이션은 시작이 느리므로
initialDelaySeconds를 넉넉하게 설정합니다.
생성되는 YAML 확인
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
namespace: my-api-project
labels:
app: api-server
spec:
replicas: 3
selector:
matchLabels:
app: api-server
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: api-server
spec:
containers:
- name: api-server
image: harbor.example.com/my-project/api-server:v1.0
ports:
- containerPort: 8080
imagePullPolicy: Always
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-credentials
resources:
requests:
cpu: 300m
memory: 512Mi
limits:
cpu: "1"
memory: 1Gi
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: api-svc
namespace: my-api-project
spec:
type: ClusterIP
selector:
app: api-server
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
Database — Deployment & Service (PVC 연결)
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | postgres |
| 네임스페이스 | my-api-project |
| 레플리카 | 1 |
| 이미지 | postgres:15 |
| 포트 | 5432 |
| 전략 | Recreate |
| 환경 변수 | POSTGRES_DB, PGDATA + Secret 참조 |
| 볼륨 마운트 | postgres-data PVC → /var/lib/postgresql/data |
| Service 타입 | ClusterIP |
volumeMounts와volumes로 PVC를 연결합니다. Pod가 재시작되어도/var/lib/postgresql/data의 데이터가 유지됩니다.PGDATA환경 변수로 데이터 디렉토리를 하위 폴더(pgdata)로 지정합니다. NFS 마운트 시 루트 디렉토리에 숨김 파일이 있으면 PostgreSQL 초기화가 실패할 수 있기 때문입니다.
생성되는 YAML 확인
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: my-api-project
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
strategy:
type: Recreate
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
ports:
- containerPort: 5432
imagePullPolicy: IfNotPresent
env:
- name: POSTGRES_DB
value: myapi
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-data
---
apiVersion: v1
kind: Service
metadata:
name: postgres-svc
namespace: my-api-project
spec:
type: ClusterIP
selector:
app: postgres
ports:
- name: tcp
protocol: TCP
port: 5432
targetPort: 5432
Ingress
KIWI 설정 요약:
| 옵션 | 값 |
|---|---|
| 이름 | api-ingress |
| 네임스페이스 | my-api-project |
| Ingress Class | traefik |
| 호스트 | api.example.com |
| TLS | api-tls-secret |
| 라우팅 | / → api-svc:8080 |
생성되는 YAML 확인
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: my-api-project
spec:
ingressClassName: traefik
tls:
- secretName: api-tls-secret
hosts:
- api.example.com
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 8080
관련 가이드
- K8s 배포 - 생성된 YAML로 실제 배포 실행
- 롤백 - 문제 발생 시 이전 버전으로 복원
- 도메인/SSL 설정 - 커스텀 도메인 및 HTTPS 설정
- HPA 자동 확장 - 트래픽에 따른 Pod 자동 확장