[Kubernetes] 스토리지

문린이·2024년 4월 1일
0

스토리지의 필요성

  1. 데이터 지속성: 컨테이너는 재시작되거나 다른 노드로 이동할 때 내부 데이터를 유지하지 않는다. 상태를 유지하는 애플리케이션(예: 데이터베이스)의 경우, 데이터를 보존하고 접근할 수 있는 외부 스토리지가 필수적이다.

  2. 데이터 공유와 협업: 여러 컨테이너가 동일한 데이터에 접근해야 하는 경우(예: 콘텐츠 관리 시스템) 스토리지 솔루션을 통해 데이터를 공유하고, 여러 서비스 간에 협업을 용이하게 한다.

  3. 데이터 백업 및 복구: 중요 데이터의 백업 및 복구를 위해 외부 스토리지를 활용하여, 데이터 손실 시 복구를 보장한다.

  4. 성능 최적화: 고성능 스토리지를 활용하여 입출력 성능을 향상시키고, 애플리케이션의 전반적인 성능을 최적화할 수 있다.

  5. 스케일링 및 관리 용이성: 스토리지 관리 기능(동적 프로비저닝, 자동 확장 등)을 통해 리소스 사용량에 따라 스토리지를 유연하게 조정하고, 운영 효율성을 높일 수 있다.

스토리지의 종류

emptyDir, hostPath, local

emptyDir은 파드 내 임시 데이터 공유에, hostPath는 파드가 호스트 머신의 특정 파일이나 디렉토리에 접근해야 할 때 사용된다. local 볼륨은 지속적인 데이터를 필요로 하지만, 특정 노드에 종속된 스토리지를 요구하는 애플리케이션에 사용된다.

emptyDir

emptyDir 볼륨은 파드가 생성될 때 만들어지고, 파드에 속한 모든 컨테이너 간에 데이터를 공유할 수 있는 임시 디렉토리이다. emptyDir 볼륨은 파드가 존재하는 동안에만 유지되며, 파드가 제거되면 emptyDir에 저장된 데이터도 함께 삭제된다.

  • 사용 사례: 임시 파일 저장, 두 컨테이너 간의 데이터 공유, 고속 디스크에 대한 접근(예: RAM 디스크 사용) 등에 사용된다.

hostPath

hostPath 볼륨은 노드의 파일 시스템에 있는 파일이나 디렉토리를 파드에 마운트한다. 이를 통해 파드가 호스트 머신의 파일 시스템에 접근할 수 있게 된다.

  • 사용 사례: 특정 시스템 파일이나 디렉토리에 접근해야 하는 경우, 예를 들어 로그 파일 또는 도커 소켓에 접근해야 할 때 사용된다. 보안상의 이유로 신중하게 사용해야 한다.

local

local 볼륨은 노드의 지속적인 스토리지에 대한 접근을 제공한다. 이는 hostPath와 유사하지만, PersistentVolumes를 통해 사용된다. local 볼륨을 사용하면, 특정 노드의 스토리지에 바인딩된 PV를 생성하여, PVC를 통해 파드에 지속적인 데이터 스토리지를 제공할 수 있다.

  • 사용 사례: 노드에 직접 연결된 고성능의 지속적인 스토리지가 필요한 워크로드에 사용된다. 예를 들어, 고성능의 로컬 디스크를 사용하는 데이터베이스 서버 등에 적합하다.

테스트

resources 제한은 lint때문에 그냥 설정 (실제 환경이라면 반드시 최적의 값으로 설정해 줘야 한다.)
One or more containers do not have resource limits - this could starve other processes

nginx- service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80

nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          resources:
            requests:
              cpu: 200m
              memory: 250Mi
            limits:
              cpu: 1000m
              memory: 500Mi
          ports:
            - containerPort: 80
              name: http
kubectl apply -f nginx-service.yaml

kubectl apply -f nginx-deployment.yaml

minikube tunnel

설정X 테스트

nginx에 /usr/share/nginx/html/index.html 을 변경

kubectl rollout restart deployment nginx-deployment

해당 명령어로 재배포

내용이 저장되지 않고 다시 원본으로 돌아온 것을 알 수 있다.

emptyDir 테스트

two-container-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: two-containers
spec:
  restartPolicy: Never
  volumes:
    - name: shared-data
      emptyDir: {}
  containers:
    - name: nginx-container
      image: nginx
      volumeMounts:
        - name: shared-data
          mountPath: /usr/share/nginx/html
      resources:
        requests:
          cpu: 200m
          memory: 250Mi
        limits:
          cpu: 1000m
          memory: 500Mi
    - name: debian-container
      image: debian
      volumeMounts:
        - name: shared-data
          mountPath: /pod-data
      resources:
        requests:
          cpu: 200m
          memory: 250Mi
        limits:
          cpu: 1000m
          memory: 500Mi
      command: ['/bin/sh']
      args: ['-c', 'tail -f /dev/null']

kubectl apply -f two-container-pod.yaml

nginx-container에 접속 후 해당 명령어(ls /usr/share/nginx/html)를 입력한다.

현재 빈 폴더임을 알 수 있다.

이제 debian-container에 접속 후 해당 명령어(mkdir -p pod-data/test)를 입력하여 debian-container에 test 폴더를 만들어 준다.

다시 nginx-container에 접속 후 해당 명령어(ls /usr/share/nginx/html)를 입력한다.

test 폴더 존재

즉, nginx-container와 debian-container가 볼륨을 공유함을 알 수 있다.
그러나 POD을 종료하면 볼륨도 같이 삭제된다.

hostPath 테스트

hostpath-test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-test
spec:
  containers:
    - name: test-container
      image: busybox
      command: ['sh', '-c', 'tail -f /dev/null']
      volumeMounts:
        - name: test-volume
          mountPath: /mnt/test
      resources:
        requests:
          cpu: 200m
          memory: 250Mi
        limits:
          cpu: 1000m
          memory: 500Mi
  volumes:
    - name: test-volume
      hostPath:
        path: /home/docker/test
        type: Directory

hostPath의 타입은 다음과 같다.

test-container에 접속 후 해당 명령어를 입력하여 hostPath 폴더를 만들어 준다.

이제 minikube ssh 명령어로 minikube에 접속 후 hostPath 폴더가 있는지 확인한다.

이는 호스트 노드의 파일시스템에 디렉터리가 POD와 마운트 됐음을 알 수 있다. 그러므로 POD가 삭제된 후 다시 실행돼도 볼륨을 유지할 수 있다.

그러나 hostPath 볼륨은 특정 노드의 파일 시스템 경로를 POD에 마운트하기 때문에, 해당 노드에서만 접근 가능하며, 다른 노드로 POD이 재스케줄링될 경우 그 볼륨에 더 이상 접근할 수 없게 된다.

local 볼륨과 퍼시스턴트볼륨의 nodeAffinity를 설정하여 이 문제를 해결할 수 있지만 만약 해당 노드가 비정상 상태가 되면 local 볼륨도 접근할 수 없게 되고, POD을 실행할 수 없게 된다.

또한, local 볼륨은 동적 프로비저닝을 지원하지 않는다.

PV, PVC, SC

PersistentVolume (PV)

PersistentVolume은 클러스터 내에서의 스토리지 볼륨이다. 이는 일반적인 컴퓨터 파일 시스템이나 네트워크 파일 시스템, 클라우드 기반 스토리지 등 다양한 스토리지 백엔드를 추상화한다.

  • 특징: PV는 개별 파드의 생명주기를 넘어서 지속되며, 클러스터 리소스처럼 관리된다. 관리자는 사전에 여러 PV를 생성하거나 동적 프로비저닝을 통해 자동으로 생성할 수 있다.

PersistentVolumeClaim (PVC)

PersistentVolumeClaim은 사용자가 스토리지에 대해 요청하는 방법이다. 사용자는 필요한 스토리지의 크기와 접근 모드를 PVC를 통해 명시한다.

  • 특징: PVC는 스토리지 볼륨을 사용하고자 하는 파드의 요구사항을 기술한다. 적절한 PV가 PVC와 자동으로 바인딩되어 파드에 스토리지를 제공한다. PVC는 사용자의 요청에 맞는 PV를 찾거나, 적절한 StorageClass를 통해 동적으로 PV를 프로비저닝한다.

StorageClass (SC)

StorageClass는 동적 스토리지 프로비저닝을 위한 방법을 제공한다. SC는 PV를 생성하기 위해 사용되는 "템플릿"으로, 특정 스토리지 백엔드와 프로비저닝 정책을 정의한다.

  • 특징: 관리자는 SC를 정의하여, PVC가 제출될 때 사용될 스토리지 타입과 정책을 설정할 수 있다. 사용자는 PVC에서 특정 SC를 지정함으로써, 원하는 스토리지 솔루션을 선택할 수 있다. 동적 프로비저닝이 활성화된 SC가 PVC에 지정되면, 새로운 PV가 자동으로 생성되고 PVC에 바인딩된다.

프로비저닝

동적 프로비저닝 (Dynamic Provisioning)

동적 프로비저닝은 사용자가 PersistentVolumeClaim(PVC)을 생성할 때, 자동으로 필요한 PersistentVolume(PV)을 생성하고 할당하는 방식이다. 사용자는 스토리지의 크기, 액세스 모드 등 필요한 스펙을 PVC를 통해 정의하고, Kubernetes는 해당 요구 사항을 만족하는 PV를 자동으로 생성하여 PVC에 바인딩한다.

  • 장점: 동적 프로비저닝을 사용하면, 스토리지 관리자가 미리 여러 PV를 생성해 두지 않아도 된다. 사용자의 요구에 따라 필요한 시점에 적절한 스토리지 리소스가 자동으로 프로비저닝된다.

  • 사용 예시: 클라우드 환경에서 EBS 볼륨이나 GCP의 Persistent Disk와 같은 스토리지 리소스를 동적으로 프로비저닝하는 경우

정적 프로비저닝 (Static Provisioning)

정적 프로비저닝은 스토리지 관리자가 사전에 PV를 생성하고 구성해 두며, 사용자는 PVC를 통해 이러한 기존 PV 중 하나를 요청하는 방식이다. 사용자의 PVC가 생성되면, Kubernetes는 PVC의 요구 사항과 일치하는 기존의 PV를 찾아 바인딩한다.

  • 장점: 정적 프로비저닝을 사용하면, 스토리지 관리자가 스토리지의 물리적 구성, 성능, 비용 등을 미리 제어할 수 있다. 또한, 특정 스토리지 정책이나 보안 요구 사항을 사전에 적용할 수 있다.

  • 사용 예시: 내부 데이터 센터의 NFS 서버나 iSCSI 타겟과 같은 기존 인프라에 스토리지를 정적으로 프로비저닝하는 경우

차이점

  1. 프로비저닝 방법: 동적 프로비저닝은 사용자의 요청에 따라 자동으로 스토리지 볼륨이 생성되는 반면, 정적 프로비저닝은 미리 생성된 스토리지 볼륨을 사용자의 요청에 할당한다.

  2. 관리의 편의성: 동적 프로비저닝은 스토리지 리소스의 관리를 자동화하여 관리의 편의성을 제공하지만, 정적 프로비저닝은 스토리지 관리자가 미리 스토리지를 준비하고 관리해야 한다.

  3. 적용 시나리오: 동적 프로비저닝은 클라우드 환경과 같이 스토리지 리소스가 유연하게 확장될 수 있는 환경에 적합하며, 정적 프로비저닝은 기존의 물리적 인프라를 효율적으로 활용해야 하는 경우에 주로 사용된다.

동적 프로비저닝 테스트

minikube를 사용한다면 standard StorageClass가 기본적으로 사용 가능합니다.

dp-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dp-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
  storageClassName: standard

kubectl apply -f dp-pvc.yaml

pvc가 생성되었다면 pv도 자동적으로 생성됩니다.

dp-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: dp-pod
spec:
  containers:
    - name: nginx
      image: nginx:alpine
      volumeMounts:
        - mountPath: '/usr/share/nginx/html'
          name: storage
      resources:
        requests:
          cpu: 200m
          memory: 250Mi
        limits:
          cpu: 1000m
          memory: 500Mi
  volumes:
    - name: storage
      persistentVolumeClaim:
        claimName: dp-pvc

kubectl apply -f dp-pod.yaml

이런 방식으로 동적 프로비저닝을 할 수 있다.

profile
Software Developer

0개의 댓글