Kubernetes(K8s)
> 컨테이너화된 애플리케이션을 자동 배포, 확장, 관리하는 오픈소스 플랫폼
> "컨테이너 오케스트레이션"으로 여러 노드(서버)에 걸쳐 컨테이너를 자동으로 배치하고 관리한다.
구성요소
1. Pod : 가장 작은 배포 단위로, 하나 이상의 컨테이너를 포함
2. Node : 컨테이너가 실행되는 물리적 또는 가상 머신
3. Cluster : 여러 노드의 집합으로, 쿠버네티스 환경 전체를 의미
4. Service : Pod에 대한 네트워크 접근을 제공하는 추상화 계층
1. Dockerfile 작성
FROM gradle:8.5-jdk17 AS builder
WORKDIR /app
COPY . .
RUN gradle clean bootJar --no-daemon
RUN echo "=== build/libs 폴더 내용 ==="
RUN ls -la /app/build/libs/
RUN echo "=== 모든 jar 파일 찾기 ==="
RUN find /app -name "*.jar" -type f
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar ./app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
2. Kubernetes에 배포하기 위한 매니페스트 파일 생성

2.1 backend.yaml
현재 내가 작성한 backend.yaml은 3개의 리소스로 구성되어 있다.
1) Deployment : 애플리케이션 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1 # Pod 1개만 실행(실제 프로덕션에서는 2~3개 권장)
2) Service : 네트워크 접근
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend # backend Deployment의 Pod 선택
ports:
- port: 80 # 서비스 내부 포트
targetPort: 8080 # Pod의 실제 포트
-> 클러스터 내부에서 backend:80으로 접근
-> 트래픽을 Pod의 8080 포트로 전달
3) Ingress : 외부 트래픽 라우팅 (* ingress.yaml을 별도로 빼도 되나 한번에 작성하였다)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend
annotations:
kubernetes.io/ingress.class: nginx # NGINX Ingress Controller 사용
spec:
rules:
- host: XXX배포 도메인 작성XXX
http:
paths:
- path: /api # /api로 시작하는 모든 요청
pathType: Prefix
backend:
service:
name: backend
port:
number: 80
최종 backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: XXX도커이미지파일XXX
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: backend-config
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: XXX배포 도메인XXX
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
number: 80
2.2 kustomization.yaml
resources:
- backend.yaml # 현재 디렉토리의 backend.yaml을 포함
bases:
- ../mysql-k8s/base # MySQL 리소스 참조
configMapGenerator:
- name: backend-config
literals:
- SPRING_PROFILES_ACTIVE=prod
-> configMapGenerator로 ConfigMap을 자동 생성해줬다.
-> backend.yaml에서 envForm으로 참조하는 backend-config가 여기서 생성됨 !
3. MySQL 연결 추가하기

동작 방식
1) StatefulSet이 Pod 생성
2) PVC 자동 생성 : AWS EBS 볼륨이 자동으로 생성됨
3) Pod가 삭제되어도 데이터 유지 : 새 Pod가 생성되면 같은 볼륨을 다시 마운트
3.1 statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-service # Service 이름과 일치해야 함!!
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:lts
ports:
- containerPort: 3306
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "true"
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_USER
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_PASSWORD
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_DATABASE
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
storageClassName: gp2
3.2 service.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
type: ClusterIP
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
배포 완료



* 전체 배포 파이프라인
Spring Boot 프로젝트 생성
-> Git으로 버전 관리
-> Jenkins 빌드 (Docker 이미지 빌드 후 ECR에 푸시) = CI
-> ArgoCD로 쿠버네티스에 배포 = CD
'개발' 카테고리의 다른 글
| ModulePropertiesUtils로 모듈 별 properties 파일 관리하기 (0) | 2025.11.06 |
|---|---|
| Spring AI에 대해 (0) | 2025.10.10 |
| SSG를 사용한 나만의 블로그 만들기 (0) | 2025.09.08 |
| iframe 접근 오류 : X-Frame Deny (0) | 2025.06.16 |
| XMLHttpRequest 객체에 대해 : 서버에 실제 파일이 존재하는지 js로 확인하기 (0) | 2025.01.21 |