Storage - Kubernetes CSI(Container Storage Interface)

2026. 1. 3. 19:47·CKA

앞에서 Docker의 스토리지 드라이버(overlay2 등) 와 볼륨 드라이버(local/외부 플러그인) 를 구분했죠.
Kubernetes로 오면 이 구분이 더 명확해집니다.

  • 컨테이너 런타임(예: containerd)은 이미지/컨테이너 레이어 파일시스템을 관리(overlayfs 같은 메커니즘)
  • Kubernetes는 “영구 스토리지”를 붙이기 위해 CSI(Container Storage Interface) 라는 표준을 통해 외부 스토리지를 연결

이 글에서는 “왜 CSI가 나왔는지”, “CRI/CNI/CSI가 각각 뭘 표준화하는지”, “CSI가 실제로 어떤 RPC를 정의하는지”, “Kubernetes에서 PVC/StorageClass로 어떻게 이어지는지”까지 흐름대로 정리합니다.


1) 왜 ‘인터페이스 표준’이 필요했나: CRI → CNI → CSI

초기 Kubernetes는 특정 런타임/네트워크/스토리지 구현과 결합이 강했습니다. 그러다 보니 새로운 런타임/네트워크/스토리지 벤더가 들어오려면 Kubernetes 코드 변경(또는 릴리스 주기 동기화)이 필요했고, 생태계를 확장하기 어렵습니다.

그래서 Kubernetes는 영역별로 “플러그인 인터페이스 표준”을 만들었습니다.

CRI (Container Runtime Interface)

  • kubelet ↔ 컨테이너 런타임 사이 통신 표준(gRPC 프로토콜)
  • 목적: kubelet이 다양한 런타임을 쓰도록 “재컴파일 없이” 플러그인처럼 갈아끼우게 함 (Kubernetes)

강의 스크립트에서 “예전엔 containerd만 쓰고 런타임 코드가 Kubernetes에 내장”처럼 들리는데, 실제 역사적으로는 Docker(dockershim) 등과의 결합/통합 이슈가 있었고, 핵심은 “쿠버네티스가 특정 런타임에 종속되지 않도록 표준(CRI)을 만든 것”입니다. (Kubernetes)

CNI (Container Network Interface)

  • 컨테이너 네트워크 플러그인 표준
  • 목적: Calico/Cilium/Flannel 같은 네트워크 벤더가 “표준 인터페이스”만 맞추면 Kubernetes에서 동작하게 함(네트워크 namespace에 인터페이스를 붙이고 IP 할당/라우팅 설정 등) (Red Hat)

CSI (Container Storage Interface)

  • 컨테이너 오케스트레이터 ↔ 스토리지 드라이버 사이 표준
  • 목적: AWS EBS, Azure Disk, NetApp, Portworx, Dell EMC, Pure 등 다양한 스토리지를 Kubernetes 코드 바깥(out-of-tree) 에서 드라이버로 제공 (GitHub)
  • CSI는 Kubernetes 전용이 아니라 “범용 표준”이며, 여러 오케스트레이터가 채택합니다(예: Kubernetes, Cloud Foundry, Mesos, Nomad 등) (GitHub)

2) CSI는 “무엇을 표준화”하나? — gRPC RPC 목록을 표준으로 고정

CSI의 본질은 단순합니다.

오케스트레이터가 스토리지를 쓰려면 “볼륨 생성/삭제/Attach/Detach/Mount/Unmount” 같은 작업이 필요한데,
이 작업들의 RPC 이름, 입력 파라미터, 반환/에러 규격을 표준으로 박아둔 것.

그래서 벤더는 CSI 스펙에 맞춰 gRPC 서버(드라이버)를 구현하면 되고, 오케스트레이터는 스펙대로 RPC를 호출하면 됩니다. (GitHub)

대표적으로 이런 계열 RPC가 등장합니다(이름은 예시/요지 수준):

  • CreateVolume / DeleteVolume: 볼륨 프로비저닝/해제
  • ControllerPublishVolume / ControllerUnpublishVolume: (블록 스토리지 계열에서) 노드에 Attach/Detach 성격
  • NodeStageVolume / NodeUnstageVolume: 노드에서 준비(스테이징)
  • NodePublishVolume / NodeUnpublishVolume: 파드에 최종 마운트/언마운트

이 구조 덕분에 “벤더 스토리지 API가 무엇이든” Kubernetes 입장에서는 동일한 흐름으로 다룹니다.


3) Kubernetes에서 CSI는 어떻게 쓰이나: StorageClass → PVC → Pod 흐름

Kubernetes 사용자는 보통 CSI를 직접 호출하지 않습니다. 대신 다음 리소스를 씁니다.

  • StorageClass: “어떤 스토리지 프로비저너(=CSI 드라이버)를 어떤 설정으로 쓸지”
  • PVC(PersistentVolumeClaim): “이만큼의 스토리지를 달라”
  • PV(PersistentVolume): 실제 할당된 볼륨(동적 프로비저닝이면 자동 생성)
  • Pod: PVC를 마운트해서 사용

(1) StorageClass 예시(개념)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: ebs.csi.aws.com   # 예시: 실제 값은 환경별 CSI 드라이버에 따라 다름
volumeBindingMode: WaitForFirstConsumer

(2) PVC 예시

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: fast
  resources:
    requests:
      storage: 20Gi

(3) Pod에서 PVC 마운트

apiVersion: v1
kind: Pod
metadata:
  name: mysql
spec:
  containers:
  - name: mysql
    image: mysql:8
    volumeMounts:
    - name: data
      mountPath: /var/lib/mysql
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: mysql-pvc

이 흐름에서 “PVC가 생겼는데 실제 볼륨이 만들어지고, 노드에 붙고, 파드 경로에 마운트되는” 모든 과정이 CSI 드라이버 RPC로 이어집니다.


4) “오케스트레이터가 CSI 드라이버를 호출한다”는 말이 실무에서 의미하는 것

Kubernetes에서 발생하는 대표 시나리오는 아래입니다.

파드가 올라가면서 볼륨이 필요할 때

  1. PVC 생성 → StorageClass 확인
  2. (동적 프로비저닝이면) CSI 드라이버 쪽으로 CreateVolume 계열 호출
  3. 스케줄링된 노드에 볼륨을 Attach/Detach 해야 하면 Controller 계열 RPC 호출
  4. 노드에서 파일시스템 준비/마운트(Node 계열 RPC)
  5. 컨테이너에서 /var/lib/mysql 같은 경로로 사용

PVC/PV 삭제로 볼륨이 회수될 때

  • 정책에 따라 DeleteVolume 계열 호출로 실제 스토리지에서도 볼륨 삭제

5) 확인/디버깅에 바로 쓰는 커맨드

CSI가 “지금 클러스터에 어떤 드라이버로 들어왔는지”부터 확인하는 게 좋습니다.

# 어떤 CSI 드라이버가 등록되어 있는지
kubectl get csidrivers

# StorageClass 목록과 provisioner 확인
kubectl get storageclass -o wide

# PVC/PV 상태 확인 (Pending이면 프로비저닝/바인딩 문제 가능)
kubectl get pvc,pv

# 특정 PVC 이벤트/에러 확인
kubectl describe pvc mysql-pvc

그리고 런타임 쪽(CRI) 확인도 같이 해두면 원인 분리가 빨라집니다.

# 노드가 어떤 컨테이너 런타임을 쓰는지(각 노드 정보)
kubectl get nodes -o wide
kubectl describe node <node> | grep -i "Container Runtime"

6) 핵심 정리

  • CRI: kubelet이 다양한 컨테이너 런타임과 통신하는 표준(gRPC) (Kubernetes)
  • CNI: 컨테이너 네트워킹 플러그인 표준(인터페이스 붙이기/IP 할당/라우팅) (Red Hat)
  • CSI: 컨테이너 오케스트레이터가 스토리지 벤더 드라이버와 통신하는 표준(gRPC), Kubernetes 포함 여러 CO가 채택 (GitHub)
  • Docker에서 “볼륨은 볼륨 드라이버가 담당”이었던 것처럼, Kubernetes에서는 “영구 스토리지는 CSI 드라이버가 담당”하는 구조로 일반화된 것

 

'CKA' 카테고리의 다른 글

Storage - PV & PVC  (0) 2026.01.03
Storage - Volume  (0) 2026.01.03
Storage - Docker의 Storage Driver vs Volume Driver  (0) 2026.01.03
Storage - Docker의 Storage  (0) 2026.01.03
Security - 정리(2)  (1) 2026.01.02
'CKA' 카테고리의 다른 글
  • Storage - PV & PVC
  • Storage - Volume
  • Storage - Docker의 Storage Driver vs Volume Driver
  • Storage - Docker의 Storage
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      페치 조인
      빈 후처리기
      버퍼
      양방향 맵핑
      Thread
      jdk 동적 프록시
      cglib
      log trace
      gesingleresult
      jpq
      @discriminatorvalue
      자바
      hibernate5module
      락
      JPQL
      고급
      WAS
      프록시 팩토리
      스레드
      김영한
      typequery
      @discriminatorcolumn
      reentarantlock
      @within
      프록시
      단방향 맵핑
      조회 성능 최적화
      Target
      @args
      requset scope
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Storage - Kubernetes CSI(Container Storage Interface)
    상단으로

    티스토리툴바