Before introducing how to use AWS EFS for Kubernetes, let me recap some terms of Persistent Volumes.
- PV (Persistent Volume): PV is a piece of storage, it can be NFS, iSCSI, EBS, EFS… The purpose of having PV is to decouple the storage from pod’s lifecycle.
- PVC (Persistent Volume Claim): PVC provides the method for pods to use PV, it includes the request storage size and access mode. If the PV supports ReadWriteMany access mode, then its PVC can be used by multiple pods.
- Storage Class: This is the abstract layer of PV which hides the implementation of PV from end users.
With the above 3 points in your mind, lets have a look the architecture.

Basically, there are four steps:
-
- Create EFS (only the first time): It includes the tasks: create the EFS in the right subnets, setup the security groups to allow Kubernetes nodes to access and enable DNS support/resolution in your VPC.
- Create StorageClass for EFS via efs-provisioner (only the first time). efs-provisioner runs as a container which plays the role of EFS broker. It allows other pods to mount EFS as the persistent volumes. Just be aware of that EFS is built on top of NFS4, so you need to have nfs-common packages installed in your Kubernetes nodes
- Create a PVC to use the StorageClass for EFS. Just note that EFS has unlimited storage, so the storage size request actually does not take any effects here. But you still have to keep it to pass the syntax check.
- Create a volume for the PVC, then mount the volume inside the pod.
Here is how the PVC and PV look. And I also attached the sample code as below.
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: aws-efs
provisioner: example.com/aws-efs
---
apiVersion: v1
kind: ConfigMap
metadata:
name: wordpress
data:
database: wordpress-db
password: ************
---
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: efs-wordpress
annotations:
volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
replicas: 2
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
spec:
containers:
- image: wordpress:latest
name: wordpress
env:
- name: WORDPRESS_DB_HOST
valueFrom:
configMapKeyRef:
name: wordpress
key: database
- name: WORDPRESS_DB_PASSWORD
valueFrom:
configMapKeyRef:
name: wordpress
key: password
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-pv
mountPath: /var/www/html
volumes:
- name: wordpress-pv
persistentVolumeClaim:
claimName: efs-wordpress
---

Great article – simple and clear. Thank you!