쿠버네티스에서 일반적인 Deployment는 가변적인 Pod 이름을 사용하며, 특정 Pod 간의 고정적인 네트워크 식별자가 필요한 서비스에는 적합하지 않습니다.
반면, StatefulSet을 활용하면 특정 Pod에 고유한 ID와 네트워크 주소를 유지할 수 있어, 데이터베이스 및 상태 기반 애플리케이션을 안정적으로 운영할 수 있습니다.
이 글에서는 StatefulSet을 활용한 고가용성 서비스 구축 및 운영 전략을 다룹니다.
📌 글에서 다루는 상황들
1. StatefulSet을 사용하여 고정된 네트워크 식별자를 가진 Pod 배포
2. Pod 재시작 및 롤링 업데이트 시 데이터 및 네트워크 ID 유지
3. kubectl을 활용한 StatefulSet 운영 및 문제 해결 방법
각 문제를 실무에서 바로 활용할 수 있도록 Manifest 템플릿과 예상 결과 값을 제공합니다.
1️⃣ StatefulSet을 사용하여 고정된 네트워크 식별자를 가진 Pod 배포
❓ 문제 상황
운영팀에서 클러스터 내에서 실행되는 데이터베이스(Persistent 서비스)의 각 인스턴스가 고유한 네트워크 주소를 유지해야 합니다.
이를 위해 StatefulSet을 사용하여 MySQL을 배포하고, 고유한 호스트네임을 유지하도록 설정해야 합니다.
• StatefulSet 이름: mysql
• Pod 네트워크 주소: mysql-0.mysql.default.svc.cluster.local
• PVC(Persistent Volume Claim) 사용하여 데이터 유지
✅ 어떻게 해결할 수 있을까요?
🛠️ 해결 방법
1. StatefulSet을 생성하여 각 Pod에 고정된 네트워크 ID를 부여합니다.
2. Headless Service를 설정하여 각 Pod이 개별적으로 DNS를 통해 접근 가능하도록 합니다.
✅ 정답 Manifest (StatefulSet 및 Headless Service 설정)
🔹 Headless Service (고정 네트워크 ID 유지)
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
clusterIP: None # Headless Service 설정
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
🔹 StatefulSet 설정
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpassword"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
✅ 이제 mysql-0, mysql-1, mysql-2 노드가 각각 고유한 네트워크 주소를 가지며 데이터베이스를 운영 가능
📌 적용 후 예상 결과 값
1. StatefulSet 배포 후 Pod 상태 확인
kubectl get pods -l app=mysql
💡 예상 출력 값
NAME READY STATUS RESTARTS AGE
mysql-0 1/1 Running 0 5m
mysql-1 1/1 Running 0 5m
mysql-2 1/1 Running 0 5m
2. 고유한 네트워크 주소 확인
kubectl exec -it mysql-0 -- hostname
💡 예상 출력 값
mysql-0
✅ 각 Pod이 고유한 네트워크 ID를 유지함
2️⃣ Pod 재시작 및 롤링 업데이트 시 데이터 및 네트워크 ID 유지
❓ 문제 상황
운영팀에서 MySQL 인스턴스를 업데이트해야 하지만, 기존 데이터가 유지되도록 해야 합니다.
Deployment와 달리, StatefulSet은 기존 네트워크 ID 및 Persistent Volume을 유지하면서 롤링 업데이트를 수행해야 합니다.
• MySQL 이미지 버전: mysql:5.7 → mysql:8.0
• 기존 데이터 유지 필수
✅ 어떻게 해결할 수 있을까요?
🛠️ 해결 방법
1. StatefulSet의 업데이트 전략을 RollingUpdate로 설정하여 하나씩 업데이트되도록 합니다.
2. Pod이 재시작되어도 같은 Persistent Volume을 유지하도록 설정합니다.
✅ StatefulSet 업데이트 적용 (RollingUpdate)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
updateStrategy:
type: RollingUpdate # 한 개씩 순차적으로 업데이트
template:
spec:
containers:
- name: mysql
image: mysql:8.0 # 새로운 버전으로 업데이트
✅ Pod이 하나씩 순차적으로 업데이트되면서 기존 데이터를 유지함
📌 적용 후 예상 결과 값
1. 업데이트 진행 상태 확인
kubectl rollout status statefulset mysql
💡 예상 출력 값
statefulset rolling update complete
2. 데이터 유지 여부 확인
kubectl exec -it mysql-0 -- mysql -uroot -prootpassword -e "SHOW DATABASES;"
💡 예상 출력 값
Database
information_schema
mysql
performance_schema
sys
✅ 업데이트 후에도 기존 데이터가 유지됨
3️⃣ kubectl을 활용한 StatefulSet 운영 및 문제 해결 방법
❓ 문제 상황
운영팀에서 StatefulSet이 정상적으로 동작하고 있는지 모니터링하고, 문제가 발생했을 때 원인을 분석해야 합니다.
kubectl 명령어를 활용하여 현재 배포 상태 및 볼륨 상태를 점검해야 합니다.
✅ 어떻게 해결할 수 있을까요?
🛠️ 해결 방법
1. kubectl get statefulset 명령어를 사용하여 현재 StatefulSet 상태를 확인합니다.
2. kubectl describe 명령어를 활용하여 StatefulSet 및 PersistentVolumeClaim(PVC) 상태를 분석합니다.
✅ StatefulSet 상태 확인 명령어
🔹 현재 StatefulSet 상태 확인
kubectl get statefulset
💡 예상 출력 값
NAME READY AGE
mysql 3/3 10m
🔹 PersistentVolumeClaim 상태 확인
kubectl get pvc
💡 예상 출력 값
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-data-mysql-0 Bound pv-001 10Gi RWO standard 10m
mysql-data-mysql-1 Bound pv-002 10Gi RWO standard 10m
mysql-data-mysql-2 Bound pv-003 10Gi RWO standard 10m
✅ StatefulSet과 연결된 PersistentVolume이 정상적으로 유지됨