Kubernetes 스토리지(Storage)

Config Map

Config Map이라는 리소스를 사용하여 환경 변수 등을 Key Value 쌍으로 저장할 수 있다. Config Map은 설정된 환경 변수를 볼륨으로 포드에 마운트합니다. 환경 변수의 설정은 매니페스트내의 spec안에 env라고 하는 항목을 마련해, 설정할 수도 있습니다. 그러나 이 경우 변수를 재사용할 수 없게 됩니다. 이 문제를 Config Map을 사용하여 해결할 수 있습니다.

구체적으로 어떻게 작성하는지에 대해 살펴 보겠습니다. 먼저 Config Map 매니페스트를 작성합니다. 이것은 kubectl create 명령에서 configmap을 지정하여 가능합니다. 아래의 예에서는 yaml 파일을 작성하고 있습니다. 이 경우 TEST_ENV라는 환경 변수에 Hello_world라는 문자열을 저장합니다.

kubectl create configmap my-config --from-literal TEST_ENV=Hello_World -o yaml > configmap.yaml 

위의 명령을 실행하여 만든 yaml 파일은 다음과 같다.
configmap.yaml

apiVersion: v1
data:
  TEST_ENV: Hello_World
kind: ConfigMap
metadata:
  creationTimestamp: "2022-09-08T08:29:59Z"
  name: my-config
  namespace: default
  resourceVersion: "10632"
  uid: 2371e43c-c361-40be-8ab9-5269edfb41c3

이 경우에는 yaml 파일의 1단에 data가 작성되고 있있는데, 이건 작성하는 노드가 가지는 데이터를 지정하는 항목이다. 이 경우는 단순히 key:TEST_ENVvalue:Hello_world를 나타내고 있다.

이와 같이 작성한 yaml 파일을 이용해 노드를 생성(kubectl apply)하고, 환경 변수를 이용하는 경우에는 Pod 생성시에 이 Config Map를 인용하여 사용할 수 있다.

아래와 같이 Pod 생성용의 yaml 파일에 작성한 것으로 Config Map의 정보의 반영을 실행한다.

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: helloworld
  name: helloworld
spec:
  containers:
  - env:
    # Pod에서 사용할 환경 변수 이름 지정
    - name: TEST_ENV_POD
      # valueFrom에서 name으로 지정한 환경 변수에 무엇을 넣을지 지정
      valueFrom:
        # configMap에서 인용하도록 지정
        configMapKeyRef: 
          # 이름이 my-config (위에서 만든)라는 configMap을 지정
          name: my-config
          # name으로 지정된 configMap에서 key가 TEST_ENV 인 환경 변수를 참조하도록 지정
          key: TEST_ENV
    image: gcr.io/google-samples/hello-app:1.0
    ports:
    - containerPort: 8080

위에 pod.yaml의 경우, helloworld라는 Pod를 생성하는 yaml 파일이지만, helloworld 내의 환경 변수로 TEST_ENV_POD를 만들고, 그 내용은 my-config라는 Condig Map의 TEST_ENV에 저장된 값을 사용한다는 것으로 지정되어 있다. 이러한 지정 방법으로 하는 것은 다른 Pod에서도 동일하게 이용할 수 있어 재사용성이 높일 수 있게 된다.

계속 해서 Pod에 Volume을 마운트하는 방법을 살펴 보겠다. Pod는 관리상의 기본 단위로 되어 있고, 가상 Network Interface(IP, 파일 시스템)를 공유한다고 하는 것을 앞에서 그랬는데, 이는 즉, Pod 자체가 Kubernetes상에서는 가상 호스트와 같이 생각될 수 있는 것을 의미한다. 이러한 Pod에 볼륨으로 Config Map을 마운트한다. Config Map은 환경 변수뿐만 아니라 Key-Value 쌍을 저장하고 해당 데이터를 파일로 볼륨에 마운트 할 수 있다. 위에서 본 것은 Config Map에 저장된 데이터를 환경 변수로 호출하였다.

이를 실현하기 위해 다음과 같이 pod.yaml 파일을 수정한다.
pod.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: helloworld-configmap-volume
  name: helloworld-configmap-volume
spec:
  containers:
  - image: gcr.io/google-samples/hello-app:1.0
    name: helloworld-configmap-volume
    ports:
    - containerPort: 8080
    resoueces: {}
    volumeMounts:
      #volume名を指定
    - name:my-config-volume
      # volume을 마운트하는 컨테이너의 파일 경로 지정
      mountPath: /my-config/TEST_ENV
    volume:
      # 작성할 볼륨 이름 지정
    - name: my-config-volume
      configMap:
        # Config Map 이름 지정
        name: my-config
        items:
          # Config Map에 있는 Key의 이름 지정
        - key: TEST_ENV
          path: keys

이 yaml 파일에서는 볼륨에 관해서, my-config라는 이름의 Config Map을 my-config-volume라는 이름의 볼륨으로 지정하고, 이 이름을 지정해 마운트를 실행하여, 그 때에 대응하는 컨테이너내의 패스명을 /my-config/TEST_ENV로 하는 것을 하고 있다. 이렇게 하면 파일화되어 변경할 수 있다는 장점이 있다.

영속 Volume

이어서 영속 Volumme(Persistest Volume)에 대해 살펴보겠다.

컨테이너에서는 데이터는 Pod내에 있는 Volume에 변경을 실시하는 것으로 데이터의 작성을 하고 있다. 따라서 Pod가 사라지면 데이터도 사라진다. 이를 방지하려면 클러스터 와이드의 Node에 있는 Persistest Volume에 데이터를 저장한다. 실제 동작으로는 여러 Node가 있는 클러스터내에 각 Node가 공유할 수 있는 volume(Persistest Volume)를 생성하여, 각 Node가 필요한 만큼만 이 공통 volume에 요구를 하여, 받아온 volume를 요구처의 Node 로 마운트한다는 것이다.

그 때문에, 공통적인 volume를 정의하는 yaml 파일(pv.yaml)과 요구 사항을 넣은 yaml 파일(pvc.yaml)을 준비하고, Pod(Node) 작성시에 사용하는 yaml 파일(pod.yaml)에는, 이 요구 사항을 참조하도록 작성한다. 각 파일의 샘플은 아래와 같다.

pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv
spec:
 storageClassName: manual
 # volume의 크기 지정
 capacity: 100M
 # 액세스 권한 범위 지정
 accessModes: ReadWriteOnce
 hostPath:
  #Node上のパスを指定
  path: "/mnt/pvc"

pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata: 
  name: pvc
spec:
 storageClassName: manual
 # 액세스 권한 범위 지정
 accessModes: ReadWriteOnce
 resources:
  # 요구 사항 지정
  requests:
    # 원하는 용량 지정
    storage: 10M

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: helloworld-pvc
  name: helloworld-pvc
spec:
  containers:
  - image: gcr.io/google-samples/hello-app:1.0
    name: helloworld-pvc
    ports:
    - containerPort: 8080
    resoueces: {}
    volumeMounts:
      # volume명 지정
    - name:my-pv
      # volume을 마운트하는 컨테이너의 파일 경로 지정
      mountPath: /mnt/pvc
    volume:
     # 작성할 볼륨 이름 지정
    - name: my-pv
      # 영구 볼륨 요청 이름 지정
      persistentVolumeClaim:
        name: pvc

실행하는 경우에는 위의 3개 파일을 차례로 kubectl apply으로 실행해 가게 되지만, 이에 앞서 클러스터에 디렉토리를 생성해 두어야 한다. 그러기 때문에 minikube를 사용하고 있는 경우에는 아래와 같이 커멘드로 클러스터에 접속하여 작성을 한다.

$ minikube ssh
$ sudo mkdir mnt/pvc