Creating an Amazon EFS for EKS by using the AWS CLI

Procedure

  1. Create an Amazon EFS file system for Amazon EKS.
    1. Run the following commands.
      export region="us-east-2" # replace with region where you have created your cluster
      export MyEfsSecurityGroup="reza-efs-sec" # replace with your unique Sec ID
      export MyEFSName="reza-gi" # replace with your unique EFS file name
      export cluster_name="gi-eks"  # replace with your EKS cluster name
      echo Get the VPC ID from the EKS cluster
      vpc_id=$(aws eks describe-cluster \
          --name ${cluster_name} \
          --region ${region} \ --query "cluster.resourcesVpcConfig.vpcId" \
          --output text)
      
      echo Create EFS and get FileSystemId
      file_system_id=$(aws efs create-file-system \
          --region ${region} \
          --performance-mode generalPurpose \
          --encrypted \
          --query 'FileSystemId' \
          --output text)
      
      echo Tag the EFS
      aws efs create-tags \
          --file-system-id ${file_system_id} \
          --tags Key=Name,Value=${MyEFSName}
      
      echo Create Security Group and get SecurityGroupId
      security_group_id=$(aws ec2 create-security-group \
          --group-name --region ${region} \ ${MyEfsSecurityGroup} \
          --description "My EFS security group" \
          --vpc-id ${vpc_id} \
          --output text)
      
      echo Retrieve VPC CIDR range and authorize inbound traffic for NFS
      cidr_range=$(aws ec2 describe-vpcs \
          --region ${region} \--vpc-ids ${vpc_id} \
          --query "Vpcs[].CidrBlock" \
          --output text \
          --region ${region})
      
      aws ec2 authorize-security-group-ingress \
          --group-id ${security_group_id} \
          --protocol tcp \
          --port 2049 \
          --cidr ${cidr_range}
      
      echo Get Subnet IDs as an array
      subnet_ids=($(aws ec2 describe-subnets \
          --filters "Name=vpc-id,Values=${vpc_id}" \
          --query "Subnets[*].SubnetId" \
          --output text))
      
      echo Create Mount Targets in each Subnet
      for subnet_id in "${subnet_ids[@]}"; do
          echo "Creating mount target for subnet: ${subnet_id}"
          aws efs create-mount-target \
              --file-system-id ${file_system_id} \
              --subnet-id ${subnet_id} \
              --security-groups ${security_group_id}
      done
    2. Obtain the CIDR range.
      echo $cidr_range
      Example output:
      172.31.0.0/16
    3. To confirm that the security group is created properly, run the following command.
      aws ec2 describe-security-groups --group-ids $security_group_id
      Make sure that the output has a rule that allows inbound traffic on TCP port 2049 from the CIDR range.
      Example output:
      {
          "SecurityGroups": [
              {
                  "Description": "My EFS security group",
                  "GroupName": "reza-efs-sec",
                  "IpPermissions": [
                      {
                          "FromPort": 2049,
                          "IpProtocol": "tcp",
                          "IpRanges": [
                              {
                                  "CidrIp": "172.31.0.0/16"
                              }
                          ],
                          "Ipv6Ranges": [],
                          "PrefixListIds": [],
                          "ToPort": 2049,
                          "UserIdGroupPairs": []
                      }
                  ],
                  "OwnerId": "346824953529",
                  "GroupId": "sg-0c81d71a21cafe4a0",
                  "IpPermissionsEgress": [
                      {
                          "IpProtocol": "-1",
                          "IpRanges": [
                              {
                                  "CidrIp": "0.0.0.0/0"
                              }
                          ],
                          "Ipv6Ranges": [],
                          "PrefixListIds": [],
                          "UserIdGroupPairs": []
                      }
                  ],
                  "VpcId": "vpc-d5b906bc"
              }
          ]
      }
    4. To confirm that your EFS file system is created properly, run the following command.
      aws efs describe-mount-targets --file-system-id $file_system_id
      Example output:
      {
          "MountTargets": [
              {
                  "OwnerId": "346824953529",
                  "MountTargetId": "fsmt-0e7e6ee43c669f6e1",
                  "FileSystemId": "fs-012a37bbc7928d7ba",
                  "SubnetId": "subnet-6594180c",
                  "LifeCycleState": "available",
                  "IpAddress": "172.31.6.128",
                  "NetworkInterfaceId": "eni-0a51adc94b02c0dee",
                  "AvailabilityZoneId": "use2-az1",
                  "AvailabilityZoneName": "us-east-2a",
                  "VpcId": "vpc-d5b906bc"
              },
              {
                  "OwnerId": "346824953529",
                  "MountTargetId": "fsmt-05009ad9515353deb",
                  "FileSystemId": "fs-012a37bbc7928d7ba",
                  "SubnetId": "subnet-a35cb3ee",
                  "LifeCycleState": "available",
                  "IpAddress": "172.31.43.92",
                  "NetworkInterfaceId": "eni-060c7c7159a117e30",
                  "AvailabilityZoneId": "use2-az3",
                  "AvailabilityZoneName": "us-east-2c",
                  "VpcId": "vpc-d5b906bc"
              },
              {
                  "OwnerId": "346824953529",
                  "MountTargetId": "fsmt-03be45814ee8000f8",
                  "FileSystemId": "fs-012a37bbc7928d7ba",
                  "SubnetId": "subnet-8d9c4af6",
                  "LifeCycleState": "available",
                  "IpAddress": "172.31.29.225",
                  "NetworkInterfaceId": "eni-042ce861bc48313c2",
                  "AvailabilityZoneId": "use2-az2",
                  "AvailabilityZoneName": "us-east-2b",
                  "VpcId": "vpc-d5b906bc"
              }
          ]
      }
  2. Create and confirm your storage classes.
    1. Export the region and MyEFSName variables.
    2. Confirm that you have the file system ID for your EFS file system.
      file_system_id=$(aws efs describe-file-systems --region ${region} | jq -r --arg name "${MyEFSName}" '.FileSystems[] | select(.Name==$name) | .FileSystemId')
      echo ${file_system_id}
    3. Apply the StorageClass:

      Create a file named efs.yaml and update these parameters:

      • Change the storage_class_name to efs-sc.
      • Replace the fileSsystemId parameter with the output of echo ${file_system_id}.
      Apply the YAML file:
      oc apply -f efs.yaml

      Sample EFS storage class manifest:

      apiVersion: storage.k8s.io/v1
      kind: StorageClass
      metadata:
        name: ${storage_class_name}
      parameters:
        directoryPerms: "777"
        fileSystemId: ${file_system_id}
        gid: "0"
        provisioningMode: efs-ap
        uid: "0"
      provisioner: efs.csi.aws.com
      reclaimPolicy: Delete
      volumeBindingMode: Immediate
      
      oc get sc
      NAME              PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
      efs-sc            efs.csi.aws.com         Delete          Immediate              false                  123m
      gp2 (default)     kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  39h
      Note: By default, you might have a gp2 storage class on your EKS cluster - however, it is recommended that you use gp3 for improved performance and deployment. For more information, see Migrating Amazon EKS clusters from gp2 to gp3 EBS volumes.

      If you keep the gp2 storage cluster and the default value is not in front of it, patch it with this command:

      kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
      In addition, ensure that these parameters (777 permission) are included in the EFS claim storage class:
      Parameters: directoryPerms=777,fileSystemId=fs-005891f4dab28cd06,gid=0,provisioningMode=efs-ap,uid=0

      For example:

      oc describe sc efs-sc 
      Provisioner:           efs.csi.aws.com 
      Parameters: 
      directoryPerms=777,fileSystemId=fs-088163fcae75a1740,gid=0,provisioningMode=efs-ap,uid=0 
      AllowVolumeExpansion:  <unset> 
      MountOptions:          <none> 
      ReclaimPolicy:         Delete 
      VolumeBindingMode:     Immediate 
      Events:                <none>