IT/Kubernetes

Deplyment에서 EBS PV 사용하기 (feat. EKS, 공유볼륨, EFS와 EBS 차이점)

엘티엘 2022. 4. 23. 08:50

EBS vs EFS

EKS에서는 PV로 EBS, EFS를 사용할 수 있다. 두개의 차이점을 간단히 설명하면 아래와 같다.

  • EBS
    • 하나의 EC2에만 mount 할수 있음
    • AZ 단위 서비스
    • 가격이 상대적으로 저렴 (0.1$/GB)
    • 볼륨의 크기를 사전에 결정 (수동 확장 가능)
  • EFS
    • 다수의 EC2에 mount 할수 있음(NAS 용도)
    • Region 단위 서비스
    • 가격이 상대적으로 비쌈 (0.2$/GB)
    • 볼륨의 크기는 자유롭게 확장 가능

정리하면 EFS는 NAS처럼 다수의 EC2와 AZ에서 공유볼륨을 사용하고자 할때 사용하며, EBS는 단일 EC2에서 데이터를 저장할때 사용하는 스토리지라는 것이다. (물론 비용은 EFS가 더 비싸고)

EBS를 Pod간 공유볼륨으로 사용할수 있을까?

일반적으로 Kubenetes 환경에서 다수의 Pod간의 공유볼륨을 사용하려면 EFS(=NAS)를 사용한다. 다만 Application 특성상 동일 instance에 Pod를 띄울수 있다면(혹은 그래야 한다면) EBS를 사용해도 Pod간 공유볼륨이 가능하다. 그렇다면 좀더 저렴한 비용으로 공유볼륨을 사용할수 있게 된다.
그림으로 그리면 아래와 같다. EC2에 EBS를 mount 하고, 해당 EC2에 데이터를 공유할 pod를 띄운다. 이럴경우 EBS를 모든 Pod에 연결해서 공유볼륨처럼 사용할 수 있게 된다.

EBS를 공유볼륨으로 사용하기

이를 위해서는 아래 순서로 작업해야 한다.

  1. EBS용 PVC 생성하기
  2. Deployment에 PVC 연결하기
  3. Pod가 하나의 EC2에 Scheduling 되도록 PodAffinity 설정하기

1. EBS용 PVC 생성하기

EKS 환경이라면 기본적으로 EBS Storageclass 가 생성되어 있을것이다.

kubectl get sc

위 명령어를 실행하면 아래처럼 storageclass 리스트를 확인할수 있다 (아래 사진에선 gp2가 EBS용 storageclass 이다)

EBS storageclass 를 사용하는pvc yaml 작성후 실행한다. (storageclass와 accessModes 값 확인) 아직 PVC와 연결된 Pod가 없기때문에 PVC는 Pending 상태이고, PV는 생성되지 않는다 (PV는 Pod 생성시 pod의 AZ에 자동으로 생성된다)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-pvc
  namespace: temp
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: gp2

2. Deployment에 PVC 연결하기

deploymenet yaml에 아래를 추가해서 Deployment와 위에서 생성한 PVC를 연결한다.

      volumes:
      - name: ebs
        persistentVolumeClaim:
          claimName: ebs-pvc

3. Pod가 하나의 EC2에 Scheduling 되도록 PodAffinity 설정하기

PodAffinity를 사용해서 Pod가 동일 host에서 스케줄링되도록 설정한다. 아래는 pod에 app=ebs-deploy label을 추가하고, podaffinity로 해당 label을 설정항다. 이렇게 하면 app=ebs-deploy라는 label을 가진 pod가 있는 Node에만 pod를 생성하겠다는 뜻이고 항상 동일 node에 생성된다. (이외에도 NodeSelector 등 다양한 방법이 있다)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ebs-deploy
  namespace: temp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ebs-deploy
  template:
    metadata:
      labels:
        app: ebs-deploy
    spec:
....
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - ebs-deploy
            topologyKey: "kubernetes.io/hostname"

실행결과

deployment 를 생성하면 아래와 같이 pv가 하나 생성되고, 동일한 host에 pod가 실행되는것을 확인할수 있다.

참고로 AWS 콘솔에서 확인해보면 EBS가 하나 생성되고, 위에 출력된 EC2에 mount 된것도 확인할 수 있다.

참고사항

  • podaffinity가 제대로 설정되지 않으면 하나의 pod만 running 되고 나머지 pod는 pvc 연결이 정상적으로 되지 않아 pending 상태가 된다. 경우에 따라 모든 pod가 스케줄링되지 않아 모두 pending 상태일수 있다.
  • 생성순서를 확인해보면, 먼저 pod들이 하나의 ec2에 스케줄링된후, 해당 az에 ebs볼륨이 만들어진후, 해당 ec2에 마운트되는것을 알수 있다.
  • deplyment 삭제시 ebs pv도 삭제되며 ( storageclass의 reclaimpolicy을 따라간다) deployment 가 다시 배포되면 pv도 해당 az에 재생성된다.
  • 동일 ec2에 배포되기 때문에 ec2에 이상이 생기면 모든 pod가 영향을 받는다. 물론 self healing은 되지만 전체 pod가 동시에 down되므로 때문에 서비스 중단은 발생한다 (모든 pod의 health check 및 재생성 시간이 필요하기 때문에 꽤 긴 시간일수도 있다)


반응형