본문으로 건너뛰기
버전: 1.0.4

6.1. 스토리지

어떨 때 보는가​

  • 데이터베이스나 파일 저장이 필요한 애플리케이션을 배포할 때
  • 파드가 Pending 에서 넘어가지 않을 때
  • 저장 공간이 모자랄 때

컨테이너의 저장 공간 문제​

컨테이너는 이미지에서 만들어지고, 안에서 파일을 고쳐도 그 변경은 컨테이너가 사라지면 함께 사라집니다.

상황컨테이너 안의 파일
애플리케이션이 다시 시작사라집니다
파드가 다른 노드로 이동사라집니다
새 버전 배포사라집니다

이 성질은 의도된 것 입니다. 어느 컨테이너를 띄워도 같은 상태에서 시작하므로 배포가 단순해집니다.

하지만 데이터베이스처럼 남겨야 하는 데이터가 있으면 곤란합니다. 그래서 컨테이너 밖에 있는 저장 공간을 안에 붙여 씁니다.

볼륨이란​

컨테이너에 붙이는 저장 공간을 볼륨 이라고 합니다. 컨테이너의 특정 경로에 붙이면(마운트) 그 경로에 쓴 파일이 볼륨에 저장됩니다.

볼륨에는 여러 종류가 있습니다.

종류수명쓰임
emptyDir파드와 함께 사라짐컨테이너끼리 파일을 주고받을 때
ConfigMap · Secret설정과 함께설정 파일 주입 (3.4 장)
PersistentVolume파드와 무관하게 유지데이터 보관

이 장에서 다루는 것은 세 번째입니다.

PV 와 PVC 로 나눈 이유​

Kubernetes 는 저장 공간을 두 자원으로 나눕니다.

자원누가 다루나무엇을 담나
PersistentVolume (PV)운영 담당자실제 저장 공간. 어느 저장 장치의 어느 영역인지
PersistentVolumeClaim (PVC)애플리케이션 담당자요청. 얼마나 필요한지

나눈 이유는 관심사가 다르기 때문 입니다.

애플리케이션을 배포하는 사람은 "10GB 가 필요하다" 만 알면 됩니다. 그 10GB 가 NFS 인지 SAN 인지, 어느 서버의 어느 경로인지는 알 필요도 없고 알아서도 곤란합니다. 환경마다 다르기 때문에 그것까지 적으면 같은 배포 정의를 다른 클러스터에 쓸 수 없습니다.

PVC 를 만들면 조건에 맞는 PV 가 자동으로 연결됩니다(바인딩).

저장 공간을 쓰는 방식​

저장 공간을 쓰는 방식

PersistentVolumeClaim​

스토리지 > 영구 볼륨 클레임 로 들어갑니다.

PVC 목록
열설명
이름PVC 이름
네임스페이스속한 네임스페이스
상태Bound 는 연결 완료, Pending 은 대기 중
용량요청한 크기
접근 모드여러 파드가 동시에 쓸 수 있는지
스토리지 클래스어떤 기준으로 공간을 만들지

상세 화면에서 어떤 파드가 이 PVC 를 쓰고 있는지 확인할 수 있습니다. PVC 를 지우기 전에 반드시 확인하십시오.

PVC 는 네임스페이스 단위 자원입니다. 다른 네임스페이스의 파드는 쓸 수 없습니다.

접근 모드​

모드뜻쓰는 곳
ReadWriteOnce (RWO)노드 하나에서만 읽기·쓰기데이터베이스. 가장 널리 지원됩니다
ReadOnlyMany (ROX)여러 노드에서 읽기만공용 참조 데이터
ReadWriteMany (RWX)여러 노드에서 읽기·쓰기여러 파드가 같은 파일을 쓸 때

ReadWriteMany 는 지원하는 저장소에서만 됩니다. NFS 계열은 되지만 블록 스토리지는 안 됩니다. 지원하지 않는 클래스에 요청하면 PVC 가 Pending 에 머뭅니다.

ReadWriteOnce PVC 를 쓰는 파드는 한 노드에만 배치됩니다. 그래서 복제본을 여러 노드에 퍼뜨리려면 파드마다 PVC 를 따로 두는 StatefulSet 을 씁니다(3.2 장).

만들고 파드에 붙이기 — YAML​

PVC 만들기​

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
namespace: my-app
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-client # 스토리지 클래스 화면의 이름
resources:
requests:
storage: 10Gi
항목설명
accessModes위 "접근 모드" 참고. 스토리지 클래스가 지원하는 것만 됩니다
storageClassName스토리지 클래스 화면의 이름을 그대로 씁니다. 생략하면 기본 클래스가 쓰입니다
storage요청 용량. Gi(기가) · Mi(메가)

storageClassName 을 아예 빼는 것과 빈 문자열("")로 두는 것은 다릅니다. 빼면 기본 클래스를 쓰고, 빈 문자열이면 동적 생성을 하지 않고 미리 만들어 둔 PV 를 찾습니다. 없으면 계속 Pending 에 머뭅니다.

파드에 붙이기​

볼륨 선언과 마운트 두 곳에 적어야 합니다.

containers:
- name: app
image: registry.example.com/my-app:1.0
volumeMounts:
- name: data # ② 아래 volumes 의 이름
mountPath: /var/lib/app # 컨테이너 안에서 이 경로에 연결됩니다
volumes:
- name: data # ① 파드가 쓸 볼륨
persistentVolumeClaim:
claimName: app-data # PVC 이름

StatefulSet 에서는 다르게 씁니다​

복제본마다 저장 공간이 따로 있어야 하면 PVC 를 직접 만들지 않고 템플릿 을 씁니다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
namespace: my-app
spec:
serviceName: db
replicas: 3
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: db
image: registry.example.com/db:1.0
volumeMounts:
- name: data
mountPath: /var/lib/db
volumeClaimTemplates: # 복제본마다 PVC 를 하나씩 만듭니다
- metadata:
name: data # volumeMounts 의 이름과 같아야 합니다
spec:
accessModes: [ReadWriteOnce]
storageClassName: nfs-client
resources:
requests:
storage: 20Gi

복제본이 3개면 data-db-0·data-db-1·data-db-2 세 PVC 가 만들어집니다. 파드가 다시 떠도 같은 번호의 PVC 에 다시 연결됩니다 — 그래서 데이터가 유지됩니다.

StatefulSet 을 지워도 이 PVC 들은 남습니다. 실수로 지웠을 때 데이터를 지키려는 설계입니다. 정말 지우려면 PVC 를 따로 지워야 합니다.

용량이 모자랄 때​

스토리지 클래스가 확장을 지원하면 용량만 늘려 다시 적용 합니다.

spec:
resources:
requests:
storage: 20Gi # 10Gi → 20Gi

줄이는 것은 되지 않습니다. 늘리기만 됩니다. 확장을 지원하지 않는 클래스면 적용이 거부되므로, 새 PVC 를 만들어 데이터를 옮겨야 합니다.

PersistentVolume​

실제 저장 공간입니다. 스토리지 > 영구 볼륨 에서 봅니다.

상태뜻
Available아직 아무 PVC 에도 연결되지 않음
BoundPVC 에 연결되어 사용 중
ReleasedPVC 는 지워졌으나 공간이 아직 정리되지 않음
Failed정리에 실패

PV 는 클러스터 단위 자원입니다. 네임스페이스에 속하지 않아 목록에 다른 팀의 것도 함께 나옵니다.

Released 가 쌓이면 저장소 공간을 계속 차지합니다. 운영 담당자에게 정리를 요청하십시오.

스토리지 클래스란​

어떤 방식으로 저장 공간을 만들지 정해 둔 설정입니다. 스토리지 > 스토리지 클래스 에서 봅니다.

스토리지 클래스 목록

클래스마다 성능·비용·기능이 다릅니다. 사용자는 이름만 고르면 됩니다.

항목설명
프로비저너공간을 만드는 담당 구성요소
회수 정책PVC 를 지울 때 데이터를 어떻게 할지
볼륨 바인딩 모드언제 실제 공간을 만들지
기본값PVC 에 클래스를 적지 않으면 쓰이는 클래스

동적 프로비저닝​

옛날 방식에서는 운영 담당자가 PV 를 미리 만들어 두어야 했습니다. 개발자가 PVC 를 만들면 그중에서 맞는 것을 골라 연결하는 식입니다.

스토리지 클래스가 있으면 PVC 를 만드는 순간 PV 가 자동으로 만들어집니다. 이것을 동적 프로비저닝이라고 합니다.

정적 (옛 방식)동적
PV 준비운영자가 미리필요할 때 자동
크기미리 정한 것 중에서 선택요청한 만큼
대기 시간맞는 PV 가 없으면 무한 대기곧바로

지금은 대부분 동적 방식입니다. PVC 만 만들면 됩니다.

볼륨 바인딩 모드​

모드동작
ImmediatePVC 를 만들면 곧바로 공간을 만듭니다
WaitForFirstConsumer파드가 배치될 노드가 정해진 뒤에 만듭니다

WaitForFirstConsumer 인 클래스에서는 PVC 가 Pending 이어도 정상입니다. 파드를 만들면 그때 연결됩니다.

이 모드가 있는 이유는 이렇습니다. 저장 공간이 특정 노드에만 있는 경우(로컬 디스크), 공간을 먼저 만들면 파드가 그 노드에만 갈 수 있습니다. 노드에 자리가 없으면 파드가 영영 뜨지 못합니다. 파드 배치를 먼저 정하고 그 노드에 공간을 만들면 이 문제가 없습니다.

회수 정책​

정책PVC 를 지우면
Delete데이터가 함께 사라집니다
Retain데이터가 남습니다. 수동으로 정리해야 합니다

중요한 데이터에는 Retain 클래스를 쓰십시오. Delete 클래스에서 PVC 를 지우는 것은 되돌릴 수 없습니다.

클래스의 회수 정책을 나중에 바꿔도 이미 만들어진 PV 에는 적용되지 않습니다. 만들기 전에 확인하십시오.

Pending 에서 멈출 때​

원인확인할 것
스토리지 클래스 이름이 틀림목록에 있는 이름과 같은지
남은 용량이 부족저장소의 남은 공간
접근 모드를 지원하지 않음ReadWriteMany 를 지원하는 클래스인지
네임스페이스 용량 상한에 걸림관리 > 리소스 할당량 (8.1 장)
볼륨 바인딩 모드가 WaitForFirstConsumer정상입니다. 파드를 만들면 연결됩니다

PVC 상세 화면의 이벤트 에 원인이 남습니다. 먼저 여기를 보십시오.

데이터를 지키려면​

  • PVC 를 지우기 전에 쓰는 파드가 있는지 확인하십시오. 상세 화면에서 볼 수 있습니다.
  • Helm 릴리즈를 지워도 PVC 는 남는 경우가 있습니다. 반대로 지워지는 경우도 있으니 중요한 데이터는 미리 백업하십시오(9.1 장).
  • PVC 크기를 늘릴 수는 있어도 줄일 수는 없습니다. 클래스가 크기 변경을 지원해야 하고, 줄이는 것은 어떤 클래스도 지원하지 않습니다.
  • 백업은 Kubernetes 가 자동으로 해 주지 않습니다. 별도 백업 도구나 저장소 자체의 스냅숏 기능을 쓰십시오.