DEV Community

sagark4578
sagark4578

Posted on

How to Set Up AWS EFS with Persistent Volumes & PVCs Using Terraform

Introduction
When deploying applications on AWS, managing persistent storage is crucial for stateful workloads. Amazon Elastic File System (EFS) provides scalable, shared file storage that integrates seamlessly with AWS services like Lambda, Kubernetes (EKS), and EC2.

In this guide, we’ll use Terraform to:

  • Create an AWS EFS file system

  • Configure security groups for secure access

  • Set up EFS mount targets for private subnets

  • Define access points for applications

  • Integrate with Kubernetes Persistent Volumes (PV) and Persistent Volume Claims (PVC)

  • Output essential EFS parameters for further integrations

  • By the end of this tutorial, you'll have a fully functional EFS setup, ready to be used in a Kubernetes cluster or other AWS environments.

Step 1: Create an AWS Security Group for EFS
The security group defines access rules for EFS connections from private subnets.

resource "aws_security_group" "efs_sg" {
  name   = "efs-app-${var.environment}-sg"
  vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id

  ingress {
    description = "Allow access from Lambda & VPC subnets"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = concat(
      data.terraform_remote_state.vpc.outputs.private_subnets_cidr,
      data.terraform_remote_state.vpc.outputs.db_subnets_cidr
    )
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
Enter fullscreen mode Exit fullscreen mode

✅ Why?

  • Ensures secure access to EFS from private subnets.

  • Outbound connections are unrestricted for seamless communication.

Step 2: Create AWS EFS File System
This block provisions an encrypted EFS instance with lifecycle policies to optimize costs.

resource "aws_efs_file_system" "aws_efs_file_system" {
  creation_token = "${var.environment}-efs-app"
  encrypted      = true

  lifecycle_policy {
    transition_to_ia = "AFTER_14_DAYS"
  }

  lifecycle_policy {
    transition_to_primary_storage_class = "AFTER_1_ACCESS"
  }

  tags = {
    Name = "${var.environment}-efs-app"
  }
}
Enter fullscreen mode Exit fullscreen mode

✅ Why?

  • Uses lifecycle policies to reduce storage costs.
  • Encryption enabled for data security.

Step 3: Create EFS Mount Targets
Mount targets enable EC2 instances, Kubernetes pods, and Lambda functions to access EFS.

resource "aws_efs_mount_target" "efs_mt" {
  count           = length(data.terraform_remote_state.vpc.outputs.db_subnets)
  file_system_id  = aws_efs_file_system.aws_efs_file_system.id
  subnet_id       = data.terraform_remote_state.vpc.outputs.db_subnets[count.index]
  security_groups = [aws_security_group.efs_sg.id]
}
Enter fullscreen mode Exit fullscreen mode

✅ Why?

  • Creates mount targets in each private subnet.
  • Ensures secure communication via the security group.

Step 4: Create an EFS Access Point
Access points define specific access rules for applications using EFS.

resource "aws_efs_access_point" "aws_efs_access_point" {
  file_system_id = aws_efs_file_system.aws_efs_file_system.id
  posix_user {
    gid = 1000
    uid = 1000
  }
  root_directory {
    path = "/app"
    creation_info {
      owner_gid   = 1000
      owner_uid   = 1000
      permissions = "777"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

✅ Why?

  • Defines POSIX permissions for secure file access.
  • Ensures controlled multi-user access to the file system.

Step 5: Kubernetes Integration with PV & PVC
To use EFS as a Persistent Volume (PV) in Kubernetes, define a PersistentVolume (PV) and a PersistentVolumeClaim (PVC) using the kubectl_manifest resource.

Persistent Volume (PV)
Create a file (for example, pv-pvc.tf) with the following code:

resource "kubectl_manifest" "persistent_volume" {
  yaml_body = <<YAML
apiVersion: v1
kind: PersistentVolume
metadata:
  name: var.name
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Gi
  csi:
    driver: efs.csi.aws.com
    volumeHandle: ${data.terraform_remote_state.efs.outputs.efs_id}::${data.terraform_remote_state.efs.outputs.efs_access_point_id}
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  volumeMode: Filesystem
YAML
}
Enter fullscreen mode Exit fullscreen mode

Persistent Volume Claim (PVC)

resource "kubectl_manifest" "persistent_volume_claims" {
  depends_on = [kubectl_manifest.persistent_volume]
  yaml_body  = <<YAML
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: var.name-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 10Gi
YAML
}
Enter fullscreen mode Exit fullscreen mode

output.tf

output "efs_dns_name" {
  value = aws_efs_file_system.aws_efs_file_system.dns_name
}

output "efs_id" {
  value = aws_efs_file_system.aws_efs_file_system.id
}

output "efs_access_point_id" {
  value = aws_efs_access_point.aws_efs_access_point.id
}

output "efs_id_app2" {
  value = aws_efs_file_system.aws_efs_file_system_app2.id
}

output "efs_access_point_app2_id" {
  value = aws_efs_access_point.aws_efs_access_point_app2.id
}
Enter fullscreen mode Exit fullscreen mode

✅ Why?

  • The output blocks expose essential EFS parameters, which can be referenced by other Terraform modules or Kubernetes manifests.
  • The Persistent Volume (PV) uses the AWS EFS CSI driver to connect to your EFS file system.
  • The Persistent Volume Claim (PVC) lets Kubernetes applications request storage dynamically.

Conclusion
With this complete setup, you now have a scalable, secure, and high-availability persistent storage solution using AWS EFS and Terraform. This guide not only provisions the necessary AWS infrastructure but also integrates with Kubernetes to manage persistent storage using PVs and PVCs.

Next Steps
Experiment with dynamic scaling by integrating AWS Auto Scaling or EFS Intelligent-Tiering.
Continue exploring Terraform modules to further streamline your infrastructure as code.
📌 Have questions or suggestions? Drop a comment below! 🚀

Image of Quadratic

Free AI chart generator

Upload data, describe your vision, and get Python-powered, AI-generated charts instantly.

Try Quadratic free

Top comments (0)

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please consider leaving a ❤️ or a kind comment on this post if it was useful to you!

Thanks!