스토리지로 퍼시스턴트볼륨(PersistentVolume)을 사용하도록 파드 설정하기

이 페이지는 스토리지에 대해 퍼시스턴트볼륨클레임(PersistentVolumeClaim)을 사용하도록 파드를 설정하는 방법을 보여준다. 과정의 요약은 다음과 같다.

  1. 클러스터 관리자로서, 물리적 스토리지와 연결되는 퍼시스턴트볼륨을 생성한다. 볼륨을 특정 파드와 연결하지 않는다.

  2. 그 다음 개발자 / 클러스터 사용자의 역할로서, 적합한 퍼시스턴트볼륨에 자동으로 바인딩되는 퍼시스턴트볼륨클레임을 생성한다.

  3. 스토리지에 대해 위의 퍼시스턴트볼륨클레임을 사용하는 파드를 생성한다.

시작하기 전에

  • 사용자는 노드가 단 하나만 있는 쿠버네티스 클러스터가 필요하고, kubectl 커맨드라인 툴이 사용자의 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 만약 사용자가 아직 단일 노드 클러스터를 가지고 있지 않다면, Minikube를 사용하여 클러스터 하나를 생성할 수 있다.

  • 퍼시스턴트 볼륨의 관련 자료에 익숙해지도록 한다.

사용자 노드에 index.html 파일 생성하기

사용자 클러스터의 단일 노드에 연결되는 셸을 연다. 셸을 여는 방법은 클러스터 설정에 따라 달라진다. 예를 들어 Minikube를 사용하는 경우, minikube ssh 명령어를 입력하여 노드로 연결되는 셸을 열 수 있다.

해당 노드의 셸에서 /mnt/data 디렉터리를 생성한다.

# 사용자 노드에서 슈퍼유저로 명령을 수행하기 위하여
# "sudo"를 사용한다고 가정한다
sudo mkdir /mnt/data

/mnt/data 디렉터리에서 index.html 파일을 생성한다.

# 이번에도 사용자 노드에서 슈퍼유저로 명령을 수행하기 위하여
# "sudo"를 사용한다고 가정한다
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"

index.html 파일이 존재하는지 테스트한다.

cat /mnt/data/index.html

결과는 다음과 같다.

Hello from Kubernetes storage

이제 사용자 노드에서 셸을 종료해도 된다.

퍼시스턴트볼륨 생성하기

이 예제에서, 사용자는 hostPath 퍼시스턴트볼륨을 생성한다. 쿠버네티스는 단일 노드에서의 개발과 테스트를 위해 hostPath를 지원한다. hostPath 퍼시스턴트볼륨은 네트워크로 연결된 스토리지를 모방하기 위해, 노드의 파일이나 디렉터리를 사용한다.

운영 클러스터에서, 사용자가 hostPath를 사용하지는 않는다. 대신, 클러스터 관리자는 Google Compute Engine 영구 디스크, NFS 공유 또는 Amazone Elastic Block Store 볼륨과 같은 네트워크 자원을 프로비저닝한다. 클러스터 관리자는 스토리지클래스(StorageClasses)를 사용하여 동적 프로비저닝을 설정할 수도 있다.

hostPath 퍼시스턴트볼륨의 설정 파일은 아래와 같다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

설정 파일에 클러스터 노드의 /mnt/data 에 볼륨이 있다고 지정한다. 또한 설정에서 볼륨 크기를 10 기가바이트로 지정하고 단일 노드가 읽기-쓰기 모드로 볼륨을 마운트할 수 있는 ReadWriteOnce 접근 모드를 지정한다. 여기서는 퍼시스턴트볼륨클레임의 스토리지클래스 이름manual 로 정의하며, 퍼시스턴트볼륨클레임의 요청을 이 퍼시스턴트볼륨에 바인딩하는 데 사용한다.

퍼시스턴트볼륨을 생성한다.

kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml

퍼시스턴트볼륨에 대한 정보를 조회한다.

kubectl get pv task-pv-volume

결과는 퍼시스턴트볼륨의 STATUSAvailable 임을 보여준다. 이는 아직 퍼시스턴트볼륨클레임이 바인딩되지 않았다는 것을 의미한다.

NAME             CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
task-pv-volume   10Gi       RWO           Retain          Available             manual                   4s

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

다음 단계는 퍼시스턴트볼륨클레임을 생성하는 단계이다. 파드는 퍼시스턴트볼륨클레임을 사용하여 물리적인 스토리지를 요청한다. 이 예제에서, 사용자는 적어도 하나 이상의 노드에 대해 읽기-쓰기 접근을 지원하며 최소 3 기가바이트의 볼륨을 요청하는 퍼시스턴트볼륨클레임을 생성한다.

퍼시스턴트볼륨클레임에 대한 설정 파일은 다음과 같다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

퍼시스턴트볼륨클레임을 생성한다.

kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml

사용자가 퍼시스턴트볼륨클레임을 생성한 후에, 쿠버네티스 컨트롤 플레인은 클레임의 요구사항을 만족하는 퍼시스턴트볼륨을 찾는다. 컨트롤 플레인이 동일한 스토리지클래스를 갖는 적절한 퍼시스턴트볼륨을 찾으면, 볼륨에 클레임을 바인딩한다.

퍼시스턴트볼륨을 다시 확인한다.

kubectl get pv task-pv-volume

이제 결과는 STATUSBound 임을 보여준다.

NAME             CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                   STORAGECLASS   REASON    AGE
task-pv-volume   10Gi       RWO           Retain          Bound     default/task-pv-claim   manual                   2m

퍼시스턴트볼륨클레임을 확인한다.

kubectl get pvc task-pv-claim

결과는 퍼시스턴트볼륨클레임이 사용자의 퍼시스턴트볼륨인 task-pv-volume 에 바인딩되어 있음을 보여준다.

NAME            STATUS    VOLUME           CAPACITY   ACCESSMODES   STORAGECLASS   AGE
task-pv-claim   Bound     task-pv-volume   10Gi       RWO           manual         30s

파드 생성하기

다음 단계는 볼륨으로 퍼시스턴트볼륨클레임을 사용하는 파드를 만드는 단계이다.

파드에 대한 설정 파일은 다음과 같다.

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage


파드의 설정 파일은 퍼시스턴트볼륨클레임을 지정하지만, 퍼시스턴트볼륨을 지정하지는 않는다는 것을 유념하자. 파드의 관점에서 볼때, 클레임은 볼륨이다.

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml

파드의 컨테이너가 실행 중임을 확인한다.

kubectl get pod task-pv-pod

사용자 파드에서 구동되고 있는 컨테이너에 셸로 접근한다.

kubectl exec -it task-pv-pod -- /bin/bash

사용자의 셸에서, nginx가 hostPath 볼륨으로부터 index.html 파일을 제공하는지 확인한다.

# 이전 단계에서 "kubectl exec" 명령을 실행한 root 셸 안에서 
# 다음의 3개 명령을 실행해야 한다.
apt update
apt install curl
curl http://localhost/

결과는 hostPath 볼륨에 있는 index.html 파일에 사용자가 작성한 텍스트를 보여준다.

Hello from Kubernetes storage

만약 사용자가 위와 같은 메시지를 확인하면, 파드가 퍼시스턴트볼륨클레임의 스토리지를 사용하도록 성공적으로 설정한 것이다.

정리하기

파드, 퍼시스턴트볼륨클레임, 퍼시스턴트볼륨을 삭제한다.

kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume

만약 클러스터의 노드에 대한 셸이 열려져 있지 않은 경우, 이전과 동일한 방식으로 새로운 셸을 연다.

사용자 노드의 셸에서, 생성한 파일과 디렉터리를 제거한다.

# 사용자 노드에서 슈퍼유저로 명령을 수행하기 위하여
# "sudo"를 사용한다고 가정한다
sudo rm /mnt/data/index.html
sudo rmdir /mnt/data

이제 사용자 노드에서 셸을 종료해도 된다.

하나의 퍼시스턴트볼륨을 두 경로에 마운트하기


apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
    - name: test
      image: nginx
      volumeMounts:
        # a mount for site-data
        - name: config
          mountPath: /usr/share/nginx/html
          subPath: html
        # another mount for nginx config
        - name: config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
  volumes:
    - name: config
      persistentVolumeClaim:
        claimName: test-nfs-claim

하나의 퍼시스턴트볼륨을 nginx 컨테이너의 두 경로에 마운트할 수 있다.

/usr/share/nginx/html - 정적 웹사이트 용 /etc/nginx/nginx.conf - 기본 환경 설정 용

접근 제어

그룹 ID(GID)로 설정된 스토리지는 동일한 GID를 사용하는 파드에서만 쓰기 작업을 허용한다. GID가 일치하지 않거나 누락되었을 경우 권한 거부 오류가 발생한다. 사용자와의 조정 필요성을 줄이기 위하여 관리자는 퍼시스턴트 볼륨에 GID로 어노테이션을 달 수 있다. 그 뒤에, 퍼시스턴트볼륨을 사용하는 모든 파드에 대하여 GID가 자동으로 추가된다.

다음과 같이 pv.beta.kubernetes.io/gid 어노테이션을 사용한다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  annotations:
    pv.beta.kubernetes.io/gid: "1234"

파드가 GID 어노테이션이 있는 퍼시스턴트볼륨을 사용하면, 어노테이션으로 달린 GID가 파드의 보안 컨텍스트에 지정된 GID와 동일한 방식으로 파드의 모든 컨테이너에 적용된다. 파드의 명세 혹은 퍼시스턴트볼륨의 어노테이션으로부터 생성된 모든 GID는, 각 컨테이너에서 실행되는 첫 번째 프로세스에 적용된다.

다음 내용

Reference

최종 수정 December 15, 2024 at 6:24 PM PST: Merge pull request #49087 from Arhell/es-link (2c4497f)