Storage - Container Storage Interface (CSI)

2025. 1. 13. 23:00쿠버네티스/쿠버네티스

728x90
반응형

https://inspirit941.tistory.com/412

컨테이너 스토리지 인터페이스 (CSI)

배경

과거에는 Kubernetes가 컨테이너 런타임 엔진으로 Docker만 사용했습니다. 이때 Kubernetes 소스 코드에 Docker와 관련된 모든 코드가 포함되어 있었습니다. 그러나 RKT, CRI-O와 같은 다른 컨테이너 런타임이 등장하면서, Kubernetes는 다양한 컨테이너 런타임을 지원할 수 있도록 확장될 필요가 있었습니다. 이를 위해 **컨테이너 런타임 인터페이스(Container Runtime Interface, CRI)**가 도입되었습니다.

  • CRI는 Kubernetes와 Docker 같은 컨테이너 런타임 간의 통신 방법을 표준화한 규격입니다.
  • 새로운 컨테이너 런타임이 개발되더라도 CRI 표준만 따르면 Kubernetes와 호환될 수 있습니다.
  • 이는 Kubernetes 소스 코드를 수정하거나 Kubernetes 개발팀과 협력할 필요 없이 가능합니다.

비슷한 방식으로, 네트워킹 솔루션을 확장하기 위해 **컨테이너 네트워킹 인터페이스(Container Networking Interface, CNI)**가 도입되었습니다. CNI 표준을 따르면 새로운 네트워킹 플러그인을 Kubernetes와 쉽게 통합할 수 있습니다.

CSI의 등장

마찬가지로, 다양한 스토리지 솔루션을 지원하기 위해 **컨테이너 스토리지 인터페이스(Container Storage Interface, CSI)**가 개발되었습니다.

  • CSI를 통해 각 스토리지 벤더는 자신의 드라이버를 작성하여 Kubernetes와 연동할 수 있습니다.
  • 예: Portworx, Amazon EBS, Azure Disk, Dell EMC Isilon, NetApp, Nutanix 등 다양한 스토리지 벤더들이 CSI 드라이버를 제공합니다.
  • 중요한 점은 CSI가 Kubernetes 전용 표준이 아니라는 것입니다. 이는 범용 표준으로 설계되었으며, 이를 구현하면 Kubernetes뿐만 아니라 Cloud Foundry, Mesos 같은 다른 컨테이너 오케스트레이션 도구에서도 작동할 수 있습니다.

CSI의 작동 방식

CSI는 컨테이너 오케스트레이터(예: Kubernetes)와 스토리지 드라이버 간의 통신을 위한 일련의 **RPC(Remote Procedure Calls)**를 정의합니다. 스토리지 드라이버는 이 RPC를 구현하여 요청을 처리해야 합니다.

주요 RPC 예시

  1. 볼륨 생성 (Create Volume)
    • Pod가 생성되면서 볼륨을 요구하면, Kubernetes는 CreateVolume RPC를 호출합니다.
    • 이 호출에는 볼륨 이름 등의 세부 정보가 포함됩니다.
    • 스토리지 드라이버는 이 요청을 처리하여 스토리지 배열에 새 볼륨을 프로비저닝(provisioning)하고 결과를 반환합니다.
  2. 볼륨 삭제 (Delete Volume)
    • 볼륨이 삭제될 때 Kubernetes는 DeleteVolume RPC를 호출합니다.
    • 스토리지 드라이버는 이 요청에 따라 스토리지 배열에서 해당 볼륨을 해제(decommissioning)해야 합니다.

CSI 명세

CSI 명세는 다음 사항들을 정확히 정의합니다:

  • 호출자가 전달해야 할 매개변수
  • 솔루션(스토리지 드라이버)이 반환해야 할 값
  • 교환되어야 할 오류 코드

요약

  1. CSI는 다양한 스토리지 솔루션과 컨테이너 오케스트레이션 도구 간의 호환성을 보장하는 범용 표준입니다.
  2. 이를 통해 새로운 스토리지 솔루션도 쉽게 Kubernetes 및 기타 플랫폼과 통합될 수 있습니다.
  3. CSI 명세는 GitHub에서 확인할 수 있으며, 세부적인 구현 내용은 명세에 따라 이루어집니다.

Kubernetes 외에도 Cloud Foundry와 Mesos가 CSI를 지원하고 있습니다.

https://kubernetes.io/ko/docs/concepts/storage/storage-classes/

https://kubernetes.io/ko/docs/concepts/storage/volumes/

https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/

https://tech.gluesys.com/blog/2022/06/21/CSI.html


 

Volume

1. 컨테이너와 데이터의 휘발성

  • 컨테이너는 일시적인 존재로, 필요한 작업을 처리한 뒤 삭제됩니다.
  • 컨테이너가 삭제되면 내부에 저장된 데이터도 함께 사라집니다.
  • 데이터를 유지하려면 **볼륨(Volume)**이라는 저장 공간을 컨테이너에 연결해야 합니다.
    • 볼륨은 컨테이너 외부에 데이터를 저장하므로, 컨테이너가 삭제되어도 데이터는 유지됩니다.

2. 쿠버네티스에서의 볼륨

  • 쿠버네티스에서도 Pod(컨테이너를 묶은 단위)는 일시적입니다.
  • Pod가 삭제되면 그 안에서 생성된 데이터도 사라집니다.
  • 이를 해결하기 위해 Pod에 볼륨을 연결합니다.
    • 볼륨에 저장된 데이터는 Pod가 삭제되어도 유지됩니다.

3. 볼륨의 간단한 예제

  1. Pod 생성 및 데이터 처리
    • 예제: 랜덤 숫자를 생성해 /opt/number.out 파일에 저장하는 Pod를 만듭니다.
    • 문제: Pod가 삭제되면 이 파일과 숫자도 사라집니다.
  2. 볼륨 추가로 데이터 유지
    • 볼륨을 생성하고, 이를 Pod에 연결합니다.
    • 볼륨은 호스트(서버)의 특정 디렉터리(예: /data)를 사용하도록 설정합니다.
    • Pod 내부의 디렉터리(/opt)와 호스트의 /data 디렉터리를 연결하면, Pod가 삭제되더라도 /data에 데이터가 남아 있습니다.

4. 볼륨 구성 방법

  • 볼륨은 다양한 방식으로 저장소를 설정할 수 있습니다.

1) HostPath (호스트 경로)

  • 호스트 서버의 특정 디렉터리(예: /data)를 사용하여 데이터를 저장합니다.
  • 단점: 여러 노드(서버)가 있는 클러스터에서는 비추천입니다.
    • 각 노드의 /data 디렉터리가 서로 다르기 때문에 동일한 데이터를 보장할 수 없습니다.

2) 외부 스토리지 솔루션

  • 쿠버네티스는 다양한 스토리지 솔루션을 지원합니다:
    • NFS, CephFS, Flocker 등 네트워크 스토리지
    • 퍼블릭 클라우드 스토리지:
      • AWS EBS (Elastic Block Store)
      • Azure Disk
      • Google Persistent Disk
    • 고급 스토리지 시스템:
      • Fiber Channel, ScaleIO 등

3) AWS EBS 예제

  • AWS EBS를 볼륨으로 사용하려면 다음과 같이 설정합니다:
     
volumes:
  - name: my-volume
    awsElasticBlockStore:
      volumeID: "vol-0abcd1234efgh5678"
      fsType: "ext4"
  • 이렇게 하면 AWS EBS에 데이터가 저장됩니다.

5. 요약

  1. 쿠버네티스에서 Pod와 데이터는 기본적으로 일시적입니다.
  2. 데이터를 유지하려면 볼륨을 생성하고 Pod에 연결해야 합니다.
  3. 여러 종류의 스토리지 옵션이 있으며, 필요에 따라 적합한 것을 선택합니다:
    • 단일 노드에서는 HostPath,
    • 다중 노드 또는 클라우드 환경에서는 NFS, AWS EBS 등의 외부 스토리지를 권장합니다.

초등학생을 위한 쉬운 설명

  • 컴퓨터 안의 상자(Pod)가 일을 하고 숫자를 만들어요.
  • 그런데 상자가 없어지면 숫자도 사라져요!
  • 그래서 상자 옆에 가방(볼륨)을 두고 숫자를 가방에 넣어요.
  • 상자가 없어져도 가방은 남아 있으니까 숫자가 안전해요!

1. 볼륨과 퍼시스턴트 볼륨의 차이

  • 이전 강의에서 배운 **볼륨(Volume)**은 Pod 안에 정의되며, Pod가 삭제되면 데이터도 함께 사라질 수 있었습니다.
  • 하지만, **퍼시스턴트 볼륨(Persistent Volume)**은 클러스터 전체에서 사용할 수 있는 중앙화된 저장소입니다.
    • 관리자가 미리 큰 저장소 풀(pool)을 만들어 놓습니다.
    • 사용자는 이 저장소에서 필요한 만큼만 가져다 쓸 수 있습니다.

왜 퍼시스턴트 볼륨이 필요할까요?

  • 많은 사용자가 여러 Pod를 배포하는 환경에서는, 매번 각 Pod에 저장소를 설정하는 것이 번거롭습니다.
  • 중앙에서 저장소를 관리하면:
    • 사용자는 간단히 필요한 저장소를 요청해서 사용할 수 있습니다.
    • 관리자는 전체 저장소를 효율적으로 관리할 수 있습니다.

2. 퍼시스턴트 볼륨 만들기

기본 템플릿

퍼시스턴트 볼륨을 생성하려면 다음과 같은 YAML 파일을 작성합니다:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-vol1
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 1Gi
  hostPath:
    path: "/data"

 

주요 구성 요소

  1. apiVersion과 kind
    • apiVersion: API 버전을 지정합니다. 여기서는 v1을 사용합니다.
    • kind: 리소스 종류를 지정합니다. 여기서는 PersistentVolume입니다.
  2. metadata
    • 퍼시스턴트 볼륨의 이름을 지정합니다. 예: pv-vol1.
  3. spec (세부 설정)
    • accessModes (접근 모드):
      • 볼륨이 어떻게 사용될지 정의합니다.
      • 주요 옵션:
        • ReadWriteOnce: 하나의 노드에서 읽기/쓰기 가능.
        • ReadOnlyMany: 여러 노드에서 읽기만 가능.
        • ReadWriteMany: 여러 노드에서 읽기/쓰기 가능.
    • capacity (용량):
      • 이 볼륨에 할당된 저장 공간 크기를 지정합니다. 예: 1Gi (1GB).
    • hostPath (저장소 경로):
      • 로컬 디렉터리를 저장소로 사용합니다. 예: /data.
      • 주의: 이 옵션은 테스트 환경에서만 사용하고, 실제 운영 환경에서는 적합하지 않습니다.

3. 퍼시스턴트 볼륨 생성 및 확인

명령어 실행

  1. YAML 파일을 작성한 뒤, 다음 명령어로 퍼시스턴트 볼륨을 생성합니다
kubectl create -f pv.yaml
kubectl get persistentvolume

4. 퍼시스턴트 볼륨의 다양한 스토리지 옵션

  • 이전 강의에서 배운 것처럼, 여러 스토리지 솔루션을 사용할 수 있습니다.
    • 로컬 디렉터리(hostPath) 외에도 다음과 같은 옵션이 있습니다:
      • AWS EBS (Elastic Block Store)
      • Azure Disk
      • Google Persistent Disk
      • NFS (Network File System)
      • CephFS 등

예: AWS EBS를 사용하는 경우

spec:
  awsElasticBlockStore:
    volumeID: "vol-0abcd1234efgh5678"
    fsType: "ext4"

5. 초등학생을 위한 쉬운 설명

  • 쿠버네티스는 여러 사람이 컴퓨터를 나눠 쓰는 놀이터라고 생각해보세요!
  • 놀이터에 있는 장난감(Pod)이 데이터를 만들어내는데, 이 데이터를 잃어버리지 않으려면 가방(볼륨)이 필요했죠?
  • 그런데 사람들이 많아지면 각자 가방을 준비하기가 너무 힘들어요!
  • 그래서 놀이터 관리자(관리자)가 큰 창고(퍼시스턴트 볼륨)를 만들어 놓고, 필요한 사람에게 조금씩 나눠주는 거예요.
  • 이제 사람들은 창고에서 필요한 만큼 가져다 쓰면 돼요!

6. 요약

  1. 퍼시스턴트 볼륨은 클러스터 전체에서 사용할 수 있는 중앙화된 저장소입니다.
  2. 관리자가 미리 큰 저장소를 만들어 놓으면, 사용자는 간단히 요청해서 사용할 수 있습니다.
  3. 다양한 스토리지 솔루션과 연동 가능하며, 운영 환경에서는 AWS EBS나 NFS 같은 외부 스토리지를 권장합니다.

Persistent Volume(PV)와 Persistent Volume Claim(PVC)란?

  • Persistent Volume(PV): 저장 공간이에요. 선생님(관리자)이 미리 만들어 둔 큰 상자라고 생각하면 돼요.
  • Persistent Volume Claim(PVC): 학생(사용자)이 "이만큼 공간이 필요해요!"라고 요청하는 메모지예요.

PVC를 사용하면 필요한 만큼 저장 공간을 가져다 쓸 수 있어요. Kubernetes는 PVC를 보고 알맞은 크기의 PV를 찾아서 연결해줘요.

PVC가 어떻게 작동하나요?

  1. 선생님(관리자)이 여러 개의 PV(저장 상자)를 준비해 둡니다.
  2. 학생(사용자)은 PVC를 작성해서 "저는 500MB가 필요해요!"라고 요청합니다.
  3. Kubernetes는 PVC를 읽고, 조건에 맞는 PV를 찾아 연결합니다.
    • 예: 요청한 크기(500MB), 접근 방식(ReadWriteOnce 등), 저장소 종류(Storage Class) 등을 확인합니다.
  4. 만약 조건에 맞는 PV가 없으면, PVC는 대기 상태에 머물러 있어요. 새로운 PV가 생기면 자동으로 연결됩니다.

중요한 특징

  • 1:1 관계: 하나의 PVC는 하나의 PV만 사용할 수 있어요. 남은 공간은 다른 사람이 쓸 수 없어요.
  • 작은 요청, 큰 상자: 요청한 크기보다 큰 PV가 있으면, 그 상자를 사용할 수도 있어요.
  • 대기 상태: 조건에 맞는 PV가 없으면 PVC는 기다립니다.

PVC 만들기

PVC를 만들 때는 다음과 같이 설정해요:

  • 이름: "My Claim"
  • 접근 모드: ReadWriteOnce (읽고 쓰기 가능)
  • 요청 크기: 500MB

PVC를 만들고 나면, Kubernetes가 자동으로 알맞은 PV를 찾아 연결합니다. 예를 들어, 1GB 크기의 PV가 있다면, 500MB 요청도 그 상자에 연결될 수 있어요.

PVC 삭제 시 발생하는 일

PVC를 삭제하면 PV에는 세 가지 옵션이 있어요:

  1. 유지(Retain): PV는 그대로 남아 있고, 관리자만 삭제할 수 있어요.
  2. 삭제(Delete): PVC가 삭제되면 PV도 자동으로 삭제돼요.
  3. 재활용(Recycle): 기존 데이터를 삭제하고 다른 사용자가 다시 쓸 수 있도록 준비돼요.

정리

  • PV: 저장 공간 (큰 상자)
  • PVC: 저장 공간 요청 (메모지)
  • PVC와 PV는 1:1로 연결돼요.
  • PVC 삭제 후에는 데이터를 유지하거나 삭제하거나 재활용할 수 있어요.

https://www.linkedin.com/pulse/complete-guide-understanding-persistent-volume-claim-pvc-arya-soni/

 

https://support.huaweicloud.com/intl/en-us/basics-cce/kubernetes_0030.html

Kubernetes Persistent Volume (PV)와 Persistent Volume Claim (PVC) 예시

Kubernetes에서 **Persistent Volume (PV)**는 클러스터의 저장소 자원을 나타내며, **Persistent Volume Claim (PVC)**는 사용자가 특정 저장소를 요청하는 객체입니다. 아래는 PV와 PVC를 설정하고 사용하는 예시를 YAML 파일과 함께 단계별로 설명합니다.

1. Persistent Volume (PV) 생성

먼저, 클러스터에 저장소를 정의하는 PV를 생성합니다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /mnt/data
  • capacity: 10Gi(기가바이트)의 저장 공간을 제공합니다.
  • accessModes: ReadWriteOnce로 설정하여 하나의 노드에서 읽기/쓰기 가능하도록 합니다.
  • persistentVolumeReclaimPolicy: Retain으로 설정하여 PVC가 삭제되더라도 PV는 유지됩니다.
  • hostPath: /mnt/data 경로를 로컬 스토리지로 사용합니다.

2. Persistent Volume Claim (PVC) 생성

PVC를 생성하여 위에서 만든 PV를 요청합니다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual
  • accessModes: ReadWriteOnce로 설정하여 PVC가 PV와 동일한 접근 모드를 요구합니다.
  • resources.requests.storage: 5Gi의 저장 공간을 요청합니다. PV의 크기(10Gi)가 요청 크기(5Gi)보다 크므로 바인딩이 가능합니다.
  • storageClassName: manual로 설정하여 동일한 스토리지 클래스를 사용하는 PV와 매칭됩니다.

3. PVC와 PV 바인딩 확인

PVC가 PV에 성공적으로 바인딩되었는지 확인합니다.

kubectl get pvc
NAME          STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
example-pvc   Bound    example-pv   10Gi       RWO            manual         2m

4. Pod에서 PVC 사용

PVC를 Pod에 연결하여 데이터를 저장할 수 있도록 합니다.

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    - name: nginx-container
      image: nginx
      volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: storage-volume
  volumes:
    - name: storage-volume
      persistentVolumeClaim:
        claimName: example-pvc
  • volumeMounts.mountPath: 컨테이너 내부에서 /usr/share/nginx/html 경로에 PVC를 마운트합니다.
  • volumes.persistentVolumeClaim.claimName: 앞서 생성한 PVC(example-pvc)를 참조합니다.

6. PVC 삭제 시 동작

PVC 삭제 후 PV의 동작은 persistentVolumeReclaimPolicy에 따라 달라집니다:

  1. Retain (유지):
    • PVC 삭제 후에도 PV는 유지됩니다.
    • 관리자가 수동으로 삭제해야 합니다.
  2. Delete (삭제):
    • PVC 삭제 시 PV도 자동으로 삭제됩니다.
  3. Recycle (재활용):
    • 데이터가 삭제된 후 다른 PVC에서 재사용 가능합니다.

Once you create a PVC use it in a POD definition file by specifying the PVC Claim name under persistentVolumeClaim section in the volumes section like this:

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

The same is true for ReplicaSets or Deployments. Add this to the pod template section of a Deployment on ReplicaSet.

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes

 

Persistent Volumes

This document describes persistent volumes in Kubernetes. Familiarity with volumes, StorageClasses and VolumeAttributesClasses is suggested. Introduction Managing storage is a distinct problem from managing compute instances. The PersistentVolume subsystem

kubernetes.io


The application stores logs at location /log/app.log. View the logs.

You can exec in to the container and open the file:

kubectl exec webapp -- cat /log/app.log
[2025-01-13 13:18:44,494] INFO in event-simulator: USER2 logged out
[2025-01-13 13:18:45,495] INFO in event-simulator: USER1 is viewing page3
[2025-01-13 13:18:46,495] INFO in event-simulator: USER1 logged out
[2025-01-13 13:18:47,496] INFO in event-simulator: USER4 is viewing page1
[2025-01-13 13:18:48,497] INFO in event-simulator: USER3 logged in
[2025-01-13 13:18:49,498] WARNING in event-simulator: USER5 Failed to Login as the account is locked due to MANY FAILED ATTEMPTS.
[2025-01-13 13:18:49,499] INFO in event-simulator: USER2 is viewing page3
[2025-01-13 13:18:50,500] INFO in event-simulator: USER4 logged in
[2025-01-13 13:18:51,501] INFO in event-simulator: USER4 logged in
[2025-01-13 13:18:52,502] WARNING in event-simulator: USER7 Order failed as the item is OUT OF STOCK.
[2025-01-13 13:18:52,503] INFO in event-simulator: USER4 is viewing page3

Configure a volume to store these logs at /var/log/webapp on the host.

Use the spec provided below.

  • Name: webapp
  • Image Name: kodekloud/event-simulator
  • Volume HostPath: /var/log/webapp
  • Volume Mount: /log

k edit pod webapp

## 볼륨 추가
 volumes:
  - name: log-volume
    hostPath:
      path: /var/log/webapp
      
## 볼륨마운트 추가
volumeMounts:
    - mountPath: /log
      name: log-volume

 

Create a Persistent Volume with the given specification.

Volume Name: pv-log

Storage: 100Mi

Access Modes: ReadWriteMany

Host Path: /pv/log

Reclaim Policy: Retain

 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-log
spec:
  capacity:
    storage: 100Mi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /pv/log

 

Let us claim some of that storage for our application. Create a Persistent Volume Claim with the given specification.

Persistent Volume Claim: claim-log-1

 

Storage Request: 50Mi

 

Access Modes: ReadWriteOnce

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim-log-1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Mi

 

 

Update the webapp pod to use the persistent volume claim as its storage.

 

Replace hostPath configured earlier with the newly created PersistentVolumeClaim.

https://waspro.tistory.com/580

https://nice-engineer.tistory.com/entry/Kubernetes-Object-Volume%EC%9D%B4%EB%9E%80-2

 

[Kubernetes] Object - Volume이란 (2)

✔️ Network 볼륨 (Persistent Storage) Pod 내부에서 특정 데이터를 보유해야 하는 stateful한(ex. DB) app의 경우 stateless한(Pod, deployment) 데이터를 영속적으로 저장하기 위한 방법이 필요하다. Pod에서 실행

nice-engineer.tistory.com

## pv 정의
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-example
spec:
  capacity:
    storage: 2Gi # 스토리지 용량
  volumeMode: Filesystem # 파일 시스템 형식
  accessModes:
    - ReadWriteOnce # 하나의 노드만 읽기/쓰기 가능
  persistentVolumeReclaimPolicy: Retain # PV 반환 정책
  hostPath:
    path: /data/pv-example # 클러스터 노드의 경로

## pvc정의
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-example
spec:
  accessModes:
    - ReadWriteOnce # 읽기/쓰기 접근 모드
  volumeMode: Filesystem # 파일 시스템 형식
  resources:
    requests:
      storage: 1Gi # 요청한 용량

### pod
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
    - name: app-container
      image: nginx # 컨테이너 이미지
      volumeMounts:
        - name: app-storage
          mountPath: /usr/share/nginx/html # 컨테이너 내부 경로
  volumes:
    - name: app-storage
      persistentVolumeClaim:
        claimName: pvc-example # 참조할 PVC 이름
반응형