공부하고 기록하는, 경제학과 출신 개발자의 노트

학습일지/kubernetes

CKA 대비 kubernetes 스터디 - 7. Storage

inspirit941 2022. 4. 2. 15:55
반응형

Docker Storage

스크린샷 2022-03-26 오전 10 27 31

크게 두 가지 개념이 있다.

Storage Driver

docker는 데이터를 어디에 저장하는지, container에서 fileSystem을 어떻게 관리하는지.

스크린샷 2022-03-26 오후 6 36 52

  • docker image를 실행하면, /var/lib/docker 라는 경로를 컨테이너 내부에 생성한다.
    • aufs, containers, image, volumes 등 하위 경로도 같이 만들어진다. 여기까지가 docker에서 흔히 말하는 'data' 필드.

Docker의 Layered Architecture


스크린샷 2022-03-26 오후 6 40 08

  • dockerfile의 맨 윗줄부터 하나씩 레이어를 쌓아가면서 이미지를 생성한다.
  • 각 레이어는 이전 레이어에서 추가된 내용만을 저장하며, 로컬에 캐시된다.
  • 따라서, 비슷한 dockerfile을 빌드하게 될 경우 layer를 새로 생성하는 대신, 이전에 캐시해둔 레이어를 재활용한다.
    • 빌드 속도를 빠르게 가져갈 수 있고
    • disk의 불필요한 중복저장을 최소화할 수 있다.

스크린샷 2022-03-26 오후 7 19 15

  • 여러 layer가 합쳐져 만들어진 docker image는 READ Only, immutable 상태가 된다.
  • 변경사항을 반영하려면 새로운 이미지를 빌드해야 함. (변경되지 않은 레이어는 재사용이 가능하다)
  • docker run을 실행할 경우, image 위에 container layer가 생성된다.
    • container layer는 컨테이너 위 애플리케이션에서 생성되는 데이터 - log file나 임시파일 등 사용자에 의해 변경된 모든 파일들 - 이 만들어지는 영역.
    • 즉 READ / Write가 가능하지만, container layer는 해당 컨테이너가 실행될 때에만 임시로 존재하는 ephemeral 레이어다.

스크린샷 2022-03-26 오후 8 15 30

  • 소스코드는 image layer에 있고, 여러 컨테이너에서 같은 layer를 공유해서 사용할 수 있다.
  • 소스코드를 수정하는 로직을 실행할 경우, READ Only인 이미지 레이어에서 Container layer로 소스코드를 복사한 뒤, 복사한 코드를 수정한다. = CopyOnWrite Mechanism
    • 이미지에 있는 파일 자체를 수정하는 게 아니라, 복사본을 떠서 ephemeral Layer에서 수정하는 것.
  • 따라서 container layer에서 수정한 소스코드 파일은 컨테이너가 종료되면 같이 삭제된다.

스크린샷 2022-03-26 오후 8 45 35


  • Layered Architecture를 관리하고
  • Writable Layer를 생성하고
  • file의 이동, 복사 등

을 관리하는 컴포넌트가 Storage Driver

  • Storage Driver는 OS가 선택해 사용한다.
    • 예컨대 ubuntu의 경우 AUFS를 사용하며, 다른 Storage Driver는 동작하지 않는다.
  • docker는 해당 OS에서 사용하는 최선의 storage driver를 선택해 실행한다.

스크린샷 2022-03-26 오후 8 20 43

만약 컨테어너가 종료되더라도 특정 파일이나 변경사항이 남아있어야 할 경우, Persistent Volume을 사용해야 한다.


Volume Mounting. -> /var/lib/docker/volumes 경로에 마운트.

  • docker volume create data_volume 명령어를 실행한다.
    • /var/lib/docker/volumes 하위에 data_volume 디렉토리가 생성된다.
    • 여기에 생성된 경로를 -v 옵션을 줘서 적용하면, rewrite layer로 해당 디렉토리를 활용할 수 있게 된다.
    • docker run -v data_volume:/var/lib/mysql mysql : mysql이 데이터를 저장하는 기본 경로를 data_volume 디렉토리로 Mount한 뒤 mysql 이미지를 실행한다.
    • mysql 컨테이너에서 생성된 모든 변경사항이 /var/lib/docker/volumes/data_volume에 저장되는 방식.
  • 미리 volume을 생성하지 않고 바로 docker run -v data_volume2:/var/lib/mysql mysql 형태로 실행하면, data_volume2 디렉토리를 생성하고 마운트한 뒤 mysql 이미지를 실행한다.

Bind Mounting. -> docker host의 어느 경로에도 마운트할 수 있음.

  • 기존 디렉토리를 mount하고 싶다면 docker run -v /data/mysql:/var/lib/mysql mysql 처럼 full path를 입력해주면 된다.

cf. 자료 사진의 -v 옵션은 옛날 옵션이며, --mount를 사용하는 게 좋다고 안내함.

  • docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql 형태로 사용하는 것을 권장.

Volume Driver Plugin in Docker

스크린샷 2022-03-26 오후 8 49 15

storage Provider와 Volume Driver는 서로 다른 역할을 한다.

  • volume driver의 기본값은 local. docker 로컬 경로에 volume을 생성하고 persistency를 관리한다.
  • 퍼블릭 클라우드 스토리지를 지원하는 volume plugin을 사용하면, 데이터를 클라우드에 저장할 수 있다.

스크린샷 2022-03-26 오후 8 50 51

Container Storage Interface (CSI)

스크린샷 2022-03-26 오후 9 05 37


  • 예전에는 k8s에 embedded docker가 유일한 runtime Engine이었다.
  • 하지만 docker 외에 다른 container runtime과의 호환성을 위해 Container Runtime Interface를 사용하는 식으로 변경되었다.
  • Orchestration Tool이 container Runtime과 통신하기 위한 표준 인터페이스라고 보면 됨.

Runtime과의 호환성을 위해 CRI가 생겼다면, 네트워크 솔루션과의 호환에는 CNI, Storage와의 호환성을 위해서는 CSI가 만들어졌다고 보면 된다.


스크린샷 2022-03-26 오후 9 07 41

CSI는 단순히 k8s뿐만 아니라 Orchestration tool 자체와 storage 간의 통신규약을 위한 프로토콜이다.

  • ex) Orchestration tool에서 CreateVolume RPC로 volume 생성 요청 시 -> volume 이름 같은 파라미터를 필수로 전달
  • Storage는 CreateVolume RPC의 Implementation이 있어야 함.

Volume


스크린샷 2022-03-27 오전 7 09 39

  • container 자체는 short period of time 실행을 위한 것. 필요하면 프로세스로 올라와서 작업하고, 작업이 끝나면 사라진다.
  • container 내부에서 생성되는 데이터도 마찬가지로 ephemeral.
  • 컨테이너에서 사용한 데이터를 보존하고 유지하기 위해서는 컨테이너의 생성 시점에서 volume attach가 필요하다.

k8s에서는 pod에 volume attach를 사용해서 데이터의 영속성을 유지한다.


스크린샷 2022-03-27 오전 7 17 29


  • volumes 필드로 host (node)에 데이터를 저장해둘 경로를 지정하고
  • container의 volumeMounts 필드로 volumes를 연결한다.
  • 위 예시의 경우, container의 /opt 디렉토리에 쓰이는 모든 파일은 node의 /data 디렉토리에 저장된다. 따라서 컨테이너가 종료되더라도 컨테이너에서 실행한 데이터는 남아 있다.

스크린샷 2022-03-27 오전 7 19 58


하지만 host의 Directory를 직접 사용하는 방식은 멀티 노드에서는 권장하지 않는다.

  • 여러 pod가 돌고 있는 각각의 노드에서 전부 동일한 데이터를 유지한다는 보장이 없기 때문.
  • 따라서 k8s에서는 다양한 방식의 volume mount storage를 제공하고 있다.

스크린샷 2022-03-27 오전 7 24 19


예컨대 AWS EBS를 storage로 정하고 싶다면 yaml 옵션을 위와 같이 변경하면 된다. 작업한 데이터는 전부 AWS EBS storage에 저장된다.


Persistent Volume

스크린샷 2022-03-27 오전 8 56 53

  • pod에 volume을 마운트해서 사용하는 것까진 좋은데, 사용자가 많아서 pod을 여러 개 띄워야 하는 앱일 경우 각 pod마다 yaml파일에 일일이 정의해야 하는 문제가 있다.
    • 경로를 수정하거나 할 경우, 기존 Pod의 yaml 파일을 빠짐없이 변경해야 하는 등 유지보수에 번거로움.
  • 좀더 Centralized Storage 방식을 사용하는 게 Persistent Volume
    • Large Pool of Storage를 만들어두고, pod에서 carved out pieces 하도록 만든 것.
    • pod에서 Persistent Volume에 storage 할당을 요청하는 게 PVC (Persistent Volume Claim.)

스크린샷 2022-03-27 오전 9 00 30


  • accessModes : volume이 마운트되는 방식을 정의함.
    • ReadOnlyMany, ReadWriteOnce, ReadWriteMany 세 가지 옵션이 있다.
  • hostPath를 지정하면 디렉토리를 설정할 수 있지만, production에서는 권장하지 않는다.
  • 위의 예시는 AWS EBS를 사용해서 Persistent Volume을 생성하도록 하는 명령어.

Persistent Volume Claim

스크린샷 2022-03-27 오전 10 07 33


  • PV와 PVC는 Namespace별로, 서로 별개의 k8s Object.
    • Admin은 PV를 생성하고, user가 PVC를 생성해서 필요한 양의 storage를 요청 후 할당받는 식.
  • 1 PVC -> bind to 1 PV. 일대일 관계.

기본적으로는 requested claim을 충족할 만큼의 capacity가 있는 Persistent Volume을 binding해 준다.

  • 일단 용량부터 맞으면, 그 후에 access mode / volumen mode / storage class 등을 따져서 최종적으로 적합한 PV를 할당한다.
  • 정 맞는 게 없으면, PVC보다 큰 용량의 PV가 할당될 수 있다. PVC와 PV는 1:1 관계이므로, 이 경우 PV의 용량이 남는다 해도 다른 요청을 위해 할당해줄 수 없다.
  • 맞는 요청이 하나도 없다면, PVC는 Volume 여유분이 생길 때까지 Pending 상태로 남아 있다.

스크린샷 2022-03-27 오전 10 08 37


  • 만약 하나의 요청에 부합하는 PV가 여러 개 있고, 그 중 특정 PV만 사용하고 싶다면 labelSelector를 사용하면 된다.

스크린샷 2022-03-27 오전 10 14 59

  • PVC
    • AccessMode : ReadWriteOnce
    • Resource Request : 500Mi
  • PV
    • AccessMode : ReadWriteOnce -> 일치
    • Resource Request : 1Gi -> 요청한 양보다 많지만, 다른 PV 선택지가 없으면 이 PV가 할당된다.

스크린샷 2022-03-27 오전 10 24 09

  • Delete 요청 -> PVC와 Binding되어 있던 PV가 분리된다.
    • ReclaimPolicy 옵션을 제공할 수 있음.
    • Retain: 일시적으로 분리한 상태. 다른 PVC에게 할당할 수 없는 상태가 되며, Admin이 직접 삭제해야 지워진다.
    • Delete: 자동으로 삭제. 따라서 PVC가 삭제되면 할당된 PV가 삭제되고, 디바이스에 여유공간이 남는 것.
    • Recycle: data volume에 저장되어 있던 데이터만 날리는 것. 다른 PVC가 사용할 수 있는 상태가 된다.

스크린샷 2022-03-27 오전 10 32 38

Storage Class

스크린샷 2022-03-27 오전 10 35 56

Static Provisioning

GCP에 PV를 적용하기 위한 예시. PVC를 생성하기 전에

  • google cloud에 PV가 만들어져 있어야 한다.
  • PV definition yaml 파일이 생성되어 있어야 한다.

이렇게 PVC 생성하기 전에 직접 PV yaml파일을 생성하고, storage 공간을 미리 확보해두는 것을 Static Provisioning이라고 부른다.

Provision Automatically 해주면 편할 텐데, 그 기능을 지원하는 게 storage class.

Dynamic Provisioning

스크린샷 2022-03-27 오전 10 36 52

스크린샷 2022-03-27 오전 10 44 52

  • 이렇게 될 경우, PV를 직접 정의할 필요가 없다. StorageClass가 사실상 PV 역할을 대신할 수 있는 object이기 때문.
  • PVC의 definition에 storage class에서 정의한 metadata.name 필드를 추가해준다. storageClassName: <storage-class-metadata-name>
  • pod는 PVC의 metadata.name을 사용하고, PVC는 storageClassName 값으로 storageClass object를 찾는다.
    • storageClass는 자동으로 PV를 생성하고, PVC - PV - Storage 간 연결을 지원해준다. storageClass라고 해서 PV를 안 쓰는 게 아님. storageClass가 대신 생성하고 관리하는 거다.

스크린샷 2022-03-27 오전 10 48 16

  • provider마다 제공할 수 있는 옵션이 다를 수 있음. 그건 parameter 필드에서 확인 가능하다.
  • gcp의 경우 type으로 storage의 기본 설정값 (standard, ssd), replicationType으로 regional-pd 등의 옵션을 줄 수 있다.

스크린샷 2022-03-27 오전 10 48 16


  • 옵션을 토대로, 여러 개의 storage class를 생성해서 비즈니스 로직에도 활용할 수 있다.
반응형