Deployment๋ก ๋ง๋ ํ๋๋ ์ฃฝ์ผ๋ฉด ์๋ก ํ์ด๋ฉ๋๋ค. ๋ฌธ์ ๋ ๊ทธ ์์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ ๊ฐ์ด ์ฌ๋ผ์ง๋ค๋ ๊ฒ๋๋ค. MySQL ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ Deployment๋ก ์ฌ๋ฆฌ๋ฉด ํ๋๊ฐ ์ฌ์์๋ ๋๋ง๋ค ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฒ์ด PersistentVolume(PV) ๊ณผ PersistentVolumeClaim(PVC), ๊ทธ๋ฆฌ๊ณ StatefulSet์ ๋๋ค.
๐งฉ ๊ฐ๋ ์ ๋ฆฌ โ ์ธ ๊ฐ์ง ์ฉ์ด ํ ๋ฒ์
| ๊ฐ๋ | ์ค๋ช | ๋น์ |
|---|---|---|
| PV | ์ค์ ์คํ ๋ฆฌ์ง ๊ณต๊ฐ | ์ฐฝ๊ณ ์์ฒด |
| PVC | PV๋ฅผ ์ฌ์ฉํ๊ฒ ๋ค๋ ์์ฒญ์ | ์ฐฝ๊ณ ์๋ ๊ณ์ฝ์ |
| StorageClass | PVC ์์ฒญ ์ PV๋ฅผ ์๋ ์์ฑํ๋ ๊ด๋ฆฌ์ | ์ฐฝ๊ณ ํ์ฌ |
| StatefulSet | ํ๋์ ๊ณ ์ ์ด๋ฆ๊ณผ ์คํ ๋ฆฌ์ง๋ฅผ ๋ถ์ฌ | ๊ณ ์ ์๋ฆฌ๊ฐ ์๋ ์ง์ |
๐ ๏ธ ๊ตฌ์ฑ ๊ณผ์
Step 1: StorageClass ์ค์น
ํด๋ผ์ฐ๋๊ฐ ์๋ ๋ก์ปฌ ํด๋ฌ์คํฐ์์๋ ์คํ ๋ฆฌ์ง๋ฅผ ์๋์ผ๋ก ํ๋ก๋น์ ๋ํด์ฃผ๋ ๊ด๋ฆฌ์๊ฐ ์์ต๋๋ค. local-path-provisioner๋ฅผ ์ค์นํ๋ฉด PVC ์์ฒญ์ด ๋ค์ด์ฌ ๋ ํธ์คํธ ๊ฒฝ๋ก์์ ์๋์ผ๋ก PV๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.26/deploy/local-path-storage.yaml
# ์ค์น ํ์ธ
kubectl get sc
# local-path (default) rancher.io/local-path โ ์ด๊ฒ ๋ณด์ด๋ฉด ์ฑ๊ณต
Step 2: MySQL StatefulSet ๋ฐฐํฌ
# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "password123"
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
# ํต์ฌ! ํ๋๋ง๋ค ๊ฐ๋ณ PVC๋ฅผ ์๋ ์์ฑ
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: local-path
resources:
requests:
storage: 5Gi
volumeClaimTemplates ๋๋ถ์ ์๋์ผ๋ก PV/PVC๋ฅผ ๋ง๋ค์ง ์์๋, ํ๋ ์์ฑ ์ ์๋์ผ๋ก 5Gi ์คํ ๋ฆฌ์ง๊ฐ ํ ๋น๋ฉ๋๋ค.
kubectl apply -f mysql-statefulset.yaml
# ํ๋ ์ด๋ฆ์ด mysql-0 ์ผ๋ก ๊ณ ์ ๋จ (Deployment์ ๋ค๋ฆ)
kubectl get pods
kubectl get pvc # PVC๊ฐ ์๋ ์์ฑ๋๋์ง ํ์ธ
Step 3: ๋ฐ์ดํฐ ๋ฃ๊ธฐ
# MySQL ํ๋ ๋ด๋ถ ์ ์
kubectl exec -it mysql-0 -- mysql -u root -ppassword123
# ๋ฐ์ดํฐ ์์ฑ
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');
SELECT * FROM users;
๐ฅ ํต์ฌ ์คํ โ ํ๋๋ฅผ ๊ฐ์ ๋ก ์ฃฝ์ฌ๋ดค๋ค
# mysql-0 ํ๋ ๊ฐ์ ์ญ์
kubectl delete pod mysql-0
StatefulSet ์ปจํธ๋กค๋ฌ๊ฐ ์ฆ์ ๊ฐ์ ์ด๋ฆ์ mysql-0 ํ๋๋ฅผ ์๋ก ๋ง๋ญ๋๋ค. ์ฌ์์ฑ๋ ํ๋์ ์ ์ํด์ ๋ฐ์ดํฐ๋ฅผ ํ์ธํด๋ดค์ต๋๋ค.
MySQL [testdb]> SELECT * FROM users;
+------+-------+
| id | name |
+------+-------+
| 1 | Alice |
| 2 | Bob |
+------+-------+
ํ๋๊ฐ ๊ต์ฒด๋๋๋ฐ๋ ๋ฐ์ดํฐ๊ฐ ์๋ฒฝํ๊ฒ ๋ณด์กด๋ฉ๋๋ค! ๐
๐ ์ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ผ์ง์ง ์์๊น? โ ๋ด๋ถ ๋์ ์๋ฆฌ
โ ํ๋๋ ๋ฐ๋์ด๋ ์ด๋ฆ์ด ๊ณ ์
Deployment๋ ํ๋๊ฐ ์ฃฝ๊ณ ์ด์๋๋ฉด ์ด๋ฆ์ด ๋ฐ๋๋๋ค (nginx-xh52a โ nginx-q91kz). StatefulSet์ **ํญ์ mysql-0**์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ค์ ํ์ด๋ฉ๋๋ค.
โก PVC๋ ํ๋์ ์๋ช ์ด ๋ค๋ฅด๋ค
ํ๋๋ฅผ ์ญ์ ํด๋ PVC(์คํ ๋ฆฌ์ง ์๋ ๊ณ์ฝ)๋ ์ญ์ ๋์ง ์๊ณ ๋จ์์์ต๋๋ค.
ํ๋ ์ญ์ ์ : mysql-0 โ pvc-mysql-0 (๊ณ์ฝ ์ ์ง)
ํ๋ ์ฌ์์ฑ: mysql-0 (์ ํ๋) โ ์๊ธฐ ์ด๋ฆํ ํ์ธ โ pvc-mysql-0 ์ ์ฌ์ฐ๊ฒฐ
“๊ฑด๋ฌผ(Pod)์ ๋ฌด๋์ ธ์ ์๋ก ์ง์์ง๋ง, ์ฃผ์(PVC)๊ฐ ๋ณํ์ง ์์๊ธฐ ๋๋ฌธ์ ๊ฐ๊ตฌ(Data)๋ ๊ทธ ์๋ฆฌ์ ๊ทธ๋๋ก ๋จ์์์๋ค.”
๐ก Deployment vs StatefulSet โ ์ธ์ ๋ญ ์ฐ๋?
| ํญ๋ชฉ | Deployment | StatefulSet |
|---|---|---|
| ํ๋ ์ด๋ฆ | ๋๋ค (nginx-xh52a) | ์์ ๊ณ ์ (mysql-0, mysql-1) |
| ์คํ ๋ฆฌ์ง | ๊ณต์ ๋ณผ๋ฅจ ๋๋ ์์ | ํ๋๋ง๋ค ๋ ๋ฆฝ PVC |
| ์ค์ผ์ผ๋ง ์์ | ๋๋ค | ์์๋๋ก (0โ1โ2) |
| ์ฌ์ฉ ์ผ์ด์ค | ๋ฌด์ํ ์น ์ฑ | DB, Kafka, Elasticsearch ๋ฑ |
โ ์ ๋ฆฌ
PV/PVC์ StatefulSet์ ์ฟ ๋ฒ๋คํฐ์ค์์ “์ํ๊ฐ ์๋ ์ ํ๋ฆฌ์ผ์ด์ (Stateful Application)” ์ ๋ค๋ฃจ๋ ํต์ฌ ํจํด์ ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฟ ๋ฒ๋คํฐ์ค์์ ์ด์ํ๋ ค๋ฉด ๋ฐ๋์ ์์์ผ ํฉ๋๋ค.
๋ค์ ๊ธ์์๋ ํด๋ฌ์คํฐ ๋ณด์์ ํต์ฌ์ธ RBAC(์ญํ ๊ธฐ๋ฐ ์ ๊ทผ ์ ์ด) ๋ฅผ ๋ค๋ฃน๋๋ค.