Amazon EKS — EFS CSI Driver
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
- Use
elasticthroughput mode — auto-scales with demand, no capacity planning - Enable encryption in transit — add
tlsto mountOptions - Use access points for multi-tenant isolation — each PVC gets its own root directory
- Configure security groups carefully — NFS port 2049 must be open from node/pod security groups
- EFS for Fargate — EFS is the only persistent storage option for Fargate pods
- Monitor costs — EFS is ~4x more expensive per GB than EBS; use only when you need ReadWriteMany