Kubernetes - Volume

Volume

emptyDir

컨테이너들끼리 데이터를 공유하기 위해서 볼륨을 사용한다.
최초 Volume이 생성 될 때는 항상 Volume이 비어있기 때문에 emptyDir라고 명칭되었다.

만약 Container1이 Web역할, Container2가 Backend역할을 처리해주는 서버라고 했을 때 이 Web서버에서 받은 특정 파일을 Mount된 Volume에 저장한다음 Backend 컨테이너 역시 이 Volume을 Mount해놓으면 두 서버가 이 Volume을 자신의 Local에 있는 파일처럼 사용하기 때문에 두 서버가 서로 파일을 주고 받을 필요가 없이 편하게 사용할 수 있다.

하지만 Volume은 Pod안에 생성이 되는 것이기 때문에 Pod에 문제가 발생해서 삭제되고 재생성되었을 경우 Volume 또한 데이터가 없어진다는 것을 의미한다.
따라서 Volume에 쓰이는 데이터는 꼭 일시적인 사용목적에 의한 데이터만 넣는 것이 좋다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-1
spec:
  containers:
    - name: container1
      image: nginx:1.14
      volumeMounts:
        - name: empty-dir
          mountPath: /mount1
    - name: container2
      image: hyun6ik/hello
      volumeMounts:
        - name: empty-dir
          mountPath: /mount2
   volumes:
   - name: empty-dir
     emptyDir: {}

mountPath는 컨테이너가 해당 path로 Volume을 Mount한다는 뜻이다.
mountPath의 경로가 컨테이너마다 다르더라도 각각의 path가 지정되는 Volume의 이름이 같다면 컨테이너마다 자신이 원하는 경로를 사용하더라도 같은 Volume을 Mount하고 있는 것이다.

hostPath

이름 그대로 한 Host 즉 Pod들이 올라가져 있는 Node의 Path를 Volume으로 사용한다는 의미다.
emptyDir과 다른 점은 hostPath를 각각의 Pod들이 Mount해서 공유하기 때문에 Pod들이 죽어도 Volume안에 있는 데이터들이 사라지지 않는다.

하지만 Pod가 죽어서 재생성될 때 꼭 해당 Node에 재생성된다는 보장이 없다.
따라서 재생성될 때 기존의 Node가 아닌 다른 Node에 재생성되었을 경우 해당 Volume을 Mount 할 수 없다.

Node가 추가될때마다 똑같은 이름의 경로를 만들어서 직접 Node에 있는 path끼리 Mount하면 문제가 되지 않지만 운영자가 직접 해줘야 한다. (자동화 할 수 없음 --> 비추천)

HostPath는 각각의 노드에는 기본적으로 각 노드 자신을 위해 사용되는 파일들이 있는데(시스템 파일, 설정파일) Pod 자신이 할당되어 있는 Host에 데이터를 읽거나 쓸때 사용한다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-2
spec:
  containers:
    - name: container
      image: nginx:1.14
      volumeMounts:
        - name: host-path
          mountPath: /mount1
  volumes:
    - name: host-path
      hostPath:
        path: /node-v
        type: Directory

Host에 있는 Path는 Pod가 만들어지기 전에 사전에 만들어져있어야 Pod가 생성될 때 에러가 나지 않는다.

HostPath는 Pod에 데이터를 저장하기 위한 용도가 아니라 Node에 있는 데이터를 Pod에서 쓰기 위한 용도다.

PVC / PV

Pod에 영속성있는 Volume을 제공하기 위한 기능이다.
실제 Volume들의 형태들은 다양하다. (Local, AWS, git ...)
이런 것들을 각각 PersistentVolume을 정의하고 연결한다.

Pod는 PersistentVolumeClaim을 통해서 PersistentVolume과 연결한다.
예를들어 쿠버네티스는 volume 사용에 있어서 User 사용영역과 Admin 사용영역으로 나눴다.
Admin은 쿠버네티스를 담당하는 쿠버네티스 운영자
User는 Pod에 Service를 만들고 배포하는 Service 담당자
Volume들의 종류는 많고 각각의 Volume들을 연결하기 위한 각각의 설정들도 다르다.

apiVserion: v1
kind: PersistentVolume
metadata:
  name: pv-1
spec:
  nfs:
    server: 192.168.0.xxx
    path: /sda/data
  iscsi: 
    targetPortal: 163.180.11
    iqn: iqn.200.qnap:...
    lun: 0
    fsType: ext4
    readOnly: no
    chapAuthSession: true
  gitRepo:
    repository: github.com...
    revision: master
    directory: ..

전문적으로 이런걸 관리하는 Admin이 PV를 만들어놓으면 User은 이 PV를 쓰기위해 PVC를 만드는데

apiVersion: v1
kind: PersistenVolumeClaim
metadata:
  name: pvc-01
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1G
  storageClassName: ""

예를들어 1G인 읽기쓰기가 가능한 볼륨을 할당해달라고 요청하면(storageClassName= "") 현재 만들어져있는 PV들 중에 선택이 되어서 만들어진다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-3
spec:
  containers:
    - name: container
      image: nginx:1.14
      volumeMounts:
        - name: pvc-pv
          mountPath: /volumne
  volumes:
    - name: pvc-pv
      persistentVolumeClaim:
        className: pvc-1

pod를 만들 때 persistenVolumeClaim에 pvc에 만들어져 있는 이름을 연결하면 이 볼륨을 컨테이너에서 사용하면 된다.

  1. 최초 Admin이 PV를 만들고
  2. User가 PVC를 만들면
  3. 쿠버네티스가 PVC내용에 맞는 적절한 PV에 연결하고
  4. Pod 생성시 PVC를 마운팅하면 된다.
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-1
spec:
  capacity:
    storage: 1G
  accessMode:
    - ReadWriteOnce
  local:
    path: /node-v
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
          - {key: node, operator: In, values: [node1]}

HostPath처럼 host에 있는 localPath를 사용하고 PV에 연결되어있는 Pod들은 node1으로 라벨링이 되어있는 Node 위에만 무조건 만들어진다는 뜻이다.
하지만 local 타입의 PV는 잘 사용하지 않는다.

좋은 웹페이지 즐겨찾기