[Kubernetes] Volume(볼륨) 정리
안녕하세요? 정리하는 개발자 워니즈 입니다. 이번시간에는 쿠버네티스의 볼륨에 대해서 정리를 해보고자 합니다.
지난 글들은 아래를 참고 해주시면 됩니다.
- 쿠버네티스 1편 : 설치 가이드
- 쿠버네티스 2편 : pod
- 쿠버네티스 3편 : service
- 쿠버네티스 4편 : deployment
- 쿠버네티스 5편 : pod 설정
- 쿠버네티스 6편 : 배포 전략
- 쿠버네티스 7편 : volume
- 쿠버네티스 8편 : daemonset
- 쿠버네티스 9편 : 테라폼을 통한 클러스터 구성
- 쿠버네티스 10편 : eks에서 volume 사용하기
- 쿠버네티스 11편 : helm
- 쿠버네티스 12편 : helm chart template
- 쿠버네티스 13편 : helm deploy
- 쿠버네티스 14편 : fluentd를 통한 log수집
- 쿠버네티스 15편 : chartmuseum
- 쿠버네티스 16편 : 배포툴(ArgoCD 설치방법/사용법)
- 쿠버네티스 17편 : 배포툴(ArgoCD 구성/알람)
- 쿠버네티스 18편 : 쿠버네티스 Autoscailing
- 쿠버네티스 19편 : 쿠버네티스 로깅 아키텍처
도커 컨테이너를 올렸다가 삭제 하게 되면, 내부에서 사용하던 내용물도 모두 사라지게 됩니다.
컨테이너는 기본적으로 상태가 없는 상태에서 구동됩니다. 즉, 컨테이너가 실행되서 상태를 가져도 컨테이너가 종료되면 컨테이너에서 생성되었던 모든 데이터는 사라진다는 뜻입니다. 이것은 Kubernetes상에서 자유롭게 Pod를 복제하고 배포하는데 있어 커다란 장점입니다.
하지만, 로그 및 데이터베이스와 같은 애플리케이션은 종료되더라도 데이터가 유지되어야만 하는 특징이 있습니다. 이런 데이터의 상태를 유지할 수 있도록 사용하는 것이 Volume입니다.
Kubernetes에서는 Docker와는 다르게 Pod 단위로 Volume을 관리하며, Life Cycle과 제공되는 디스크 Type 따라 다양한 옵션과 종류가 존재합니다. 이 장에서는 Kubernetes의 영구 Volume체계인 PersistentVolume(PV)와 PersistentVolumeClaim(PVC)에 대해 살펴봅니다.
1. Volume 종류
Volume은 제공되는 디스크 Type에 따라 여러가지 종류의 Volume Type을 지원합니다.
Temp | Local | Network |
---|---|---|
emptyDir | hostPath | NFS, AWS EBS.. |
- emptyDir은 동일한 Pod내에서 사용가능한 임시 Volume으로 Pod가 삭제되면 Volume의 데이터도 같이 삭제됩니다.
- hostPath는 특정 노드에 mount된 파일시스템을 Volume으로 사용합니다. 본 교육에서는 로컬 VM환경이므로 HostPath Type으로 실습하는 예제입니다.
- Network : 네트워크 또는 클라우드 상에 존재하는 storage를 Volume으로 사용합니다.
2. Volume Provisioning 에 따른 분류
Kubernetes에서는 자동으로 Volume을 생성할 수 있느냐 없느냐에 따라 Static Volume Provisioning과 DynamicVolume Provisoning으로 구분할 수 있는데,
- Static Volume Provisioning : 관리자가 수동으로 Kubernetes에서 Persistent Volume을 생성
- DynamicVolume Provisoning : 개발자의 요청에 의해 자동으로 Kubernetes에서 Persistent Volume을 생성
즉, DynamicVolume Provisoning은 개발자나 클라우드 사용자가 손쉽게 Volum사용요청(PVC) 만으로 Volume을 사용할 수 있습니다.
3. Persistent Volume(PV) & Persistent Volume Claim(PVC)
쿠버네티스에서 볼륨을 사용하는 구조는 스토리지를 매핑시킨 PersistentVolume(PV)과 그 PV를 Pod에서 사용할때 PV로 Volume내역을 요청하는 PersistentVolumeClaim(PVC) 2단계로 분리되어 있습니다.
PV는 Storage와 mount되어 있으므로 쉽게말해 볼륨 또는 Storage 자체를 의미합니다.
PVC는 개발자 또는 클라우드 사용자가 PV에게 Volume을 할당해달라는 요청입니다. 사용하고 싶은 용량과 각종 Volume에 관한 설정값을 정해서 요청하게 됩니다.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
Phase
Volume은 아래와 같은 상태를 가집니다. 해당 상태는 PV이 배포되고, kubectl get pv 명령을 통해 조회할 수 있습니다.
- Available – PV가 생성되고 PVC가 바인딩되기 전 상태
- Bound – PVC가 PV에 바인된 상태
- Released – PVC가 삭제된 상태
- Failed – 실패상태
Access Modes
- ReadWriteOnce – 단일 노드에 의한 읽기-쓰기로 볼륨이 마운트될 수 있습니다.
- ReadOnlyMany – 여러 노드에 의한 읽기 전용으로 볼륨이 마운트될 수 있습니다.
- ReadWriteMany – 여러 노드에 의한 읽기-쓰기로 볼륨이 마운트될 수 있습니다.
CLI에서는 아래와 같이 표시됩니다.
- RWO – ReadWriteOnce
- ROX – ReadOnlyMany
- RWX – ReadWriteMany
Reclaim Policy
PV와 바인딩된 PVC를 삭제했을때 PV는 Released 상태로 변경됩니다. 이때 PV와 연결된 디스크의 파일들을 어떻게 처리할 것인지에 대한 설정으로 아래와 같이 설정할 수 있습니다.
- Retain – PVC가 삭제되어도 PV 및 데이터 유지(다시 쓰기 위해서는 PV를 삭제하고 재생성해야함)
- Recycle – PV는 유지하고 파일만 삭제 (
rm -rf /thevolume/*
) - Delete – 볼륨 및 데이터 삭제
4. PersistentVolumeClaims
Each PVC contains a spec and status, which is the specification and status of the claim.
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
Claims As Volumes
Pod는 아래와 같이 PVC로 PV에 접근할 수 있습니다.
kind: Pod
apiVersion: v1
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
5. 실습 예제
Create a Secret for MySQL Password
실습에서 사용할 mysql 패스워드를 secret으로 생성해두겠습니다.
# kubectl create secret generic mysql-pass --from-literal=password=pwd
Volume
Create PersistentVolumes
PersistentVolume yaml파일 생성
apiVersion: v1
kind: PersistentVolume
metadata:
name: wp-pv-volume
labels:
type: local
spec:
capacity:
storage: 3Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: "/data/mysql"
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node
Create PersistentVolumeClaims
PersistentVolumeClaims yaml 파일 생성
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-pv-claim
spec:
storageClassName: local-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
selector:
matchLabels:
type: local
Backend
Creating a Mysql Pod
Mysql Pod yaml파일 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: mysql
spec:
containers:
- image: mysql:5.6
imagePullPolicy: Always
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
Creating a Mysql Service
Mysql Service yaml 파일 생성
apiVersion: v1
kind: Service
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
clusterIP: None
FrontEnd
Creating a WordPress Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
replicas: 1
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:4.8-apache
imagePullPolicy: Always
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 80
name: wordpress
Creating a WordPress Service
Service yaml파일 생성
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
selector:
app: wordpress
tier: frontend
일괄로 pv, pvc, pod, svc를 생성합니다.
kubectl apply -f /{예제폴더}/
결과확인
root@master:/lab/dashboard# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 172.168.1.1 443/TCP 4h56m
wordpress NodePort 172.168.1.177 8080:32382/TCP 10m
wordpress-mysql ClusterIP None 3306/TCP 10m
브라우저에서 http://localhost:32382 로 접속해봅니다.
node VM에서 mysql데이터가 생성되었는지 확인해봅니다.
root@node:/data/mysql# ll
total 110616
drwxr-xr-x 5 vboxadd vboxsf 4096 12월 5 15:39 ./
drwxr-xr-x 3 root root 4096 12월 5 15:12 ../
-rw-rw---- 1 vboxadd vboxsf 56 12월 5 15:38 auto.cnf
-rw-rw---- 1 vboxadd vboxsf 12582912 12월 5 15:38 ibdata1
-rw-rw---- 1 vboxadd vboxsf 50331648 12월 5 15:38 ib_logfile0
-rw-rw---- 1 vboxadd vboxsf 50331648 12월 5 15:38 ib_logfile1
drwx------ 2 vboxadd vboxsf 4096 12월 5 15:38 mysql/
drwx------ 2 vboxadd vboxsf 4096 12월 5 15:38 performance_schema/
drwx------ 2 vboxadd vboxsf 4096 12월 5 15:39 wordpress/
6. 마치며..
이번시간에는 쿠버네티스 볼륨
에 대해서 알아보는 시간을 갖었습니다. 보통 어플리케이션 로그의 종류를 외부로 빼서 가져가는것 같습니다. 필자가 속한 프로젝트에서도 쿠버네티스 도입을 시도하고있는데, 웹/와스 구조중에 웹쪽을 컨테이너로 넣어서 관리를 할예정입니다.
웹서버에 필요한 로그파일들을 외부의 PV로 빼서 관리를 하게되면, 확인하기도 훨씬 간편하고 POD의 생명주이게 상관없이 로그 보관도 용이할 것 같습니다.
다음 이시간에는 HELM
에 대해서 알아보도록 하겠습니다.