0부터 시작하는 AWS 공부 - EKS 활용하기 - EBS CSI 드라이버를 이용한 동적 프로비저닝

Jaehong Lee·2023년 4월 12일
4
post-thumbnail

1. EBS CSI 드라이버 설치

CSI 란

참조 : https://tech.gluesys.com/blog/2022/06/21/CSI.html
참조 : https://nice-engineer.tistory.com/entry/Kubernetes-EBS-for-CSI-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84-CSI%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

  • CSI ( Container Storage Interface) 란 컨테이너 오케스트레이션 시스템과 Storage Controller ( Plugin ) 사이의 Interface이며, gRPC 기반으로 구성되어 있다

    • CSI는 Storage를 제어하는 Plugin, Volume Life Cycle, 컨테이너 오케스트레이션 시스템과 CSI Plugin 사이의 인터페이스를 정의한다
  • CSI의 구성 요소

    • Provisioner : PV 생성
    • Attacher : Pod가 PVC 사용 시, PV를 Mount
    • Controller : Volume 생성 및 삭제
    • NodeServer : Pod가 배포될 Node에 Volume이 Mount될 수 있도록 환경 구성
  • Plugin 은 쿠버네티스와 같은 CO의 명령에 따라서 스토리지를 컨트롤하는 컨트롤러이다

    • 컨트롤러 Plugin : 스토리지 중앙 관리 기능을 담당하며, 아무 노드에서 동작해도 상관 없다
    • 노드 Plugin : 컨테이너가 동작하는 모든 노드에서 동작하는 Plugin으로, 각 Node를 제어한다
  • Volume Life Cycle은 다음과 같다

    • CREATED -> NODE READY -> Volume Ready -> PUBLISHED -> Delete Volume

EBS CSI Plugin 역할 생성

참조 : https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/csi-iam-role.html

  • Amazon EBS CSI Plugin이 사용자를 대신하여 AWS API를 호출하려면 IAM 권한이 필요하다. 이를 위해서 OIDC 자격 증명 공급자를 사용하는 역할 생성을 통해, EBS CSI 드라이버에 대한 IAM 정책을 EKS 클러스터의 OIDC와 연결해야 한다

  • EBS CSI Plugin을 위한 역할을 생성하자. IAM 콘솔에 들어가서 역할 생성을 누르자

  • 이전에 생성한 OIDC 자격 공급 증명자를 선택하고, 대상을 선택하자

  • 정책 추가에서 AmazonEBSCSIDriverPolicy를 선택하자
  • 역할을 생성하자

  • 생성한 역할의 신뢰 관계 편집에 들어가자
aud": "sts.amazonaws.com" 
# 위와 같이 써있는 곳을 찾자

sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
# 해당 부분을 위와 같이 바꾸자
  • aud": "sts.amazonaws.com"라고 써있는 부분을 찾아서 바꾸자
  • 정책 업데이트를 누르자


EBS CSI 드라이버 설치

  • EBS CSI 드라이버는 EKS 클러스터가 EBS를 사용하여 볼륨을 프로비저닝 및 관리해주는 CSI 드라이버이다

  • kubernetes.io/aws-ebs 프로비저너도 있는데 왜 EBS CSI가 필요한가?

    • 해당 프로비저너는 Kubernetes Source Code 내부에 존재하는 AWS EBS 프로비저너로, Kubernetes Release Lifecycle을 따라서 배포된다. 따라서 프로비저너의 신규 기능을 사용하려면 Kubernetes 버전을 업그레이드 해야 한다
    • 따라서 내부에 내장된 EBS 프로비저너를 사용하지 않고, EBS CSI 드라이버를 설치하여 ' EBS CSI Controller Pod ' 를 통해 볼륨 프로비저닝이 가능하도록 하겠다

  • EKS 클러스터 콘솔에 들어가서 ' 추가 기능 가져오기 ' 를 누르자

  • Amazon EBS CSI 드라이버를 선택하자

  • 위에서 생성한 역할을 지정하자
  • 드라이버를 설치하자

[honguser@ip-192-168-11-50 work]$ kubectl get pod -n kube-system
NAME                                  READY   STATUS    RESTARTS   AGE
ebs-csi-controller-6875b778b5-24nq9   6/6     Running   0          104s
ebs-csi-controller-6875b778b5-nb2dj   6/6     Running   0          103s
ebs-csi-node-d9swx                    3/3     Running   0          104s
ebs-csi-node-qtxn2                    3/3     Running   0          104s
  • EBS CSI 컨트롤러와 노드가 배포되었다
[honguser@ip-192-168-11-50 work]$ kubectl get sa -n kube-system
NAME                                 SECRETS   AGE
ebs-csi-controller-sa                0         3m
ebs-csi-node-sa                      0         2m59s
  • EBS CSI를 위한 Service Account도 배포되었다

2. EBS CSI 드라이버를 이용한 동적 프로비저닝

  • EBS 볼륨은 Pod가 생성되는 Node와 동일한 가용 영역에 있어야 한다

  • EBS는 특정 가용 영역에 생성되어 단일 EC2 인스턴스에 붙는 스토리지이므로 해당 EC2 인스턴스에 배포된 Pod 끼리만 공유 가능하다. 다른 인스턴스에 배포된 Pod와 스토리지를 공유하고 싶으면, EFS를 사용해야 한다

    • 따라서, PV의 accessModes가 ReadWriteOnce만 지원한다. 다른 인스턴스와 EBS 볼륨을 동시에 공유할 수 없기 때문이다
    • EFS는 EBS보다 가격이 비싸고, IO가 느린 단점이 있다

StorageClass 생성

참조 : https://kubernetes.io/ko/docs/concepts/storage/storage-classes/

  • Kubernetes에서는 StorageClass를 이용하여 프로비저너에게 명령을 전달하여 PV를 자동 생성하는 동적 프로비저닝을 트리거할 수 있다. StorageClass는 Namespace에 종속되지 않는다

    • 즉, 동적 프로비저닝은 StorageClass와 프로비저너를 사용하여 자동으로 PV를 생성해서 PVC와 Bound 시키는 기능이다
  • StorageClass 에는 Provisioner, Provisioning, Binding 관련 설정을 할 수 있다

    • volumeBindingMode : PV의 바인딩과 프로비저닝 동작 설정
    • ReclainPolicy : PV 재사용 시, PV 내용을 지울지 말지에 대한 설정
    • 사용할 프로비저너 지정 및 생성할 볼륨 사양에 대해서도 설정할 수 있다
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: hong-ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: Immediate
reclaimPolicy: Delete
parameters:
  csi.storage.k8s.io/fstype: ext4
  type: gp2
allowedTopologies:
  - matchLabelExpressions:
    - key: topology.ebs.csi.aws.com/zone
      values:
      - ap-northeast-2a
      - ap-northeast-2c
  • StorageClass를 작성하자

    • provisioner : 사용할 프로비저너인 EBS CSI를 지정
    • volumeBindingMode - Immediate : pvc 생성 시, 프로비저닝과 바인딩이 바로 발생하도록 설정
      • WaitForFirstConsumer라면, pvc를 사용하는 Pod가 배포될 때까지 Provisioning과 Mount를 지연시킨다
    • reclaimPolicy - Delete : 볼륨 사용이 끝나면, 삭제하도록 설정
    • parameters : EBS 볼륨 타입과 볼륨 파일 시스템 지정
    • allowedTopologies : 프로비저닝을 제한하기 위한 설정. Key와 Value를 통해 설정한다
      • Key - topology.ebs.csi.aws.com/zone : EBS 볼륨이 생성되는 가용 영역을 제한하기 위해 사용
      • values - 가용 영역 : EKS 클러스터 워커 노드가 위치한 가용 영역에 EBS 볼륨이 생성되게 설정
kubectl apply -f storageclass.yaml
  • 배포해주자
[honguser@ip-192-168-11-50 work]$ kubectl get storageclass
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  2d3h
hong-ebs-sc     ebs.csi.aws.com         Delete          Immediate              false                  40m
  • 배포된 StorageClass를 확인하자. 잘 배포되었다
  • EKS에 기본적으로 내장된 프로비저너인 kubernetes.io/aws-ebs를 위한 StorageClass가 배포되있는 것을 확인할 수 있다
  • 이제 해당 storageclass를 이용하여 pvc를 배포할 것이다


PVC 생성

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  namespace: hongspace
  name: hong-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: hong-ebs-sc
  • PVC를 작성하자. 요구하는 볼륨은 크기는 2Gi이고, 하나의 노드에서만 Read / Write가 가능해야 한다

    • resources : 요구하는 볼륨 사양
    • storageClassName : 사용하는 StorageClass. 특정 storageClass를 가진 pv는 해당 storageClass를 사용하는 pvc에만 연결된다
    • accessModes : Volume의 Read / Write 권한에 대한 옵션
      • ReadWriteMany : 여러개의 노드가 Read / Write 가능
      • ReadOnlyMany : 여러개의 노드가 Read 가능
      • ReadWriteOnce : 하나의 노드에서만 Read / Write 가능

    EBS는 accessModes에서 ReadWriteOnce만 지원한다! EBS는 단일 인스턴스에만 붙으므로, 다른 노드와 공유할 수 없기 때문이다. 다른 옵션을 사용하면 PVC 생성이 안된다

kubectl apply -f pvc.yaml
  • 배포해주자
[honguser@ip-192-168-11-50 work]$ kubectl get pv,pvc -n hongspace
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
persistentvolume/pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be   2Gi        RWO            Delete           Bound    hongspace/hong-pvc   hong-ebs-sc             2s

NAME                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/hong-pvc   Bound    pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be   2Gi        RWO            hong-ebs-sc    5s
  • PVC가 잘 배포되었으며, StorageClass를 통해 요구 사양에 맞는 PV도 프로비저닝되어 Bound되었다

  • 실제로 EBS 볼륨이 잘 생성되었다. 유형은 storageClass 에서 정의했으며, 크기는 pvc 에서 정의했다

Pod에 Mount 하기

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hong-deploy1
  namespace: hongspace
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hongdeploy1
  template:
    metadata:
      name: replica1
      labels:
        app: hongdeploy1
    spec:
      volumes: # volume 정의
      - name: hongvolume1 # volume 이름
        persistentVolumeClaim: # 사용할 Volume 방식. 이번에는 pvc를 사용한다
          claimName: hong-pvc # 사용할 pvc
      containers:
      - name: hongtainer1
        image: nginx
        ports:
          - containerPort: 80
        volumeMounts: # 컨테이너와 volume mount 정의
          - name: hongvolume1 # 사용할 volume
            mountPath: /hongdata # mount할 경로
---

apiVersion: v1
kind: Service
metadata:
  namespace: hongspace
  name: hong-svc1
spec:
  ports:
  - name: hong-svc-port
    port: 80
    targetPort: 80
  selector:
    app: hongdeploy1
  • volumeMounts 는 컨테이너의 특정 경로와 볼륨을 Mount 시켜준다
  • Pod의 spec 정의란에 Volume을 정의하자. 사용할 PVC와 Volume 이름을 정의하면 된다

    • 위와 같이 NFS를 통해 Volume을 사용할 수도 있다
kubectl apply -f deploy.yaml
  • 배포해주자
[ec2-user@ip-192-168-11-50 work]$ kubectl describe deploy -n hongspace hong-deploy1
.
.
.
  Containers:
   hongtainer1:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:
      /hongdata from hongvolume1 (rw)
  Volumes:
   hongvolume1:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  hong-pvc
    ReadOnly:   false
 .
 .
 .
  • 배포한 Deployment 상세 정보를 확인하면, Volume이 잘 Mount된 것을 확인할 수 있다
  • 나머지 2 개의 Deployment에 대해서 pvc를 배포하고, Mount 시키자

[honguser@ip-192-168-11-50 work]$ kubectl get pv,pvc -n hongspace
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
persistentvolume/pvc-3b4d964e-bd66-406e-82bf-475f77e57ff0   2Gi        RWO            Delete           Bound    hongspace/hong-pvc3   hong-ebs-sc             7s
persistentvolume/pvc-7c25f68c-f248-411e-893c-7790f3321e72   2Gi        RWO            Delete           Bound    hongspace/hong-pvc2   hong-ebs-sc             11s
persistentvolume/pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be   2Gi        RWO            Delete           Bound    hongspace/hong-pvc    hong-ebs-sc             39m

NAME                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/hong-pvc    Bound    pvc-d0ef839b-f17a-410d-be9a-4ea35b1f15be   2Gi        RWO            hong-ebs-sc    39m
persistentvolumeclaim/hong-pvc2   Bound    pvc-7c25f68c-f248-411e-893c-7790f3321e72   2Gi        RWO            hong-ebs-sc    15s
persistentvolumeclaim/hong-pvc3   Bound    pvc-3b4d964e-bd66-406e-82bf-475f77e57ff0   2Gi        RWO            hong-ebs-sc    11s
  • 각 Deployment를 위한 PV, PVC를 확인하자. 모두 잘 Bound 되었다

  • 2 개의 EBS Volume이 추가적으로 생성되었다

  • 2 개의 Deployment에 pvc를 이용한 Volume과 Volume Mount를 정의하고, 배포하자

  • 각 Deployment 내부의 Pod에 대해 Volume이 잘 Mount 되었다
[honguser@ip-192-168-11-50 work]$ kubectl get deploy -n hongspace
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hong-deploy1   3/3     1            3           6h29m
hong-deploy2   3/3     1            3           6h25m
hong-deploy3   3/3     1            3           6h25m
  • 배포한 Deployment도 잘 작동한다

구축 구조

  • 위와 같은 구조이며, Provisiong & Mount 과정은 아래와 같다
  1. pvc가 배포
  2. 사용하는 StorageClass가 Provisioner인 AWS EBS-CSI Plugin에 요청
  3. 요구 사항에 맞는 EBS Volume 생성 및 PV 배포
  4. StorageClass Name과 요구 사양을 통해 PV와 Bound
    • volumeBindingMode가 WaitForFirstConsumer라면, pvc를 사용하는 Pod가 배포될 때까지 Provisioning과 Mount를 지연시킨다
  5. Pod 배포 시, 사용하는 pvc를 통해 Pod와 PV가 Mount

  • yaml 코드로 구조를 보면 위와 같다

EBS CSI 드라이버를 이용한 동적 프로비저닝이 완료됬다!!!

profile
멋진 엔지니어가 될 때까지

0개의 댓글