Amazon EKS — EFS CSI Driver

2 minute read

Amazon EFS provides shared file storage that multiple pods can read and write simultaneously (ReadWriteMany). This is critical for workloads that need shared data — content management, ML training data, and shared configuration.


Installation

Step 1 — Create an IAM Role

eksctl create iamserviceaccount \
  --cluster my-cluster \
  --namespace kube-system \
  --name efs-csi-controller-sa \
  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy \
  --approve \
  --role-name AmazonEKS_EFS_CSI_DriverRole

Step 2 — Install as EKS Add-on

aws eks create-addon \
  --cluster-name my-cluster \
  --addon-name aws-efs-csi-driver \
  --service-account-role-arn arn:aws:iam::123456789:role/AmazonEKS_EFS_CSI_DriverRole

Verify

kubectl get pods -n kube-system -l app=efs-csi-controller

Create an EFS File System

# Get the VPC ID
VPC_ID=$(aws eks describe-cluster --name my-cluster --query "cluster.resourcesVpcConfig.vpcId" --output text)

# Create EFS
EFS_ID=$(aws efs create-file-system \
  --performance-mode generalPurpose \
  --throughput-mode elastic \
  --encrypted \
  --tags Key=Name,Value=eks-efs \
  --query "FileSystemId" --output text)

echo "EFS ID: $EFS_ID"

Create Mount Targets

Create a mount target in each subnet where your nodes run:

# Create a security group for EFS
EFS_SG=$(aws ec2 create-security-group \
  --group-name eks-efs-sg \
  --description "EFS mount target SG" \
  --vpc-id $VPC_ID \
  --query "GroupId" --output text)

# Allow NFS from the cluster security group
CLUSTER_SG=$(aws eks describe-cluster --name my-cluster \
  --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" --output text)

aws ec2 authorize-security-group-ingress \
  --group-id $EFS_SG \
  --protocol tcp --port 2049 \
  --source-group $CLUSTER_SG

# Create mount targets in private subnets
for SUBNET in subnet-aaa subnet-bbb subnet-ccc; do
  aws efs create-mount-target \
    --file-system-id $EFS_ID \
    --subnet-id $SUBNET \
    --security-groups $EFS_SG
done

EFS StorageClass

Static Provisioning

Create a PV pointing to an existing EFS file system:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
spec:
  capacity:
    storage: 100Gi   # EFS is elastic — this is informational only
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-0123456789abcdef0
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: ""
  resources:
    requests:
      storage: 100Gi
  volumeName: efs-pv

Dynamic Provisioning with Access Points

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap           # Creates EFS access points
  fileSystemId: fs-0123456789abcdef0
  directoryPerms: "700"
  gidRangeStart: "1000"
  gidRangeEnd: "2000"
  basePath: "/dynamic_provisioning"
mountOptions:
  - tls

Each PVC creates a unique EFS access point with its own directory:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-data
  namespace: production
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 50Gi    # Informational — EFS is elastic

Performance Modes

Mode Latency Throughput Use Case
General Purpose Low (sub-ms) Up to 10 GiB/s Web serving, CMS, home dirs
Max I/O Higher Higher aggregate Big data, media processing
Elastic (throughput) Low Auto-scales Variable workloads
Provisioned (throughput) Low Guaranteed Consistent throughput needs

EFS vs EBS Comparison

Feature EBS EFS
Access mode ReadWriteOnce ReadWriteMany
AZ scope Single AZ Multi-AZ
Protocol Block device NFS v4.1
Capacity Fixed (must resize) Elastic (auto-grows)
IOPS Up to 256K (io2) Depends on mode
Price $0.08/GB-month (gp3) $0.30/GB-month
Fargate support No Yes
Snapshots Native EBS snapshots AWS Backup

Best Practices

  1. Use elastic throughput mode — auto-scales with demand, no capacity planning
  2. Enable encryption in transit — add tls to mountOptions
  3. Use access points for multi-tenant isolation — each PVC gets its own root directory
  4. Configure security groups carefully — NFS port 2049 must be open from node/pod security groups
  5. EFS for Fargate — EFS is the only persistent storage option for Fargate pods
  6. Monitor costs — EFS is ~4x more expensive per GB than EBS; use only when you need ReadWriteMany

Updated: