도커 컨테이너를 올렸다가 삭제 시, 내부에서 사용하던 내용물들도 모두 사라진다.
컨테이너는 기본적으로 상태가 없는 상태에서 구동된다. 즉, 컨테이너가 실행되서 상태를 가져도 컨테이너가 종료되면 컨테이너에서 생성되었던 모든 데이터는 사라진다. 이것은 Kubernetes 상에서 자유롭게 Pod를 복제하고 배포하는데 있어 커다란 장점이다.
하지만, 로그 및 데이터베이스와 같은 애플리케이션은 종료되더라도 데이터가 유지되어야만 하는 특징이 있다. 이런 데이터의 상태를 유지할 수 있도록 사용하는 것이 Volume이다.
Kubernetes에서는 Docker와는 다르게 Pod 단위로 Volume을 관리하며, Life Cycle과 제공되는 디스크 Type에 따라 다양한 옵션과 종류가 존재한다.
Volume은 제공되는 디스크 Type에 따라 여러가지 올류의 Volume Type을 지원한다.
Temp | Local | Network |
---|---|---|
emptyDir | hostPath | NFS, AWS EBS |
Kubernetes에서는 자동으로 Volume을 생성할 수 있느냐 없느냐에 따라 Static Volume Provisioning과 DynamicVolume Provisoning으로 구분할 수 있다.
즉, Dynamic Volume Provisioning은 개발자나 클라우드 사용자가 손쉽게 Volume 사용 요청(PVC) 만으로 Volume을 사용할 수 있다.
쿠버네티스에서 볼륨을 사용하는 구조는 스토리지를 매핑시킨 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
Volume은 아래와 같은 상태를 가진다. 해당 상태는 PV가 배포되고, kubectl get pv
명령을 통해 조회할 수 있다.
CLI에서는 아래와 같이 표시
PV와 바인딩된 PVC를 삭제했을때 PV는 Released 상태로 변경된다. 이때 PV와 연결된 디스크의 파일들을 어떻게 처리할 것인지에 대한 설정으로 아래와 같이 설정할 수 있다.
각각의 PVC는 spec과 상태를 가진다.
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]}
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
Create a Secret for MySql password
실습에서 사용할 mysql 패스워드를 secret 으로 생성한다.
kubectl create secret generic mysql-pass --from-literal=password=pwd
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
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
Create 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
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
Create 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 <none> 443/TCP 4h56m
wordpress NodePort 172.168.1.177 <none> 8080:32382/TCP 10m
wordpress-mysql ClusterIP None <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/