지난 포스팅까지 간단한 풀스택 시스템을 쿠버네티스에 클러스터 적용해보았다. MySQL DB에 데이터를 입력하고 조회까지 하였지만 컨테이너를 내렸다고 올리면 데이터가 모두 사라져 버린다. 컨테이너를 노드 안의 외부볼륨에 마운트 하면 컨테이너가 내려가더라도 데이터를 유지할 수 있다.
( 자세한 코드는 위 깃허브 링크에서 확인할 수 있습니다. )
PV ( Persistent Volume )
볼륨이란 파일시스템을 갖춘 저장공간(Storage)이다. PV는 클러스터 내에 존재하는 볼륨이다. 클러스터가 존재하는 동안 제거되지 않는 저장공간이기에, Persistent(영구적)이라는 말이 붙는다. 파드에서 컨테이너가 올라가면 컨테이너는 PV에 마운트하여 컨테이너 외부볼륨에 접근할 수 있다.
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
volumeMode: Filesystem
capacity:
storage: 3Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
hostPath:
path: /mysql/mysql_data
claimRef:
name: mysql-pvc
namespace: default
PV에서 눈에 띄는 속성을 몇개 살펴보자. persistentVolumeReclaimPolicy 설정은 Retain으로 하였다. PVC가 사라져도 PV 내부 파일을 유지할 수 있도록 하는 설정이다. persistentVolumeReclaimPolicy에 대한 자세한 내용은 아래 포스팅을 참고하면 된다.
hostPath는 PV에 연결된 호스트 머신의 경로를 의미한다. 나는 MiniKube환경을 사용하였으므로, minikube ssh로 미니큐브에 접근하여 해당 경로에 접근할 수 있다. /mysql/mysql_data 경로에 저장된 파일은 PV와 마운트되는 모든 컨테이너가 참조할 수 있다.
PVC ( Persistent Volume Claim )
PVC는 PV의 자원을 어떻게 사용할 건지에 대한 내용을 담은 요청서이다. 어떤 방식으로 접근할 건지, 어느정도 저장공간을 사용할 건지, 사용할 저장공간의 이름은 무엇인지 등등의 내용을 담은 요청이다. 컨테이너가 PV에 마운트하려면 리소스 활용계획을 담은 PVC가 있어야 한다.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 3Gi
storageClassName: ""
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-db
spec:
replicas: 1
selector:
matchLabels:
app: mysql-db
template:
metadata:
labels:
app: mysql-db
spec:
containers:
- name: mysql-db
image: lordofkangs/mysql_db
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_Password
- name: MYSQL_DATABASE
value: myapp
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: mysql-pvc
파드를 배포하는 Deployment yaml 파일이다. 가장 아래를 보면 컨테이너의 volumeMounts 설정이 있다. 외부스토리지에 마운트되어질 컨테이너 내부 경로를 의미한다. 내부경로와 마운트 될 외부스토리지(PV)에 대한 참조정보는 volumes 설정에 명세한다. 이로써 /var/lib/mysql 경로에 생성된 데이터는 모두 PV의 /mysql/mysql_data로 저장되어 진다. 컨테이너가 내려가면 /var/lib/mysql의 데이터는 사라지지만 /mysql/mysql_data 그대로 남아있다. 새로운 컨테이너가 올라오면 /mysql/mysql_data 경로를 참조하여 데이터를 그대로 가져올 수 있다.
그럼 지난포스팅에서 생성한 secret, svc, deployment yaml 파일에 pv, pvc를 추가하여 하나의 yaml 파일을 만들어 테스트 해보자.
mysql-db.yaml
apiVersion: v1
data:
DB_Password: am9obmFobg==
kind: Secret
metadata:
creationTimestamp: null
name: db-secret
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
volumeMode: Filesystem
capacity:
storage: 3Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
hostPath:
path: /mysql/mysql_data
claimRef:
name: mysql-pvc
namespace: default
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 3Gi
storageClassName: ""
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mysql-db
ports:
- protocol: TCP
port: 3306
targetPort: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-db
spec:
replicas: 1
selector:
matchLabels:
app: mysql-db
template:
metadata:
labels:
app: mysql-db
spec:
containers:
- name: mysql-db
image: lordofkangs/mysql_db
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_Password
- name: MYSQL_DATABASE
value: myapp
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: mysql-pvc
테스트해보기
kubectl apply -f mysql-db.yaml
MySQL PV, PVC, SVC, Deployment를 모두 생성하고 ingress 서비스로 접근해보자. ingres서비스는 노드포트 서비스로 30261 포트로 접근할 수 있다.
데이터를 입력하고 컨테이너를 내렸다가 다시 올려도 데이터가 사라지지 않고 유지된다.
minikube ssh
호스트머신인 minikube에 접속하고 PV에 명시한 /mysql/mysql_data 경로에 가보자.
그럼 위와 같이 MySQL 컨테이너에서 생성한 데이터가 저장되어 있음을 확인할 수 있다. 이처럼 PV, PVC를 활용하면 컨테이너에서 생성한 데이터를 외부에 저장할 수 있어 데이터를 유지할 수 있다.
참고자료
'DevOps > K8S' 카테고리의 다른 글
[K8S] Kubernetes 동작원리 (0) | 2024.02.25 |
---|---|
[Kubernetes] NFS 서버에 PV 만들어 접근하기 ( 우분투 환경 ) (0) | 2023.10.16 |
[Kubernetes] ClusterIP, NodePort, LoadBalancer의 차이 (0) | 2023.10.13 |
[Kubernetes] MySQL 서비스 및 디플로이먼트 생성하기 (3) | 2023.10.13 |
[Kubernetes] 프론트엔드, 백엔드 서비스 및 디플로이먼트 생성하기 (0) | 2023.10.12 |