새소식

Recent Study/udemy - CKA with Practice Tests

Section 8 : Storage

  • -

Introduction to Docker Stroage : 쿠버네티스 같은 컨테이너 오케스트레이션 도구 저장소를 이해하려면 먼저 저장소가 컨테이너로 어떻게 작동되는지 이해하는게 좋습니다. 먼저 Docker로 저장소가 어떻게 작동하는지 확인해봅시다.

 

Docker의 저장소에 관해서는 2가지 메인 개념이 있습니다.

1. Stroage Drivers

2. Volume Dirvers

 

Storage in Docker

 

 

시스템에 Docker를 설치하면 이 폴더 구조가 /var/lib/docker에 생성됩니다. AUFS 컨테이너라고 불리는 것 아래에 이미지 볼륨 등 여러개의 폴더가 있습니다. 이곳이 docker가 기본값으로 모든 데이터를 저장하는 곳이죠. 여기서 데이터란 Docker 호스트에서 실행되는 이미지 및 컨테이너와 관련된 파일을 말합니다.

 

 

이를 위해서 계층 구조를 이해하면 좋습니다. 도커는 이미지를 구축할 때 Layered architecture에 이것을 사용합니다. 도커 파일의 각각 지시 사항 명령은 도커 이미지에 새 레이어를 만듭니다. 이전 레이어에서 변경된 것만요. 위를 예로 3개의 이전 계층을 재사용해 최신 소스 코드를 빠르게 업데이트 하고, 응용 프로그램 이미지를 재구축합니다.

 

이 모든 계층은 최종으로 도커 이미지가 형성할 때 docker build 명령으로 생성됩니다. 빌드가 완료되면, 해당 계층의 내용물을 수정할 수 없습니다. 그리고 이 layer 상단에 write할 수 있는 새 layer를 만듭니다. 이 writeable layer는 애플리케이션이 작성한 로그 파일, 컨테이너가 생성한 임시 파일 또는 해당 컨테이너에서 사용자가 수정한 파일과 같이 컨테이너가 생성한 데이터를 저장하는 데 사용됩니다.

 

 

이 layer의 수명은 컨테이너가 살아있는 동안 지속되고, 컨테이너가 소멸되면 이 레이어와 여기에 저장된 모든 변경사항도 함께 소멸됩니다. 이 이미지를 사용하여 생성된 모든 컨테이너는 동일한 이미지 레이어를 공유합니다. 

 

 

새로 생성된 컨테이너에 로그인하고, temp.txt라는 새 파일을 생성한다고 말하면 컨테이너 레이어에 읽기 및 쓰기가 가능한 해당 파일이 생성됩니다. 그렇다면 Image Layers의 파일은 수정할 수 없나요? 아니요, 수정할 수 있지만 수정된 docker 파일을 저장하기 전에 Container Layer의 파일 복사본을 자동으로 만들고, Read Write 계층인 Container Layer에 앞으로 수정사항이 생길겁니다. 이후의 모든 수정은 Read Write 계층에서 파일을 수정하게 되고, 이것을 copy on mechanism이라고 합니다. 이미지 레이어가 읽기 전용이라는 것은 이러한 레이어의 파일이 이미지 자체에서 수정되지 않음을 의미합니다. 따라서 이미지는 docker build 명령을 사용하여 이미지를 다시 빌드할 때까지 항상 동일하게 유지됩니다.

 

 

컨테이너를 삭제하면 동시에, 새 임시 파일도 제거됩니다. 이 데이터를 유지하고 싶다면? Volume을 사용하면 됩니다. 이를 위해 docker volume을 이용합니다.

> docker volume create data_volume

> docker run -v data_volume:/var/lib/mysql mysql

 

1. docker 볼륨을 생성합니다.

2. docker 컨테이너를 실행할 때 docker 실행 명령을 이용해 이 볼륨을 docker 컨테이너 내부에 마운트 할 수 있습니다. 이런 v 옵션으로 레이어를 다시 쓰는거죠. 데이터베이스가 작성한 모든 데이터는 docker 호스트에 생성된 볼륨에 저장됩니다. 컨테이너가 파괴되어도 데이터는 살아있습니다. 

 

예로 docker run 명령으로 새 인스턴스를 생성합니다. data_volume2로요. 이때 create로 생성하지 않아도 Docker는 자동으로 볼륨을 만들어 컨테이너에 마운트합니다. 이를 volume mounting이라고 합니다.

만약 데이터가 다른 곳에 있다면 어떻게 할까요? 예로 /data 라는 다른 외부 저장소를 사용하고 있고, 해당 장소를 volume으로 사용하고 싶다면 어떻게 될까요? 이때는 마운트하려는 폴더의 전체 경로를 작성하면 됩니다. 컨테이너에 폴더를 마운트합니다. 이를 bound mounting이라고 합니다.

> docker run -v /data/mysql:/var/lib/mysql mysql

 

이렇게 마운트의 종류는 2가지 입니다. volume mounting, bound mounting.

 

참고로 -v를 사용하는 것은 예전 스타일입니다. 새로운 방법은 --mount를 사용하는 것입니다. --mount는 각 파라미터를 키와 값의 형식으로 지정할 수 있기에 선호되는 방식입니다. 방식은 아래와 같습니다.

> docker run --mount type = bind, source=/data/mysql, target = /var/lib/mysql mysql

그래서 이 모든 것을 책임지는 것은 무엇일까요? Layered 아키텍처를 유지하고, 파일을 이동해 복사와 쓰기를 가능하게 하는 것이요. 이는 Storage Driver입니다. 각 운영체제에 맞는 Storage Driver가 있고, 다른 특성과 안정성을 제공하고 있습니다.

 

 

Storage Driver

스토리지 드라이버는 이미지 및 컨테이너의 저장소를 관리하는 데 도움이 됩니다. 또한 이전 강의에서 볼륨에 대해 간략하게 다루었습니다. 스토리지를 유지하려면 볼륨을 생성해야 한다는 것을 배웠습니다. 볼륨은 스토리지 드라이버에 의해 처리되지 않는다는 점을 기억하세요.

볼륨은 볼륨 드라이버 플러그인에 의해 처리됩니다. default 볼륨 드라이버 플러그인은 "Local" 입니다. 로컬 볼륨 플러그인은 Docker 호스트에서 볼륨을 생성하고 해당 데이터를 var/lib/docker volumes 디렉토리 아래에 저장하는 데 도움이 됩니다.

 

 

Container Stroage Interface

 

 

과거에 쿠버네티스는 Docker를 컨테이너 런타임 엔진으로 사용했고, Docker와 작동하는 모든 코드는 쿠버네티스의 소스 코드에 내장되어 있었습니다. rkt, cri-o 같은 컨테이너 런타임이 들어오면서 다른 컨테이너 런타임을 작업하기 위해 지원을 열고 확장하는 것이 중요했습니다. 그렇게 Container runtime interface가 탄생되었습니다.

 

Container runtime interface는 쿠버네티스 같이 오케스트레이션 솔루션이 Docker 같은 컨테이너 런타임과 어떻게 통신할지 정의하는 표준입니다. 앞으로는 어떤 컨테이너 런타임 인터페이스가 개발되더라도 cri 표준을 따르면 됩니다.

 

 

CSI는 쿠버네티스 특정 표준이 아닙니다. 보편적인 표준을 의미하고, 구현된 경우 모든 컨테이너 오케스트레이션 도구가 지원되는 플러그인이 있는 모든 스토리지 공급업체와 작동할 수 있습니다. 이것은 컨테이너 오케스트레이터에 의해 호출될 RPC 또는 원격 프로시저 호출 세트를 정의하며 스토리지 드라이버에 의해 구현되어야 합니다.

 

예를 들어 CSI는 파드가 생성되고 볼륨이 필요할 때 컨테이너 오케스트레이터(이 경우 Kubernetes)가 볼륨 생성 RPC를 호출하고 볼륨 이름과 같은 세부 정보 집합을 전달해야 한다고 말합니다. 스토리지 드라이버는 이 RPC를 구현하고 해당 요청을 처리하고 스토리지 어레이에서 새 항목을 프로비저닝하고 작업 결과를 반환해야 합니다. 마찬가지로 컨테이너 오케스트레이터는 볼륨이 삭제될 때 볼륨 삭제 RPC를 호출해야 하며 스토리지 드라이버는 해당 호출이 이루어질 때 어레이에서 볼륨을 폐기하는 코드를 구현해야 합니다.

 

 

Volumes

 

 

쿠버네티스에서 생성된 pod는 본질적으로 일시적입니다. pod를 생성한 후 삭제하면 처리한 데이터도 함께 삭제됩니다. 이를 위해 pod에 볼륨을 연결합니다. pod에서 생성된 데이터는 볼륨에 저장되고, 삭제된 후에도 데이터가 그대로 유지됩니다.

 

 노드에 볼륨을 생성합니다. (보라색 원) 간단하게 구성해 호스트에 있는 디렉터리를 사용하도록 하겠습니다. 아래 경우에는 호스트에서 경로를 지정합니다 /data 볼륨에 생성된 파일은 Node1의 디렉터리 /data에 저장됩니다. 볼륨이 생성되면 컨테이너에서 이에 접근하기 위해 컨테이너 내부의 디렉터리에 그 볼륨을 마운트합니다. 각 컨테이너에서 볼륨 마운트 필드를 사용해 디렉터리에 데이터 볼륨을 마운트합니다. 이는 컨테이너 내부의 OPT입니다. 임의 숫자는 이제 컨테이너 안에 있는 /opt에 작성됩니다. 데이터 볼륨에 있는거고, 

 

 

Persistent Volumes

 

 

앞서 배운 Volumes는 volume 저장소를 구성하는 데 필요한 모든 구성 정보가 pod 정의 파일에 들어갑니다. 사용자가 많은 넓은 환경에서 많은 pod를 배포할 경우 사용자는 각각의 저장소를 구성해야 합니다. 스토리지를 보다 중앙에서 관리하기에는 Persistent Volume이 좋습니다.

 

사용자는 Persistent Volume을 이용해 해당 풀을 저장소로 선택할 수 있습니다. accessMode가 의미하는 것은 호스트에 볼륨이 어떻게 마운트 되어야 하는지 정의합니다. 다음은 용량을 정의할 수 있고, capacity에 해당하는 값을 작성하면 됩니다. 다음은 hostPath 옵션입니다. 노드의 로컬 디렉터리에서 저장소를 이용하는 것이죠.

 

 

Persistent Volume CLAIMS

 

 

persistent volume 및 persistent volume claims은 Kubernetes 네임스페이스에서 두 개의 다른 오브젝트입니다. 관리자는 persistent volume 세트를 생성하고 사용자는 스토리지를 사용하기 위해 persistent volume claims을 생성합니다. persistent volume claims이 생성되면 Kubernetes는 request와 volume에 설정된 속성을 기반으로 persistent volume을 claims에 바인딩합니다.

 

모든 persistent volume claims은 단일 persistent volume에 바인딩됩니다. 바인딩 프로세스 중에 Kubernetes는 claims에서 요청한 대로 용량이 충분한 persistent volume을 찾으려고 합니다. 여기에는 Access Modes, Volume Modes, Storage Class, Sufficient Capacity 등과 같은 기타 모든 요청 속성도 반영이 됩니다.

 

그러나 단일 claims에 대해 가능한 볼륨이 여러 개 있고 특히 특정 volume을 사용하려는 경우엔 레이블과 selector를 사용하여 올바른 volume에 바인딩할 수 있습니다. 마지막으로, 다른 모든 기준이 일치하고 더 나은 옵션이 없는 경우 더 작은 claims이 더 큰 volume에 바인딩될 수 있습니다.

 

claims과 volume 사이에는 일대일 관계가 있으므로 다른 claims은 volume의 나머지 용량을 사용할 수 없습니다. 사용 가능한 volume이 없는 경우 persistent volume claims은 클러스터에서 새 volume을 사용할 수 있을 때까지 보류 상태로 유지됩니다. 최신 volume을 사용할 수 있게 되면 claims은 자동으로 새로 사용 가능한 volume에 바인딩됩니다.

 

claims이 삭제되면 default persistent volume은 어떻게 되나요? 이 때 volume에 상태를 선택할 수 있습니다. default로는 볼륨을 유지하도록 설정되어 있습니다.

 

1)persistentVolumeReclaimPolicy: Retain은 관리자가 수동으로 삭제할 때까지 남아 있음을 의미합니다. 다른 claims에서 재사용할 수 없습니다.

2)persistentVolumeReclaimPolicy: Delete 로 설정하면 claims이 삭제되는 즉시 volume도 삭제됩니다. 따라서 최종 저장 장치의 저장 공간을 확보합니다. 세 번째 옵션은 재활용하는 것입니다.

3)persistentVolumeReclaimPolicy: Recycle로 설정하면, 데이터 volume의 데이터는 다른 claims에서 사용하기 전에 삭제됩니다.

 

 

Storage Class

1) static Provisioning : 여기서 문제는 이 PV가 생성되기 전에 Google Cloud에 디스크를 생성해야 한다는 것입니다. 애플리케이션에 스토리지가 필요할 때마다 먼저 Google Cloud에서 디스크를 수동으로 프로비저닝한 다음 생성한 디스크와 동일한 이름을 사용하여 persistent volume definition 파일을 수동으로 생성해야 합니다. 이를 static provisioning volume이라고 합니다.

 

 

2)dynamic Provisioning : 애플리케이션이 필요로 할 때 volume이 자동으로 프로비저닝 된다면 좋았을 것입니다. 여기서 스토리지 클래스가 필요합니다. 스토리지 클래스를 사용하면 Google Cloud에서 스토리지를 자동으로 프로비저닝하고 claims이 있을 때 파드에 연결할 수 있는 프로비저너(예: Google Storage)를 정의할 수 있습니다. 이를 volume의 dynamic provisioning이라고 합니다.

 

3) storage class : API 버전이 storage.k8s.io/v1으로 설정된 스토리지 클래스 오브젝트를 생성하면 됩니다. 이름을 지정하고 프로비저너를 Kubernetes.io/gce-pd로 사용합니다. 저장을 위해 PVC를 사용하는 파드가 있고 PVC가 PV에 바인딩된 원래 상태로 돌아가서 이제 스토리지 클래스가 있으므로 더 이상 PV 정의가 필요하지 않습니다. 스토리지는 스토리지 클래스가 생성될 때 자동으로 생성됩니다. PVC가 우리가 정의한 스토리지 클래스를 사용하려면 PVC 정의에 스토리지 클래스 이름을 지정합니다. 이것이 PVC가 사용할 스토리지 클래스를 아는 방법입니다. 다음에 PVC가 생성되면 이와 연결된 스토리지 클래스는 정의된 프로비저너를 사용하여 GCP에서 필요한 크기의 새 디스크를 프로비저닝한 다음 persistent volume을 생성하고 PVC를 해당 volume에 바인딩합니다. 따라서 여전히 PV를 생성한다는 점을 기억하세요. 더 이상 수동으로 PV를 생성할 필요가 없다는 것입니다. 스토리지 클래스에 의해 자동으로 생성됩니다.

 

 

'Recent Study > udemy - CKA with Practice Tests' 카테고리의 다른 글

Section 9 : Networking  (0) 2024.07.28
KodeKloud - Test Record (section 8)  (1) 2024.07.20
KodeKloud - Test Record (section 7)  (2) 2024.07.12
Section 7 : Security  (0) 2024.07.12
KodeKloud - Test Record (section 6)  (0) 2024.07.02
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.