Provisioning Amazon EFS with Terraform: Architecture, Modules, and EKS Integration

Amazon Elastic File System provides scalable file storage for use with Amazon EC2 instances. Deploying it with Terraform Infrastructure as Code gives repeatable, versioned control over file system creation, mount targets, security, lifecycle policies, and integration with container workloads. This guide covers a detailed Terraform implementation for EFS, from core resource definitions to module reuse and EKS integration patterns.

Overview of Amazon EFS and Terraform

Amazon Elastic File System is a network-attached NFS file system that scales elastically with demand. It is ideal for shared storage across multiple EC2 instances, container workloads on ECS and EKS, and lift-and-shift legacy applications that require a scalable, network-attached storage across multiple Availability Zones.

Using Terraform to provision EFS allows a single definition to create the file system, mount targets in each specified subnet, security groups for access control, and optional features such as encryption, backup policies, lifecycle transition to Infrequent Access, and access points. The approach is compatible with Terraform 1.0+ and AWS provider 5.x, and it requires existing VPC subnets and security groups.

Project Structure and Prerequisites

A typical EFS Terraform project is organized for clarity and reuse.

aws-efs-terraform/ ├── main.tf ├── variables.tf ├── outputs.tf └── terraform.tfvars

Prerequisites for deployment include:

  • AWS CLI configured
  • Terraform installed
  • VPC and subnets already configured
  • Basic understanding of network file systems

These prerequisites ensure the network foundation for mount targets and security group rules is in place before Terraform applies the EFS resources.

Core Terraform Resources

The foundation of an EFS deployment is the file system resource with encryption and lifecycle policy.

```hcl
provider "aws" {
region = var.aws_region
}

resource "awsefsfilesystem" "main" {
creation
token = "${var.projectname}-efs"
encrypted = true
lifecycle
policy {
transitiontoia = "AFTER30DAYS"
}
tags = {
Name = "${var.project_name}-efs"
}
}
```

Creation token provides an idempotent reference when creating the Elastic File System. Encryption is enabled by default in modern designs, with optional KMS key ARN support in module variants. The lifecycle policy transitions data to IA after 30 days.

Mount targets connect the file system to subnets.

hcl resource "aws_efs_mount_target" "main" { count = length(var.subnet_ids) file_system_id = aws_efs_file_system.main.id subnet_id = var.subnet_ids[count.index] security_groups = [aws_security_group.efs.id] }

Mount targets are created in each specified subnet to enable multi-AZ architecture. The count pattern ensures one mount target per subnet ID.

Security Group and Mount Targets

Access to EFS occurs over NFS on TCP port 2049. A dedicated security group restricts inbound traffic.

hcl resource "aws_security_group" "efs" { name = "${var.project_name}-efs-sg" description = "Allow EFS inbound traffic" vpc_id = var.vpc_id ingress { description = "NFS from VPC" from_port = 2049 to_port = 2049 protocol = "tcp" security_groups = var.allowed_security_group_ids } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.project_name}-efs-sg" } }

The ingress rule allows NFS from VPC security groups. Egress is open. Modules can accept custom security groups for access control and can be configured with securitygroupingress maps that allow NFS inbound and optionally SSH.

Lifecycle Policies and Backup

Cost optimization and durability are handled via lifecycle and backup resources.

hcl resource "aws_efs_backup_policy" "policy" { file_system_id = aws_efs_file_system.main.id backup_policy { status = "ENABLED" } }

Backup policy status can be ENABLED or DISABLED. A module parameter backuppolicystatus defaults to DISABLED and accepts ENABLE or DISABLED.

Lifecycle policy for the EFS file system is expressed as:

hcl lifecycle_policy = [{ "transition_to_ia" = "AFTER_30_DAYS" }]

The transitiontoia setting moves infrequently accessed data to Infrequent Access storage class after the defined period.

Access points provide application-level isolation.

hcl resource "aws_efs_access_point" "test" { file_system_id = aws_efs_file_system.main.id }

In production EKS scenarios, dedicated access points are created per application, for example /data/podinfo, with Kubernetes StorageClass, PV, and PVC configured to use EFS.

Community Modules and Reusability

Terraform modules abstract EFS creation into reusable components. A module which creates AWS EFS elastic file system resources can be invoked as:

hcl module "efs" { source = "terraform-aws-modules/efs/aws" name = "example" creation_token = "example-token" encrypted = true kms_key_arn = "arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" }

Another module creates an Elastic File System along with mount targets and a security group that allows access to 2049 to any instance that has the security group attached.

hcl module "efs-0" { source = "AustinCloudGuru/efs/aws" vpc_id = "vpc-0156c7c6959ba5858" name = "dev-efs" subnet_ids = ["subnet-05b1a3ffd786709d5", "subnet-0a35212c972a2aaf05", "subnet-0d0e78f696428aa28"] security_group_ingress = { default = { description = "NFS Inbound" from_port = 2049 protocol = "tcp" to_port = 2049 self = true cidr_blocks = [] } } lifecycle_policy = [{ "transition_to_ia" = "AFTER_30_DAYS" }] tags = { Terraform = "true" Environment = "development" } }

Modules accept parameters such as encrypted, kmskeyid, lifecyclepolicy, name, backuppolicystatus, and securitygroup_ingress. Pinning module version is recommended for production stability.

Input Variables and Outputs

Standard module interfaces expose inputs and outputs for composition.

Input variables:

Name Type Description
region string AWS region to deploy the EFS filesystem
environment string Tag to specify the deployment environment e.g., dev, staging, prod
subnet_ids list List of subnet IDs where mount targets will be created
securitygroupids list List of security group IDs to attach to mount targets

Additional module inputs include:

Name Description Type Default Required
backuppolicystatus Enable/disable backup for EFS Filesystem. Value should be ENABLE/DISABLED. Defaults to DISABLED string "DISABLED" no
encrypted If true, the file system will be encrypted bool true no
kmskeyid If set, use a specific KMS key string null no
lifecycle_policy Lifecycle Policy for the EFS Filesystem list(object({ transitiontoia = string })) [] no
name A unique name used as reference when creating the Elastic File System to ensure idempotent file system creation string

Outputs for downstream modules:

Name Description
efs_id The ID of the created EFS filesystem
mounttargetids The list of EFS mount target IDs
efs_arn The ARN of the created EFS filesystem

Alternative outputs used in standalone configurations:

hcl output "efs_id" { value = aws_efs_file_system.main.id description = "EFS file system ID" } output "efs_dns_name" { value = aws_efs_file_system.main.dns_name description = "EFS DNS name for mounting" } output "access_point_ids" { value = { api = aws_efs_access_point.api.id worker = aws_efs_access_point.worker.id } description = "Access point IDs by service" }

Exporting these values allows other modules to consume the file system identifier, DNS name, and access point IDs.

Integrating EFS with EKS Using Terraform

Integrating EFS with Amazon EKS using Terraform involves provisioning the file system, enabling encryption at rest with AWS KMS, configuring IRSA for EFS driver permissions, and creating Kubernetes PV/PVC for workload persistence.

Requirements for deployment:

Requirement Description
EKS Cluster A running Amazon EKS cluster v1.28 or newer recommended
EFS CSI Driver Addon The aws-efs-csi-driver addon must be installed either via Terraform aws-ia/eks-blueprints-addons or manually using kubectl / Helm
OIDC Provider OIDC provider is enabled for the cluster required for IRSA

By the end of the integration, the result is a KMS-encrypted EFS file system accessible to the EKS cluster, dedicated access points per application, Kubernetes StorageClass, PV, and PVC configured to use EFS, and verified pod read/write access to the mounted EFS volume.

This pattern is ideal for persistent storage for container workloads on ECS and EKS, shared file storage between EC2 instances, and mountable multi-AZ NFS storage for enterprise workloads.

Production Considerations

A production EFS setup involves more than just the file system resource. Considerations include tagging resources by environment and name for clarity, supporting multi-AZ architecture via mount targets in each specified subnet, accepting custom security groups for access control, and enabling backup policy and lifecycle transition for cost and durability.

Deployment readiness is verified by compatibility with Terraform 1.0+ and AWS provider 5.x, with requirements for existing VPC subnets and security groups.

Conclusion

Terraform provides a comprehensive and repeatable path to provision Amazon EFS with encryption, multi-AZ mount targets, security groups, lifecycle policies, backup policies, and access points. Using core resources gives fine-grained control over creation token, encryption, and NFS ingress on port 2049. Community modules accelerate adoption with standardized inputs for name, encrypted, kmskeyarn, lifecyclepolicy, backuppolicystatus, subnetids, and securitygroupids, while exposing outputs such as efsid, mounttargetids, and efsarn.

For container workloads, the integration with EKS via the EFS CSI driver, KMS encryption at rest, IRSA, and per-application access points delivers persistent, shared storage that scales with demand. The combination of infrastructure as code discipline and EFS elasticity makes Terraform the preferred method to build production-grade file storage on AWS.

Sources

  1. The Cloud Panda Blog
  2. Terraform AWS Modules EFS
  3. Archiphire Docs AWS EFS Filesystem
  4. OneUptime Blog
  5. Austin Cloud Guru Terraform AWS EFS
  6. Dev.to Integrating Amazon EFS with Amazon EKS

Related Posts