- 기본 스토리지 운영환경을 분리시켜서 사용할 수 있다.
- 관리자: 스토리지 구성 (PV)
- 개발자: 필요한 만큼 요구 (PVC)
- 일반적으로 Pod가 재시작되면 데이터가 사라지는데( emptyDir 라는 일시적인 공간에 저장), PV & PVC를 사용하면 데이터를 유지할 수 있다.
- Pod가 PVC를 마운트하여 스토리지를 사용하며, PVC가 삭제되면 PV는 설정된 정책에 따라 처리된다.
실습] /log의 데이터가 /var/log/webapp에 저장될 수 있도록 volume configure
controlplane ~ ➜ kubectl edit pod webapp
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-xhjhq
readOnly: true
- mountPath: /log
name: log-volume
...
volumes:
- name: log-volume
hostPath:
path: /var/log/webapp
controlplane ~ ✖ kubectl replace --force -f /tmp/kubectl-edit-2279183393.yaml
pod "webapp" deleted
pod/webapp replaced
controlplane /var/log/webapp ➜ ls
app.log # Mount 된 것 확인
# PersistentVolumes (PV)
- PV는 클러스터 내에서 독립적으로 관리되는 스토리지 리소스이다. ( 쉽게 말해 애플리케이션이 쓰는 Disk를 모아놓은 Pool이 PV이다.)
- Access Modes
- RWO - ReadWriteOnce: 하나의 노드에서 읽기/쓰기 가능 (대부분의 블록 스토리지)
- ROX - ReadOnlyMany
- RWX - ReadWriteMany: 여러 노드에서 읽기/쓰기 가능 (NFS, CephFS 등)
- RWOP - ReadWriteOncePod: 하나의 Pod에서만 읽기/쓰기 가능
controlplane ➜ vi pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-log
spec:
capacity:
storage: 100Mi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /pv/log
controlplane ➜ kubectl create -f pv.yaml
persistentvolume/pv-log created
controlplane ➜ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv-log 100Mi RWX Retain Available <unset> 6s
# 실습 : NFS 기반의 PV
[master ~/Getting-Start-Kubernetes/14]$kubectl get pv
No resources found
[master ~/Getting-Start-Kubernetes/14]$cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
capacity:
storage: 2Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
storageClassName: manual
persistentVolumeReclaimPolicy: Delete
nfs:
server: 127.27.20.50
path: /sharedir/k8s
[master ~/Getting-Start-Kubernetes/14]$kubectl get pv
No resources found
[master ~/Getting-Start-Kubernetes/14]$kubectl apply -f pv.yaml
persistentvolume/pv1 created
[master ~/Getting-Start-Kubernetes/14]$kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv1 20Gi RWX Delete Available manual 3s
# PersistentVolumesClaims
- Pod가 PV를 직접 사용할 수 없기 때문에, PVC를 통해 스토리지를 요청하는 방식이다.
- 즉, PersistentVolumesClaims (PVC)은 사용자의 스토리지에 대한 요청이다.
- 쿠버네티스는 해당 PVC에 맞는 PV를 찾아서 자동으로 연결해준다.
controlplane ~ ➜ vi pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim-log-1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Mi
controlplane ~ ➜ kubectl create -f pvc.yaml
persistentvolumeclaim/claim-log-1 created
controlplane ~ ➜ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
claim-log-1 Pending <unset> 5s
# ACCESS MODES 불일치가 되면 이렇게 Pending상태가 된다.
# PVC를 ReadWriteMany 모드로 바꿔준다.
controlplane ~ ➜ vi pvc.yaml
controlplane ~ ➜ kubectl replace --force -f pvc.yaml
persistentvolumeclaim "claim-log-1" deleted
persistentvolumeclaim/claim-log-1 replaced
controlplane ~ ➜ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
claim-log-1 Bound pv-log 100Mi RWX <unset> 11s
# 100Mi로 바뀌었다.
- 새롭게 만든 PVC를 Pod에 업데이트하기
- volume으로 Claim하기
- Claim을 volume 으로 사용해서 파드가 스토리지에 접근
- Claim 은 Claim 을 사용하는 파드와 동일한 네임스페이스에 있어야 한다.
- 클러스터는 파드의 네임스페이스에서 클레임을 찾고 이를 사용하여 클레임과 관련된 PV을 얻는다. 그런 다음 볼륨이 호스트와 파드에 마운트된다.
- volume으로 Claim하기
controlplane ~ ➜ kubectl edit pod webapp
volumes:
- persistentVolumeClaim:
claimName: claim-log-1
name: log-volume
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes
PV 삭제 정책(persistentVolumeReclaimPolicy)
PV가 더 이상 사용되지 않을 때, 어떻게 처리할지 결정하는 옵션이다.
Retain: PV를 유지 (데이터 삭제 X)
Recycle: PV를 삭제하고 초기화 후 다시 사용 (현재는 deprecated)
Delete: PVC가 삭제되면 PV도 함께 삭제됨 (AWS EBS, GCE PD 등에서 사용)
controlplane ~ ➜ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv-log 100Mi RWX Retain Bound default/claim-log-1 <unset> 17m
# Retain 정책 사용
controlplane ~ ➜ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
claim-log-1 Bound pv-log 100Mi RWX <unset> 10m
controlplane ~ ➜ kubectl delete pvc claim-log-1
persistentvolumeclaim "claim-log-1" deleted
controlplane ~ ➜ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
claim-log-1 Terminating pv-log 100Mi RWX <unset> 11m
controlplane ~ ➜ kubectl describe pvc claim-log-1
Name: claim-log-1
Namespace: default
StorageClass:
Status: Terminating (lasts 2m5s) # Terminating에서 멈춰있다.( pv-log pod에서 사용중이기 때문에)
Volume: pv-log
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 100Mi
Access Modes: RWX
VolumeMode: Filesystem
Used By: webapp
Events: <none>
# 파드를 삭제한다면
controlplane ~ ➜ kubectl delete pod webapp
pod "webapp" deleted
controlplane ~ ➜ kubectl get pvc
No resources found in default namespace.
# 삭제됐다.
controlplane ~ ➜ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv-log 100Mi RWX Retain Released default/claim-log-1 <unset> 24m
# PV는 Released 상태가 된다.
# PVC 실습
[master ~/Getting-Start-Kubernetes/14]$cat pvc-pod-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- image: nginx:1.14
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html # pvc의 이름 선언
persistentVolumeClaim:
claimName: pvc-web # pvc 이름
[master ~/Getting-Start-Kubernetes/14]$kubectl apply -f pvc-pod-web.yaml
pod/web created
[master ~/Getting-Start-Kubernetes/14]$kubectl get pods
NAME READY STATUS RESTARTS AGE
web 1/1 Running 0 19s
[master ~/Getting-Start-Kubernetes/14]$kubectl describe pod web
Name: web
Namespace: default
Priority: 0
Service Account: default
Node: gke-cluster-1-default-pool-697aeef7-xlub/10.128.0.16
...
Volumes:
html:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc-web
ReadOnly: false
[master ~/Getting-Start-Kubernetes/14]$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 0/1 ContainerCreating 0 2m28s 10.32.0.2 gke-cluster-1-default-pool-697aeef7-xlub <none> <none>
StorageClass
일반적으로 Pod가 스토리지를 직접 사용하지 않고, PVC를 통해 요청해야 접근할 수 있다. 스토리지 클래스 (StorageClass)를 사용하면 동적으로 PV를 생성할 수도 있다.
StorageClass를 사용하면 스토리지가 자동으로 생성되기 때문에 PV를 정의하지 않아도 된다.
PVC Definition에 StorageClass 이름을 지정한다.
- 스토리지 클래스는 특정 프로비저너를 사용하여 동적으로 영구 볼륨을 생성한다.
- PROVISIONER란 특정 스토리지 클래스를 사용하여 영구 볼륨(Persistent Volume, PV)을 생성하는 데 사용되는 프로비저닝(provisioning) 플러그인
# 스토리지 조회하기
controlplane ~ ➜ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 6m53s
local-storage kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 9s
portworx-io-priority-high kubernetes.io/portworx-volume Delete Immediate false 9s
# local-path는 로컬 경로 기반의 스토리지를 제공하는 프로비저너
# no-provisioner: 수동으로 영구 볼륨을 프로비저닝해야 함
# local-stroage 사용하는 pvc만들기
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 500Mi
storageClassName: local-storage
controlplane ~ ➜ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
local-pvc Pending local-storage <unset> 4s
PVC가 PV를 사용하지 않으면 waiting for first consumer to be created before binding이유로 Pending이 된다.
controlplane ~ ➜ kubectl describe pvc local-pvc
Name: local-pvc
Namespace: default
StorageClass: local-storage
Status: Pending
Volume:
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal WaitForFirstConsumer 10s (x12 over 2m51s) persistentvolume-controller waiting for first consumer to be created before binding
# Pod 생성
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx:alpine
name: nginx
resources: {}
volumeMounts: # 컨테이너 내의 디렉토리에 연결
- mountPath: "/var/www/html"
name: local-pvc-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
volumes: # PVC 참조
- name: local-pvc-volume
persistentVolumeClaim:
claimName: local-pvc
# local-pvc로 요청된 스토리지를 /var/www/html에 마운트한다.
controlplane ~ ➜ kubectl create -f nginx.yaml
pod/nginx created
controlplane ~ ➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 9s
controlplane ~ ➜ kubectl create -f delayed-volume-sc.yaml
storageclass.storage.k8s.io/delayed-volume-sc created
controlplane ~ ➜ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
delayed-volume-sc kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 42s
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 60m
local-storage kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 54m
portworx-io-priority-high kubernetes.io/portworx-volume Delete Immediate false 54m
- VOLUMEBINDINGMODE: Persistent Volume (PV)이 Persistent Volume Claim (PVC)와 바인딩되는 시점을 제어한다.
- Immediate (기본값) : PVC가 생성되면 즉시 PV와 바인딩
- 스토리지 리소스가 클러스터의 어떤 노드에 있든지 상관없이 PVC가 요청하는 즉시 바인딩이 이루어짐을 의미한다.
- WaitForFirstConsumer: PVC가 생성되더라도, 해당 PVC가 사용될 Pod가 실제로 스케줄링되기 전까지 PV와 바인딩되지 않는다.
- Immediate (기본값) : PVC가 생성되면 즉시 PV와 바인딩
반응형
'Container > Kubernetes' 카테고리의 다른 글
[K8S] ETCD Backup 및 Restore (0) | 2024.04.21 |
---|---|
[K8S] Kubernetes DNS (0) | 2024.04.21 |
CKA 시험준비 (0) | 2024.04.16 |
[K8S] cordon & drain (0) | 2024.04.13 |
[K8S] Taint & Toleration (0) | 2024.04.12 |