본문으로 바로가기

Kubernetes PVC를 Amazon EFS로 구성하기

category IT/DevOps 2021. 9. 13. 11:30
반응형

Intro

PVC를 EFS로 구성해보도록 하겠습니다.

사용한 도구(Tool)

  • AWS cli
  • kubectl
  • helm 3

AWS EFS 생성

아래 옵션에 들어가는 값은 커스텀 하게 변경하여 사용해야합니다.

AWS VPC ID 확인

해당 ID는 아래 security group 생성에 사용됩니다.

aws ec2 describe-vpcs

AWS security group 생성

AWS EFS생성시 사용할 security group을 생성합니다.
<EFS_SECURITY_GROUP_NAME> : security group name
<VPC_ID> : 위에서 확인한 vpc id

aws ec2 create-security-group \
--region ap-northeast-2 \
--group-name <EFS_SECURITY_GROUP_NAME> \
--description "Amazon EFS for EKS, SG for mount target" \
--vpc-id <VPC_ID>

security group에 inbound rules 적용

<EFS_SECURITY_GROUP_ID> : 위에서 생성한 securitygroup id
<MY_VPC_CIDR> : 내 전체 VPC CIDR대역

aws ec2 authorize-security-group-ingress \
--group-id <EFS_SECURITY_GROUP_ID> \
--region ap-northeast-2 \
--protocol tcp \
--port 2049 \
--cidr <MY_VPC_CIDR>

create EFS file system

aws efs create-file-system \
--creation-token creation-token \
--performance-mode generalPurpose \
--throughput-mode bursting \
--region ap-northeast-2 \
--tags Key=Name,Value=MyEFSFileSystem \
--encrypted

create mount point target

<FILE_SYSTEM_ID> : 위에서 생성한 file system id
<SECURITY_GROUP_ID> : 위에서 생성한 security group id
<SUBNET_ID_ZONE1> : EFS mounpoint할 subnet id (이중화를 고려하여 zone1, zone2를 각각 다른 az로 설정)
<SUBNET_ID_ZONE2>: EFS mounpoint할 subnet id (이중화를 고려하여 zone1, zone2를 각각 다른 az로 설정)

aws efs create-mount-target \
--file-system-id <FILE_SYSTEM_ID> \
--subnet-id <SUBNET_ID_ZONE1> \
--security-group <SECURITY_GROUP_ID> \
--region ap-northeast-2
aws efs create-mount-target \
--file-system-id <FILE_SYSTEM_ID> \
--subnet-id <SUBNET_ID_ZONE2> \
--security-group <SECURITY_GROUP_ID> \
--region ap-northeast-2

EFS provisioner 생성

EFS provisioner는 kubernetes에서 외부 EFS를 사용할 수 있도록 해주는 프로그램입니다.
helm으로 설치하는 방법과(방법1) manifest를 직접 설정하여 설치하는 방법(방법2)이 있습니다.

방법 1. helm으로 설치

helm install -f ./values.yaml efs-provisioner stable/efs-provisioner

provisioner Helm - values.yaml

아래 nodeselector는 필요시 지정합니다.

nodeSelector:
  nodegroup-type: MANAGE

efsProvisioner:
  efsFileSystemId: fs-f6933c96
  awsRegion: ap-northeast-2
  provisionerName: aws-efs
  storageClass:
    reclaimPolicy: Retain

방법2. menifest파일로 설치

namespace 는 커스터마이징 필요

provisioner - service_account.yaml

# service_account.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: default
  name: efs-provisioner

provisioner - rbac.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: efs-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-efs-provisioner
subjects:
  - kind: ServiceAccount
    name: efs-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: efs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-efs-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-efs-provisioner
subjects:
  - kind: ServiceAccount
    name: efs-provisioner
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-efs-provisioner
  apiGroup: rbac.authorization.k8s.io

provisioner - deployment.yaml

  • FILE_SYSTEM_ID: EFS 파일 시스템 ID를 지정합니다. 예: fs-xxxxxxxx
  • AWS_REGION: AWS 리전을 지정합니다. 서울이면 ap-northeast-2를 지정합니다.
  • PROVISIONER_NAME: 프로비저너 이름으로 사용할 임의의 값입니다.
  • EFS_SERVER_URL : .efs.ap-northeast-2.amazonaws.com
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: default
  name: efs-provisioner
spec:
  selector:
    matchLabels:
      app: efs-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: efs-provisioner
    spec:
      serviceAccount: efs-provisioner
      containers:
        - name: efs-provisioner
          image: quay.io/external_storage/efs-provisioner:v2.4.0
          env:
            - name: FILE_SYSTEM_ID
              value: "<FILE_SYSTEM_ID>"
            - name: AWS_REGION
              value: "<AWS_REGION>"
            - name: PROVISIONER_NAME
              value: "<PROVISIONER_NAME>"
          volumeMounts:
            - name: pvcs
              mountPath: /pvcs
      volumes:
        - name: pvcs
          nfs:
            server: "<EFS_SERVER_URL>"
            path: /
  • storageclass.yaml
  • PROVISIONER_NAME: deployment에서 설정한 name
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  namespace: default
  name: efs-provisioner
provisioner: "<PROVISIONER_NAME>"

Kubernetes PVC생성

PVC_NAME : PVC이름을 명시합니다.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: <PVC_NAME>
  annotations:
    volume.beta.kubernetes.io/storage-class: "efs-provisioner"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

Deployment에 PVC mount 예시

<VOLUME_NAME> : 적당한 customizing
<PVC_NAME> : 위에서 생성한 PVC이름

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
        volumeMounts:
          - name: <VOLUME_NAME>
            mountPath: "/usr/share/nginx/html"
      volumes:
        - name: <VOLUME_NAME>
          persistentVolumeClaim:
            claimName: <PVC_NAME>
반응형