본문 바로가기
Framework and Tool/Kubernetes

Kubernetes - Volume

by ocwokocw 2022. 11. 12.

- 출처: Kubernetes in action

- 볼륨 소개

볼륨은 파드의 구성요소이며, 파드의 spec 에서 정의한다. 독립적인 쿠버네티스의 구성요소는 아니어서 자체적으로 생성이나 삭제가 불가능하다. 파드의 모든 컨테이너에서 사용가능하지만 접근하려는 컨테이너에서 마운트 돼야한다.
 
예를 들어 아래와 같은 컨테이너들이 있다고 가정해보자.
 
  • 웹서버: /var/htdocs 디렉터리에서 HTML 페이지 서비스, /var/logs 에 엑세스 로그를 저장하는 웹서버 실행
  • 컨텐츠 에이전트: /var/html 에 html 을 생성하는 에이전트
  • 로그 로테이터: /var/logs 디렉터리를 처리(로그 순환, 압축, 분석)
 
또한 아래 2 가지 볼륨을 갖는다고 가정하자.
 
  • 볼륨1: HTML 공유 볼륨
  • 볼륨2: 로그 공유 볼륨
 
위의 3 컨테이너들과 2 가지 공유 볼륨을 아래와 같은 시나리오로 사용해야 잘 동작할것이다.
 
  • 웹서버의 /var/htdocs에 볼륨1을 마운트, /var/logs에는 볼륨2를 마운트
  • 컨텐츠 에이전트의 /var/html에 볼륨1을 마운트
  • 로그 로테이터의 /var/logs에 볼륨2 마운트
 
각 컨테이너는 볼륨을 마운트하지 않으면 같은 파드여도 해당 파일에 접근할 수 없다. 컨테이너에서 접근하려면 파드에서 볼륨을 정의하고 볼륨 마운트를 컨테이너 spec에 정의한다.

- 볼륨 유형

  • emptyDir: 일시적 데이터를 저장하는데 사용되는 빈 디렉토리
  • hostPath: 워커노드의 파일 시스템을 파드의 디렉터리로 마운트
  • gitRepo: Git repo.를 체크아웃해 초기화한 볼륨
  • nfs: NFS 공유를 파드에 마운트
  • gcePersistentDisk, awsElasticBlockStorage, azureDisk: 클라우드 제공자의 전용 스토리지 마운트
  • cinder, cephfs, iscsi, 등: 다른 유형의 network 스토리지 마운트
  • configMap, secret, downwardAPI: 쿠버네티스 리소스나 클러스터 정보를 파드에 노출하는데 사용되는 특별한 볼륨
  • persistentVolumeClaim: 사전에 혹은 동적으로 프로비저닝된 퍼시스턴트 스토리지를 사용하는 방법
 
위에서 특수 유형의 볼륨은 데이터를 저장하지 않으며 쿠버네티스의 메타데이터를 파드에 실행중인 앱에 노출하는데 사용된다.

- emptyDir

빈 디렉터리로 시작하며 라이프사이클이 파드에 묶여있어 파드 삭제시 볼륨의 컨텐츠를 삭제한다. 동일 파드에서 컨테이너간 파일을 공유하는데 사용되거나 컨테이너에서도 큰 데이터셋 정렬을 위해 임시데이터를 디스크에 쓰는 목적으로도 사용된다.
 
볼륨 소개절에서 언급했던 웹서버와 컨텐츠 에이전트 컨테이너가 emptyDir 유형의 볼륨을 공유하도록 파드를 정의해보자.
 
apiVersion: v1
kind: Pod
metadata:
  name: fortune
spec:
  containers:
  - image: luksa/fortune
    name: html-generator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs
  - image: nginx:alpine
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: html
    emptyDir: {}
 
luksa/fortune 이미지를 사용하는 첫번째 컨테이너는 10초마다 랜덤 문구를 /var/htdocs/index.html에 쓴다. nginx:alpine 이미지를 사용하는 2번째 컨테이너는 Nginx 서버가 서비스하는 기본 디렉토리 /usr/share/nginx/html 의 파일을 서비스하기 시작한다.
 
각 컨테이너는 마운트할 볼륨을 volumeMounts 하위에 작성한다. html 이라는 볼륨을 자신의 mountPath에 마운트 한다. html 이라는 볼륨은 컨테이너간에 공유할 수 있으므로 컨테이너와 동레벨의 volumes 에서 정의한다.
 
 
 
위의 pod yaml을 생성하고 포트 포워딩 해준 후 브라우저로 접속해보면 아래와 같은 문구를 볼 수 있다.
 
 
 
emptyDir 은 파드를 호스팅하는 워커 노드의 실제 디스크에 생성되므로 디스크 유형에 따라 성능이 결정된다. emptyDir을 디스크가 아닌 메모리를 사용하는 tmpfs 파일 시스템으로 지정 할 수도 있다.
 
- name: html
    emptyDir:
      medium: memory

- Git Repository 볼륨으로 사용

Git repo 볼륨을 기본적으로 emptyDir 볼륨이며 파드 시작시 Git repo 복제 후 특정 revision을 체크아웃한다.
 
Git repo 볼륨은 생성되고 나면 참조하는 repo와 동기화 되지는 않는다. 만약 rc가 파드를 관리하면 파드를 삭제하고 재생성시 해당 볼륨에 최신 커밋을 포함하게 된다.
 
만약 Git repo를 사용하면서 동기화를 원한다면 해당 로직을 nginx 웹서버와 동일한 컨테이너에 두는 것은 좋은 방법이 아니다. 대신 별도 2번째 컨테이너인 일명 "사이드카" 컨테이너에서 실행돼야 한다.
 
새로운 동기화로직을 앱 코드에 밀어넣으면 복잡성이 올라가고 재사용성이 떨어진다. Git repo 동기화 로직을 사이드카로 추출하면 다른 유형의 볼륨을 사용한다고 했을 때 기존 nginx 웹서버 앱을 그대로 사용하면서 볼륨 설정만 바꿔주면 된다.

- 워커 노드 파일시스템의 파일 접근

대부분의 파드는 호스트 노드를 인식하여 노드 파일시스템에 접근하지 않는다. 하지만 특정 시스템 레벨의 파드(데몬셋)들은 노드 파일을 읽는 경우가 있는데 쿠버네티스는 이를 위해 hostPath 볼륨을 제공한다.
 
hostPath 볼륨은 노드파일 시스템의 특정 파일, 디렉터리를 가리킨다.
 
gitRepo나 emptyDir은 파드 종료시 컨텐츠를 삭제하지만 hostPath는 컨텐츠를 유지한다. 단 컨텐츠를 유지한다는 조건은 신규 파드가 동일한 워커 노드로 스케줄링 되어야 한다.
 
 

 

댓글