[Kubernetes] AWS EKS에 볼륨 마운트 해보기

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 EKS 클러스터에 EFS를 마운트해서 볼륨으로 사용하는 내용을 정리해보려고 합니다. 필자가 속한 프로젝트에서는 log, config 파일등을 어떻게 관리할지를 고민하고 있는 단계입니다. 우선 공유 해서 사용할 수 있는 것은 최대한 공융를 해서 사용해보려고 합니다.

지난 글들은 아래를 참고 해주시면 됩니다.

K8S에서의 볼륨을 마운트 하는 방식에는 지난 시간에 정리해둔 포스팅을 참조해주시기 바랍니다.

쿠버네티스 볼륨 정리

다음의 세가지에 대해서 정리를 할예입니다.

  • hostpath 마운트
  • EBS 마운트
  • EFS 마운트

1. hostpath로 로그 마운트 하기

hostpath같은 경우는 worker-nodes를 host로 보고 그 안에 생성된 POD끼리 host 내부의 경로를 공유해서 사용하는 형태입니다. 필자 같은 경우, POD로 아파치 미들웨어를 띄웠는데 그안에 생성되는 log(access, error)파일들을 host에서 볼수 있도록 hostpath로 지정할 생각을 해보았습니다

그림은 위와 같은 형태가 되겠습니다. POD를 감싼 박스가 1개의 host이고, host를 감싸는 박스가 한개의 가용 zone을 나냅니다.

pod < host < AZ 의 순으로 집합 관계를 표현할 수 있겠습니다.

  • deployment yaml 파일
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  # Deployment 객체의 Unique한 명칭
  name: disp-example-author
spec:
  # Deployment label selector for pod
  selector:
    matchLabels:
      app: dispatcher-author
  # 3 Pods should exist at all times.
  replicas: 2
  template:
    metadata:
      labels:
        # Pod의 라벨
        app: dispatcher-author
    spec:
      containers:
      - name: dispatcher-author
        # Run this image
        imagePullPolicy: Always
        image: author
        volumeMounts:
        - mountPath: /usr/local/apache2/logs
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          path: /test
          type: Directory

위와 같은 형태가 되는데, 우선 replica를 2개로 구성했습니다. 필자는 1개의 cli 인스턴스와 2개의 worke-nodes로 구성을 해두었습니다. 그래서 2개의 pod을 띄워 각각 host의 경로에 log를 쌓도록 해두었습니다.

기존에 deployment에서 추가되는 부분은 아래와 같습니다.

        volumeMounts:
        - mountPath: /usr/local/apache2/logs
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          path: /test
          type: Directory

보시면, volumes를 host의 경로로 지정을 합니다(단, 여기서 경로는 반드시 생성이 되어있어야 합니다. )

해당 volume을 POD의 특정 경로로 마운트 합니다. /usr/local/apache2/logs

도커의 -v 옵션과 동일하게 host의 특정경로를 POD에 마운트 시켜서 사용하겠다는 내용입니다. 그러면, pod에 쌓이는 로그들이 host에서 적재가 되어, host에 직접 접속을 하면 볼 수 있는 효과가 있습니다.

그런데 여기서 하나의 worker-nodes에 여러개의 POD들이 같은 경로에 마운트 되었을경우에는 같은 파일에 대해서 어떤 처리가 되는지는 테스트가 필요할 것 같습니다.

2. EBS 마운트 하기

우선 host 방식에서 같은 파일에 대한 점유 문제로 인해, EBS를 사용하면 어떻게 될까라는 생각을 해보았습니다. 그런데, EBS 자체가 1개의 인스턴스에 마운트 되어야 하고, 그것을 같은 POD들이 마운트해서 사용하면 역시 hostpath와 같은 문제가 발생할 것 같다는 생각을 해보았습니다

그런데, 제 생각과 달리, EBS를 마운트 하는 방식에서 문제가 생겼었습니다. 우선 파일들을 보면서 정리해보겠습니다

  • EBS 생성
  • EBS 볼륨 마운트

EBS를 직접 생성해준다음에 해당 volume id를 기반으로 hostpath와 동일하게 마운트 하는 방식입니다. 그런데, 제가 PV, PVC를 생성하지 않았기때문에 위의 그림과 같이 1개의 POD에만 물리는거 같습니다. replica를 2개로 해두면, 나머지 POD에 대해서는 이미 ebs 볼륨에 대한 자원이 마운트 되어 사용할 수 없다고 나오면서 에러가 납니다.

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  # Deployment 객체의 Unique한 명칭
  name: disp-example-author
spec:
  # Deployment label selector for pod
  selector:
    matchLabels:
      app: dispatcher-author
  # 3 Pods should exist at all times.
  replicas: 3
  template:
    metadata:
      labels:
        # Pod의 라벨
        app: dispatcher-author
    spec:
      containers:
      - name: dispatcher-author
        # Run this image
        imagePullPolicy: Always
        image: author
        volumeMounts:
        - mountPath: /test-ebs
          name: test-volume
      volumes:
      - name: test-volume
      # This AWS EBS volume must already exist.
        awsElasticBlockStore:
          volumeID: vol-0efbe085426300704
          fsType: ext4

위에 보시는것처럼 hostpath와 동일하게, 다음이 중요합니다.

    volumeMounts:
    - mountPath: /test-ebs
      name: test-volume
  volumes:
  - name: test-volume
  # This AWS EBS volume must already exist.
    awsElasticBlockStore:
      volumeID: vol-0efbe085426300704
      fsType: ext4

volumeID: vol-0efbe085426300704 실제로 이러한 볼륨을 내부 POD에 마운트 하여 사용한다고 보면됩니다.

**추가 수정할 부분은 직접 PV와 PVC 로 생성하여 마운트를 해볼 예정입니다. 아무래도 이렇게 하면 hostpath 와 동일하게 여러개의 POD에 마운트가 될것 같습니다.

3. EFS 마운트 하기

오늘의 정리하는 부분에서 제일 중요한 부분입니다.

EFS에서 보이는 차이점이 있으신가요? 우선 storage classEFS provisioner가 생성이 된것을 볼 수 있습니다. EKS 에서 EFS를 마운트해서 사용하기 위해서는 2가지 리소스가 필요합니다.

  • storage class : 어떤 스토리지를 사용할 것인가?
  • EFS provisioner : 생성된 EFS를 기반으로 어떠한 경로에 어떻게 마운트를 시킬까를 정의하는 POD입니다.
  1. 스토리지 클래스 및 컨피그 맵 정의
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/class.yaml
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/configmap.yaml

위의 configmap에서 아래 내용 수정

apiVersion: v1
kind: ConfigMap
metadata:
  name: efs-provisioner
data:
  file.system.id: fs-390f9d92              => 수정
  aws.region: us-west-2                    => 수정
  provisioner.name: example.com/aws-efs
  dns.name: ""
kubectl apply -f class.yaml
kubectl apply -f configmap.yaml
  1. 프로비저너 & 접근제어 설정
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/deployment.yaml
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/rbac.yaml

위의 프로비저너(deployment)에서 아래 내용 수정

volumeMounts:
  - name: pv-volume
  mountPath: /persistentvolumes
volumes:
  - name: pv-volume
    nfs:
      server: fs-1234abcd.efs.us-east-1.amazonaws.com    => 수정 
      path: /
kubectl apply -f rbac.yaml
kubectl apply -f deployment.yaml
  1. 테스트
  wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/claim.yaml
  wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/test-pod.yaml

우선 필자의 deployment 파일을 보자.

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  # Deployment 객체의 Unique한 명칭
  name: disp-example-author
spec:
  # Deployment label selector for pod
  selector:
    matchLabels:
      app: dispatcher-author
  # 3 Pods should exist at all times.
  replicas: 3
  template:
    metadata:
      labels:
        # Pod의 라벨
        app: dispatcher-author
    spec:
      containers:
      - name: dispatcher-author
        # Run this image
        imagePullPolicy: Always
        image: author
        volumeMounts:
        - name: efs-pvc
          mountPath: "/usr/local/apache2/logs"
      volumes:
        - name: efs-pvc
          persistentVolumeClaim:
            claimName: efs

중요한 부분은 아래와 같습니다.

        volumeMounts:
        - name: efs-pvc
          mountPath: "/usr/local/apache2/logs"
      volumes:
        - name: efs-pvc
          persistentVolumeClaim:
            claimName: efs

PV는 이미 프로비저너를 통해서 생성이 되어있고, PVC 역시 생성이 되어있습니다. 이부분이 모두 프로비저너에서 진행이 되고, 사용자는 어떻게 매핑을 시킬지만 위와같이 정의를 하면됩니다.

4. 마치며..

이번시간에는 hostpath, ebs, efs에 대해서 알아봤습니다. 아직은 볼륨을 어떤식으로 적절하게 사용할 수 있을지는 정하지 못했지만, EFS는 zone을 넘어서 모든 POD에서 공유를 할 수 있다는 장점때문에, config파일이나 공유해서 사용하는 파일들에 대해서는 꽤나 큰 장점이 있는 것 같습니다.

하지만, log 파일들에 대해서는 한곳에 모아두는것은 파일점유때문에 안되는 것 같습니다. 그래서 다음시간에는 로그를 어떻게 모니터링할지에 대한 정리를 할 예정입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다