DevOps/Kubernetes

[EKS] AWS EBS 볼륨을 K8S PV로 사용

Jen'_' 2021. 12. 22. 17:41
반응형

Pod 간 공유 가능한 스토리지를 만들어야 했습니다.

그러던 중 PV, PVC 라는 k8s 개념이 있어서 공부한 것을 정리해 보겠습니다.

물리 스토리지를 쿠버네티스 클러스터에 표현한 것이 PV이고, Pod의 볼륨과 PV를 연결하는 관계가 PVC 입니다.

 

EKS 1.23버전 이후부터는 AWS EBS CSI Driver(https://github.com/kubernetes-sigs/aws-ebs-csi-driver)를 설치 하지 않으면 EBS를 PV로 사용할 수 없습니다.

참고: https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/kubernetes-versions.html#kubernetes-1.23

 

Provisioning

PV를 프로비저닝 할 수 있는 방법에는 정적(static) 프로비저닝동적(dynamic) 프로비저닝이 있습니다. 

1. Static Provisioning

정적 프로비저닝은 관리자가 수동으로 물리 디스크를 생성한 후 PV를 생성하고 PVC에 바인딩 한 후에, Pod에서 사용할 수 있습니다.

미리 준비된 스토리지가 있다면 PV를 수동으로 생성하는 정적 프로비저닝을 사용하면 되지만 클라우드를 사용하고 있다면 미리 준비하지 않고 필요시에 스토리지를 생성하면 되기 때문에 동적 프로비저닝을 사용합니다. 

출처: https://bcho.tistory.com/1259

 

2. Dynamic Provisioning

동적 프로비저닝을 사용하면 관리자가 사전에 물리 디스크와 PV를 수동으로 생성할 필요가 없이 PVC만 정의하면 이에 맞는 물리 디스트 생성 및 PV 생성을 자동화합니다. PVC는 StorageClass를 요청해야 하며 관리자는 동적 프로비저닝이 발생하도록 해당 클래스를 생성하고 구성해야 합니다.

출처: https://bcho.tistory.com/1259

 


1. Static Provisioning

외부에서 생성한 물리적 볼륨을 k8s 내에서 사용하기 위해 PV와 연결합니다.

실행 순서는 1. AWS EBS 생성 2. pv.yaml 생성 3. pvc.yaml 생성 4. pod에 정의 입니다. 

 

PV용 AWS EBS 프로비저닝

- EBS 볼륨은 PV를 연결하려는 pod가 생성되는 node와 동일한 리전 및 가용성 영역에 있어야 합니다.

$ aws ec2 create-volume --region ap-northeast-2 --availability-zone ap-northeast-2a --size 5 --volume-type gp2

 

node에 label 부여

- pod가 생성될 node를 지정하기 위함

$ kubectl label nodes <ap-northeast-2a에 생성된 노드 이름> <레이블 키>=<레이블 값>

ex) kubectl label nodes ip-192-168-11-22.ap-northeast-2.compute.internal az=a

 

PersistentVolume (PV)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-1
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  capacity:
    storage: 5Gi
  csi:
    driver: ebs.csi.aws.com
    fsType: ext4
    volumeHandle: vol-xxxxxxxxxxxxx
  persistentVolumeReclaimPolicy: Retain
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: topology.ebs.csi.aws.com/zone
              operator: In
              values:
                - ap-northeast-2a
cs

 

 csi 

  • driver: 드라이버 이름 지정
  • volumeHandle: Disk 볼륨 ID
  • readOnly: 볼륨을 읽기 전용으로 "ControllerPublished" (연결)할지 여부를 나타내는 선택적인 불리언(boolean) 값. 기본적으로 false 이다. 
  • fsType: 만약 PV의 VolumeMode  Filesystem 인 경우에 이 필드는 볼륨을 마운트하는 데 사용해야 하는 파일시스템을 지정하는 데 사용될 수 있다. 

https://kubernetes.io/ko/docs/concepts/storage/volumes/#csi

 

 

 

PersistentVolumeClaim (PVC)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: wordpress
  name: pvc-1
spec:
  storageClassName: "" # Empty string must be explicitly set otherwise default StorageClass will be set
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  volumeMode: Filesystem
  volumeName: pv-1
cs

 

 AccessMode 

PV에 대한 동시에 Pod에서 접근할 수 있는 정책을 정의합니다. (AWS EBS는 ReadWriteOnce 만 가능)

  • ReadWriteOnce: 하나의 노드에서 해당 볼륨이 읽기-쓰기로 마운트 될 수 있다. ReadWriteOnce 접근 모드에서도 파트가 동일 노드에서 구동되는 경우에는 복수의 파드에서 볼륨에 접근할 수 있다. 
  • ReadWriteMany: 볼륨이 다수의 노드에서 읽기 전용으로 마운트 될 수 있다.
  • ReadWriteOncePod: 볼륨이 단일 파드에서 읽기-쓰기로 마운트 될 수 있다. 전체 클러스터에서 단 하나의 파드만 해당 PVC를 읽거나 쓸 수 있어야 하는 경우 ReadWriteOncePod 접근 모드를 사용한다. 이 기능은 CSI 볼륨과 쿠버네티스 버전 1.22+ 에서만 지원된다.

https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/#%EC%A0%91%EA%B7%BC-%EB%AA%A8%EB%93%9C

 

 

Wordpress 배포

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
        - image: wordpress:5.5.3-apache
          name: wordpress
          env:
            - name: WORDPRESS_DB_HOST
              value: wordpress-mysql
            - name: WORDPRESS_DB_PASSWORD
              value: password
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
          - name: ebs-volume
            mountPath: /data
      volumes:
      - name: ebs-volume
        persistentVolumeClaim:
          claimName: pvc-1  
     nodeSelector:  
        az: a                  
 
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30000
  selector:
    app: wordpress
    tier: frontend
cs

 

워드프레스에 PVC를 붙여 배포해보겠습니다.

 

 

server ip:30000

워드프레스 기본 이미지가 잘 나옵니다.

 

 

해당 파드에 들어가 EBS 볼륨이 붙었는지 확인해보겠습니다.

$ kubectl exec -it <pod name> -- bash

/data 경로에 마운트가 된 것을 확인할 수 있습니다. 

 

 

2. Dynamic Provisioning

동적 프로비저닝을 사용하면 관리자가 사전에 물리 디스크와 PV를 수동으로 생성할 필요가 없이 PVC만 정의하면 이에 맞는 물리 디스트 생성 및 PV 생성을 자동화합니다. PVC는 StorageClass를 요청해야 하며 관리자는 동적 프로비저닝이 발생하도록 해당 클래스를 생성하고 구성해야 합니다.

 

StorageClass

- PVC에서 EBS 볼륨 및 관련 PV를 자동으로 생성합니다. 볼륨 생성에 대한 세분화된 제어를 위해 StorageClass를 통해 매개변수를 전달할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
parameters:
  csi.storage.k8s.io/fstype: ext4
  type: gp3
allowedTopologies:
- matchLabelExpressions:
  - key: topology.ebs.csi.aws.com/zone
    values:
    - ap-northeast-2a
    - ap-northeast-2b
    - ap-northeast-2c
    - ap-northeast-2d
cs

 

provisioner로 aws ebs csi driver를 지정합니다.

https://github.com/kubernetes-sigs/aws-ebs-csi-driver

 

 

 volumeBindingMode 

  • Immediate(디폴트): PVC가 생성되면 볼륨 바인딩과 동적 프로비저닝이 즉시 발생하는 것을 나타낸다. 
  • WaitForFirstConsumer: PVC를 사용하는 파드가 생성될 때까지 PV의 바인딩과 프로비저닝을 지연시킨다.(사용 가능한 프로바이저가 따로 있음)

https://kubernetes.io/ko/docs/concepts/storage/storage-classes/#%EB%B3%BC%EB%A5%A8-%EB%B0%94%EC%9D%B8%EB%94%A9-%EB%AA%A8%EB%93%9C

 

 

 Reclaim Policy  

PV는 연결된 PVC가 삭제된 후 다시 다른 PVC에 의해서 재사용이 가능한데, 재사용 시에 디스크의 내용을 지울지 유지할지에 대한 정책을 Reclaim Policy를 이용하여 설정이 가능합니다. (디스크의 특성에 따라 적용 가능한 Policy가 다릅니다)

  • Retain: 삭제하지 않고 PV의 내용을 유지합니다. 삭제할 때는 수동으로 삭제해야 합니다.
  • Recycle: 기본 볼륨 플러그인에서 지원하는 경우 Recycle 반환 정책은 볼륨에서 기본 스크럽(rm -rf /thevolume/*)을 수행하고 새 클레임에 다시 사용할 수 있도록 합니다.
  • Delete: 볼륨의 사용이 끝나면, 해당 볼륨은 삭제됩니다. AWS EBS, GCE PD, Azure Disk 등이 이에 해당합니다.

https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/#%EB%B0%98%ED%99%98-reclaiming

 

 

PersistentVolumeClaim (PVC)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: nginx
  name: pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: ebs-sc
 
cs

storageClassName을 지정해 줍니다.

 

volumeBindingMode를 WaitForFirstConsumer으로 사용했기 때문에 바로 PV가 생기지 않고 Pod에서 요청하면 생깁니다.

 

Nginx 배포

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: ebs-volume
          mountPath: /data
      volumes:
      - name: ebs-volume
        persistentVolumeClaim:
          claimName: pvc    
      nodeSelector:
        az: a              
cs

 

PVC의 상태가 Bound가 되었고 PV가 생성된 것을 확인할 수 있습니다.

Pod->PVC->SC->EBS 생성 및 PV생성!

 


주의 사항

AWS EBS는 특정 가용영역에 생성되어 EC2에 붙는 스토리지로서 AccessMode가 ReadWriteOnce입니다.

그러므로 동일한 노드에 배포된 Pod끼리만 공유가 가능합니다.

서로 다른 노드에 배포된 Pod에서 동일한 스토리지를 공유하고 싶다면 EFS를 사용합니다.

+ EFS는 EBS보다 가격도 비싸고 IO도 느립니다..

+ EFS를 사용하려면 동적 프로비저닝이아닌 정적 프로비저닝 방식으로 PVC를 붙여야합니다.

 

 

참고

https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/

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

https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/examples/kubernetes

 

 

반응형