본문 바로가기
Kubernetes/AWS EKS Workshop Study

3주차 1편 EKS Fundamentals - Storage

by 개발자 영만 2024. 3. 24.

스토리지 이해

배경

  • 파드가 정지되면 파드 내부의 데이터는 모두 삭제됩니다. → 파드는 Stateless 애플리케이션
  • 컨테이너는 temporary filesystem(tmpfs)를 사용하여 파일을 읽고 쓸 수 있습니다.
  • 컨테이너가 삭제되면 temporary filesystem의 데이터는 삭제고, 컨테이너는 깨끗한 상태로 다시 시작됩니다. 또한 여러 컨테이너가 temporary filesystem을 공유할 수 없습니다.
  • Ephemeral volumes을 사용하면 Pod내의 컨테이너간 데이터를 공유할 수 있습니다. 그러나 Pod가 삭제되는 즉시 Ephemeral volumes도 삭제가 됩니다.

https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/

  • 데이터베이스처럼 데이터 보존이 필요합니다. → Persistent Volumes
  • Persistent Volume(PV) 객체는 애플리케이션 데이터를 유지하는 데 사용되는 스토리지 볼륨입니다.
  • Pods의 수명 주기와 별개로 자체의 수명 주기를 가집니다.
  • Persistent Volume(PV)은 실제 스토리지 볼륨을 나타냅니다. Kubernetes는 PV를 포드에 연결하는데 필요한 추가 추상화 계층인 PersistentVolumeClaim(PVC)을 가지고 있습니다.
  • 기본적으로 PV 객체를 직접 Pod에 마운트할 수 없습니다. PVC객체를 생성하고 Pod에 연결하는 방식입니다.

https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/

  • 파드가 생성될 때 자동으로 볼륨을 마운트하여 파드에 연결하는 기능을 동적 프로비저닝(Dynamic Provisioning)이라고 합니다.
  • 동적 프로비저닝을 사용하면 PV객체를 생성할 필요가 없습니다. 대신에, PVC를 생성할 때 내부적으로 자동으로 생성됩니다.

https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/

  • 퍼시스턴트 볼륨의 사용이 끝났을 때 해당 볼륨은 어떻게 초기화할 것인지 별도로 설정할 수 있는데, 쿠버네티스는 이를 Reclaim Policy 라고 부릅니다.
  • Reclaim Policy 에는 크게 Retain(보존), Delete(삭제, 즉 EBS 볼륨도 삭제됨), Recycle 방식이 있습니다.

 

스토리지 소개

emptyDir

  • emptyDir 볼륨은 파드가 노드에 할당될 때 처음 생성되며, 해당 노드에서 파드가 실행되는 동안에만 존재합니다.
  • 파드 내 모든 컨테이너는 emptyDir 볼륨에서 동일한 파일을 읽고 쓸 수 있지만, 해당 볼륨은 각각의 컨테이너에서 동일하거나 다른 경로에 마운트될 수 있습니다.
  • 어떤 이유로든 노드에서 파드가 제거되면 emptyDir 의 데이터가 영구적으로 삭제됩니다.

https://kubetm.github.io/k8s/03-beginner-basic-resource/volume/

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi

 

hostPath

  • hostPath 볼륨은 호스트 노드의 파일시스템에 있는 파일이나 디렉터리를 파드에 마운트 합니다.

https://kubetm.github.io/k8s/03-beginner-basic-resource/volume/

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:
      # 호스트의 디렉터리 위치
      path: /data
      # 이 필드는 선택 사항이다
      type: Directory

 

PV/PVC

  • 퍼시스턴트볼륨 (PV)은 관리자가 프로비저닝하거나 스토리지 클래스를 사용하여 동적으로 프로비저닝한 클러스터의 스토리지입니다. 노드가 클러스터 리소스인 것처럼 PV는 클러스터 리소스입니다.
  • 퍼시스턴트볼륨클레임 (PVC)은 사용자의 스토리지에 대한 요청입니다. 파드는 노드 리소스를 사용하고 PVC는 PV 리소스를 사용합니다. 파드는 특정 수준의 리소스(CPU 및 메모리)를 요청할 수 있습니다. 클레임은 특정 크기 및 접근 모드를 요청할 수 있습니다.

https://kubetm.github.io/k8s/03-beginner-basic-resource/volume/

  • PersistentVolume
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-01
  labels:
    pv: pv-01
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
  • PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-01
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
  storageClassName: slow
  selector:
    matchLabels:
      pv: pv-01
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

 

라이프사이클

  • Provisioning
    • 정적 프로비저닝 : 클러스터 관리자는 여러 PV를 만들 수 있습니다. 클러스터 사용자가 사용할 수 있는 실제 스토리지의 세부 사항을 제공합니다. 이 PV들은 쿠버네티스 API에 존재하며 사용할 수 있습니다.
    • 동적 프로비저닝 : 클러스터 관리자가 생성한 정적 PV가 사용자의 PVC와 일치하지 않으면 클러스터는 PVC를 위해 특별히 볼륨을 동적으로 프로비저닝할 수 있습니다. 이 프로비저닝은 스토리지클래스를 기반으로 합니다.
  • Reclaiming
    • Retain : PVC가 삭제되어도 PV는 여전히 존재하며 볼륨은 "Released" 된 상태로 간주됩니다. 그러나 이전 데이터가 여전히 볼륨에 남아 있기 때문에 아직 사용할 수 없는 상태입니다. 관리자는 볼륨을 수동으로 반환할 수 있습니다.
    • Delete : PV와 외부 인프라(예: AWS EBS, GCE PD, Azure Disk 또는 Cinder 볼륨)의 관련 스토리지 자산을 모두 삭제합니다. 동적으로 프로비저닝된 볼륨은 스토리지클래스의 ReclaimingPolicy를 상속하며 기본값은 Delete 입니다.
    • Recycle : Deprecated

 

CSI (Contaier Storage Interface) 소개

CSI Driver 배경

  • AWS EBS provisioner는 당연히 Kubernetes release lifecycle을 따라서 배포되므로, provisioner 신규 기능을 사용하기 위해서는 Kubernetes version을 업그레이드해야 하는 제약 사항이 있습니다.
  • 따라서, Kubernetes 개발자는 Kubernetes 내부에 내장된 provisioner (in-tree)를 모두 삭제하고, 별도의 controller Pod을 통해 동적 provisioning을 사용할 수 있도록 만들었습니다. →  CSI (Container Storage Interface) driver

AWS docs

일반적인 CSI driver 구조

  • AWS EBS CSI driver도 아래와 같은 구조
  • StatefulSet 또는 Deployment로 배포된 controller Pod이 AWS API를 사용하여 실제 EBS volume을 생성하는 역할을 합니다.
  • DaemonSet으로 배포된 node Pod은 AWS API를 사용하여 Kubernetes node (EC2 instance)에 EBS volume을 attach 해줍니다.

 

노드별 볼륨 한도

쿠버네티스 기본 한도

클라우드 서비스 노드 당 최대 볼륨
Amazon Elastic Block Store (EBS) 39
Google Persistent Disk 16
Microsoft Azure Disk Storage 16
  • 할당 가능한 볼륨 개수 확인
# 확인
kubectl describe node | grep Allocatable: -A1
  • KUBE_MAX_PD_VOLS 환경 변수의 값을 설정한 후, 스케줄러를 재시작하여 이러한 한도를 변경 가능합니다.

 

기본 컨테이너 환경의 임시 파일시스템 사용

# 파드 배포
# date 명령어로 현재 시간을 10초 간격으로 /home/pod-out.txt 파일에 저장
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/date-busybox-pod.yaml
cat date-busybox-pod.yaml | yh
kubectl apply -f date-busybox-pod.yaml

# 파일 확인
kubectl get pod
kubectl exec busybox -- tail -f /home/pod-out.txt

# 파드 삭제 후 다시 생성 후 파일 정보 확인 > 이전 기록이 보존되어 있는지?
kubectl delete pod busybox
kubectl apply -f date-busybox-pod.yaml
kubectl exec busybox -- tail -f /home/pod-out.txt

 

호스트 Path 를 사용하는 PV/PVC : local-path-provisioner 스트리지 클래스 배포

# 배포
curl -s -O https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
kubectl apply -f local-path-storage.yaml

# 확인
kubectl get-all -n local-path-storage
kubectl get pod -n local-path-storage -owide
kubectl describe cm -n local-path-storage local-path-config
kubectl get sc
kubectl get sc local-path

  • PV/PVC 를 사용하는 파드 생성
# PVC 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath1.yaml
cat localpath1.yaml | yh
kubectl apply -f localpath1.yaml

# PVC 확인
kubectl get pvc
kubectl describe pvc

# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath2.yaml
cat localpath2.yaml | yh
kubectl apply -f localpath2.yaml

# 파드 확인
kubectl get pod,pv,pvc
kubectl describe pv    # Node Affinity 확인
kubectl exec -it app -- tail -f /data/out.txt

# 워커노드 중 현재 파드가 배포되어 있다만, 아래 경로에 out.txt 파일 존재 확인
ssh ec2-user@$N2 tree /opt/local-path-provisioner

# 해당 워커노드 자체에서 out.txt 파일 확인 : 아래 굵은 부분은 각자 실습 환경에 따라 다름
ssh ec2-user@$N2 tail -f /opt/local-path-provisioner/pvc-cb13554b-1871-42a2-8c44-590d925f03a9_default_localpath-claim/out.txt

  • 파드 삭제 후 파드 재생성해서 데이터 유지 되는지 확인
# 파드 삭제 후 PV/PVC 확인
kubectl delete pod app
kubectl get pod,pv,pvc
for node in $N1 $N2 $N3; do ssh ec2-user@$node tree /opt/local-path-provisioner; done

# 파드 다시 실행
kubectl apply -f localpath2.yaml
 
# 확인
kubectl exec -it app -- head /data/out.txt
kubectl exec -it app -- tail -f /data/out.txt

 

AWS 스토리지 서비스 비교