쿠버네티스인 액션 6장 볼륨

2023. 8. 19. 11:51Kubernetes

6.1 볼륨 소개

 

볼륨은 파드의 구성요소로 컨테이너와 동일하게 파드 스펙에서 정의된다.

볼륨은 독립적인 쿠버네티스 오브젝트가 아니므로 자체적으로 생성, 삭제될수없다.

볼륨은 파드의 모든 컨테이너에서 사용가능하지만 접근하려는 컨테이너에서 각각 마운트돼야한다.

-> 컨테이너 스펙에 VolumeMount를 정의하면 된다. 

 

6.1.2  사용가능한 볼륨 유형 소개

emptyDIr: 일시적인 데이터를 저장하는 데 사용되는 간단한 빈 디렉터리다.

hostPath : 워커노드의 파일 시스템을 파드의 디렉터리로 마운트하는데 사용한다.

gitRepo: 깃 레포지터리의 콘텐츠를 체크아웃해 초기화한 볼륨이다.

nfs: NFS 공유를 파드에 마운트 한다.

gcePersistentDisk, awsElasticBlockStore,azureDIsk: 클라우드 제공자의 전용 스토리지를 마운트하는데 사용한다.

cinder,flexVolume scaleIO: 다른유형의 네트워크 스토리지를 마운트하는데 사용한다.

configMap,secret,downwardApI: 쿠버네티스 리소스나 클러스터 정보를 파드에 노출하는데 사용되는 특별한 유형의 볼륨이다.

PersistentVolumeClaim: 사전에 혹은 동적으로 프로비저닝된 퍼시스턴트 스토리지를 사용하는 방법이다.

 

6.2 볼륨을 사용한 컨테이너간 데이터 공유 

 

6.2.1 emptyDir 볼륨 사용

볼륨이 빈디렉터리로 시작된다. 

- 파드에 실행중인 애플리케이션은 어떤 파일이든 볼륨에 쓸수있다.

- 볼륨의 라이프사이클이 파드에 묶여 있으므로 파드가 삭제되면 볼륨의 컨텐츠는 사라진다.

-동일파드에서 실행중인 컨테이너간 파일을 공유할때 유용하다.

- 단일 컨테이너에서도 가용한 메모리에 넣기에 큰 데이터 세트의 정렬작업을 수행하는것과 같이 임시데이터를 디스크에 쓰는 목적인경우 사용할수있다.

 

emptyDIr 은 가장 단순한 볼륨 유형이지만 다른 유형들도 이 볼륨을 기반으로 한다.

그 중하나가 gitRepo 볼륨이다.

 

gitRepo 볼륨은 기본적으로 emptyDir 볼륨이며 파드가 시작되면 깃 레포지토리를 복제하고 특정 리비전을 체크아웃해 데이터로 채운다.

 

사이드카 컨테이너 소개

새로운 로직을 메인 app코드에 밀어넣어 복잡성을 더하고 재사용성을  떨어트리는 대신에 사이드카를 추가하면 기존 컨테이너 이미지를 사용할수 있다.

 

6.3 워커노드 파일시스템의 파일 접근 

대부분의 파드는 호스트 노드를 인식하지 못하므로 노드의 파일 시스템에 있는 어떤 파일에도 접근하면 안된다.그러나 특정 시스템 레벨의 파드는 노드의 파일을 읽거나 파일 시스템을 통해 노드 디바이스를 접근하기 위해 노드의 파일 시스템을 사용해야한다. 

쿠버네티스는 hostPath 볼륨으로 가능케 한다.

 

6.3.1. hostPath 볼륨 소개

hostPath 볼륨은 노드 파일 시스템의 특정 파일이나 디렉터리를 가리킨다

hostPath 볼륨은 파드가 종료되도 삭제되지 않는다. 

이전 파드가 동일한 노드에 스케줄링 된다는 조건에서 새 파드는 이전파드가 남긴 모든 항목을 볼수있다.

(문제: 노드가 바뀌면 이전 파드의 노드의 볼륨에 남긴 파일은 볼수가 없는거네.)

-> 이 문제 때문에 일반적인 파드에 사용하는것은 좋은 생각이 아니다.

 

kube-system 의 pod들을 살펴보면 노드의 로그파일이나 kubeconfig(쿠버네티스 구성파일),CA 인증서를 접근하기 위해 이 유형의 볼륨을 사용하는것을 볼수있다.

 

hostPath 볼륨을 자체 데이터를 저장하기 위한 목적으로 사용하지 않는다.

단지 노드데이터에 접근하기 위해 사용한다.

팁: 노드의 시스템 파일에 읽기, 쓰기 를 하는 경우에만 hostPath 볼륨을 사용한다는 것을 기억하라. 여러 파드에 걸쳐 데이터를 유지하기 위해서는 절대 사용하지 말라.

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory

 

kube-apiserver 에서 HostPath 를 인증서 확인용으로 씀 

6.4 퍼시스턴트 스토리지 사용

어떤 노드의 파드에서도 접근가능한 볼륨이 되려면 NAS 에 저장되야한다.

-> 우린 NAS 에 어떻게 저장하나? 

: pv 에 nfs 형태로 저장함.

 

 

6.5 기반 스토리지 기술과 파드의 분리 

이상적으로 는 쿠버네티스에 어플리케이션을 배포하는 개발자는 기저에 어떤 종류의 스토리지 기술이 사용되는지 알필요가 없어야 하고 동일한 방식으로 파드를 실행하기 위해어떤 유형의 물리 서버가 사용되는지 알 필요가 없어야 한다.

 

퍼시스턴트 볼륨클레임의 바인딩을 삭제해 릴리스 될때까지 다른 사용자는 동일한 퍼시스턴트 볼륨을 사용할 수없다.

# pod는 pvc 만 명시해주면된다.
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

퍼시스턴트 볼륨 클레임 생성하기 

 

퍼시스턴트 볼륨클레임이 생성되자마자 쿠버네티스는 적절한 퍼시스턴트 볼륨을 찾고 클레임에 바인딩한다.

 

퍼시스턴트 볼륨 클레임 조회하기

kubectl get pvc 

 

RWO(ReadWriteOnce) : 단일 노드만이 읽기/쓰기용으로 볼륨을 마운트 할 수있다.

ROX(ReadOnlyMany): 다수 노드가 읽기용으로 볼륨을 마운트 할 수 있다.

RWX(ReadWriteMany): 다수 노드가 읽기/쓰기용으로 볼륨을 마운트 할 수있다.

 

RWO,ROX,RWX 는 파드 수가 아닌 볼륨을 동시에 사용할 수있는 워커 노드 수와 관련이 있다.

 

 

퍼시스턴트 볼륨 조회하기 

kubectl get pv 

# nfs 로 pv 설정
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
# hostPath 로 pv 설정 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: ""
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

 

* NFS :network filesystem의 약자로 다른 host에 있는 file system의 일부를 자신의 디렉토리인것처럼 mount 에서 사용할 수 있다.  

# k get pvc myclaim -o yaml
apiVersion: v1
kind: PersistentVolumeClaim
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]}

6.5.5 퍼시스턴트 볼륨과 퍼시스턴트 볼륨 클레임 사용의 장점 이해하기 

 

애플리케이션 개발자에게 인프라스트럭처에서 스토리지를 가져오는 간접적인 방식을 사용하는 것이 더 간단하다.

퍼시스턴트 볼륨과 퍼시스턴트 볼륨클레인을 생성하는 추가 절차가 필요한 것은 맞지만, 개발자는 기저에 사용된 실제 스토리지 기슬을 알 필요가 없다.

 

6.5.6 퍼시스턴트 볼륨 재사용 

퍼시스턴트 볼륨 클레임과 파드 삭제후 퍼시스턴트볼륨 클레임을 재생성시 Pending 상태로 남아있다.

 

바인딩 되지않는 이유는 퍼시스턴트 볼륨을 조회해보면 답이 나온다. 

status 열은 Released 이고 이전과 같은 Available 이 아니다. 이미 볼륨을 사용했기 때문에 데이터를 가지고 있으므로 클러스터 관리자가 볼륨을 완전히 비우지 않으면 새로운 클레임에 바인딩 할 수 없다.

 

퍼시스턴트 볼륨을 수동으로 다시 클레임하기 

PersistentVolumeClaimPolicy 를 Retain 으로 설정하면 퍼시스턴트 볼륨이 이러한 동작을 할수 있다. 

쿠버네티스가 클레임이 해제되도 볼륨과 콘텐츠를 유지하도록 한다. 퍼시스턴트 볼륨을 수동으로 재사용할 수있는 유일한 방법은 퍼시스턴트 볼륨 리소스를 삭제하고 다시 생성하는것이다. 이떄 기반 스토리지 파일을 어떻게 할지 결정해야한다.

삭제 할수도있고, 다음 파드에서 다시 사용하도록 남겨둘수도 있다.

 

퍼시스턴트볼륨을 자동으로 다시 클레임하기 

다른 두가지 리클레임 정책은 Recycle 과 Delete 다. 

Recycle 은 볼륨의 콘텐츠를 삭제하고 볼륨이 다시 클레임 될수 있도록 볼륨을 사용가능하게 만든다.

 

반대로 Delete 정책은 기반 스토리지를 삭제한다. 

단, GCE 퍼시스턴트 디스크에서 Recycle 옵션은 지원하지않는다. 다른 유형도 옵션 지원여부가 다를수 있으니 정책을 확인하고 써야한다.

 

6.6.2 퍼시스턴트 볼륨클레임에서 스토리지 클래스 요청하기 

 

크기와 접근모드 지정외에 퍼시스턴트 볼륨클레임에 사용할 스토리지 클래스를 지정해야한다.

클레임을 생성하면 fast 스토리지 클래스 리소스에 참조된 프로비저너가 퍼시스턴트 볼륨을 생성한다. 

 

프로비저너가 뭐야? 존재하는건 어떤거야?

-> 자동으로 볼륨까지 생성해서 매핑해주는 존재

 

- PVC 에서 존재하지않는 스토리지 클래스를 참조하면 PV 프로비저닝은 실패한다. PVC 를 kubectl describe 명령으로 보면 provisioningFailed 이벤트가 표시된다.

 

6.6.3 스토리지 클래스를 지정하지 않은 동적 프로비저닝 

kubectl get sc 

# sc aws-ebs
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

각 스토리지클래스에는 해당 스토리지클래스에 속하는 퍼시스턴트볼륨을 동적으로 프로비저닝 할 때 사용는 provisioner, parameters  reclaimPolicy 필드가 포함된다.

출처:스토리지 클래스 | Kubernetes

 

스토리지 클래스를 지정하지 않고 퍼시스턴트볼륨클레임 생성하기 

빈 문자열을 스토리지 클래스 이름으로 지정하면 pvc 가 새로운 pv 를 동적 프로비저닝 하는 대신 미리 프로비저닝된 pv에 바인딩 된다. 

-> 스토리지 클래스가 따로없다면, pv를 생성하고, pvc 생성시 pvc 에 이미 생성된 pv가 바인딩 될것이다.