Engineering Scalable Shared Storage: Implementing Amazon EFS with Terraform

Amazon Elastic File System (EFS) provides a scalable, network-based file sharing storage system that allows multiple servers—such as Amazon EC2 instances or containers within an Amazon EKS cluster—to access the same shared storage concurrently. Leveraging Terraform for the deployment of EFS ensures that infrastructure is treated as code, allowing for version-controlled, repeatable, and compliant storage architectures.

Implementing EFS through Terraform involves more than the mere creation of a file system; it requires the orchestration of mount targets, security groups, access points, and lifecycle policies to ensure the system is performant, secure, and cost-effective.

Architectural Fundamentals of AWS EFS

EFS operates as a managed Network File System (NFS), eliminating the need for manual scaling of disk space or the management of underlying hardware. Unlike Amazon EBS, which is generally attached to a single instance, EFS is designed for shared access across thousands of compute instances.

To make an EFS file system accessible, mount targets must be created in the subnets where the compute resources reside. A mount point is effectively an endpoint that provides the necessary network path for a server to communicate with the EFS file system.

Prerequisites and Environment Configuration

Before initiating the Terraform deployment, several foundational components must be in place to ensure a seamless execution.

Hardware and Software Requirements

  • Terraform installed on the local machine or CI/CD runner.
  • AWS CLI configured with appropriate credentials.
  • A pre-existing Virtual Private Cloud (VPC) and defined subnets.
  • A basic understanding of Network File Systems (NFS) and how they operate.

Authentication and State Management

AWS access keys and secret keys must be configured on the operating machine, or an alternative form of AWS authentication (such as IAM instance profiles) must be utilized. To maintain the state of the infrastructure and allow for collaboration, a remote backend is highly recommended. Using an S3 bucket for tfstate files prevents state corruption and enables locking.

Example backend.tf configuration:

hcl terraform { backend "s3" { bucket = "terraform-tfstate" // your bucket name key = "tfstate" region = "us-east-1" // your region } }

Core Implementation Strategy

A production-ready project structure for EFS deployment typically segregates configurations to maintain readability and modularity.

Recommended Project Structure

  • aws-efs-terraform/
    • main.tf: The primary resource definitions.
    • variables.tf: Input variable definitions for flexibility.
    • outputs.tf: Exported values for use by other modules.
    • terraform.tfvars: Specific value assignments for the environment.

Defining the EFS File System

The central resource is aws_efs_file_system. Key configurations include encryption and lifecycle management. Transitioning files to the Infrequent Access (IA) storage class after a set period (e.g., 30 days) significantly reduces costs for data that is not accessed frequently.

```hcl
resource "awsefsfilesystem" "main" {
creation
token = "${var.project_name}-efs"
encrypted = true

lifecyclepolicy {
transition
toia = "AFTER30_DAYS"
}

tags = {
Name = "${var.project_name}-efs"
}
}
```

Configuring Mount Targets and Connectivity

Since EFS is a regional service, mount targets must be deployed in each subnet where instances need access. The aws_efs_mount_target resource handles this mapping.

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] }

Security Group Orchestration

EFS communicates over the NFS protocol, which uses TCP port 2049. The security group must be configured to allow inbound traffic on this port from the specific security groups of the EC2 instances or EKS nodes.

```hcl
resource "awssecuritygroup" "efs" {
name = "${var.projectname}-efs-sg"
description = "Allow EFS inbound traffic"
vpc
id = var.vpc_id

ingress {
description = "NFS from VPC"
fromport = 2049
to
port = 2049
protocol = "tcp"
securitygroups = var.allowedsecuritygroupids
}

egress {
fromport = 0
to
port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

tags = {
Name = "${var.project_name}-efs-sg"
}
}
```

Advanced EFS Features and Compliance

For enterprise environments, basic file system creation is insufficient. Compliance frameworks such as FedRAMP and the AWS Well-Architected Framework mandate strict encryption and backup policies.

Compliance Controls Matrix

The following table outlines the mandatory controls for EFS file systems across various global compliance frameworks.

Control FedRAMP Moderate Rev 4 Well-Architected v10 AWS Benchmark v5.0 AWS Benchmark v6.0 CISA Cyber Essentials Title 21 CFR Part 11 EU GMP Annex 11 FFIEC Cybersecurity
Encryption at rest enabled
Encrypted with CMK

Backup Policies and Access Points

To ensure data durability and granular access control, optional resources can be added to the Terraform configuration.

  • Backup Policies: The aws_efs_backup_policy ensures that the file system is backed up automatically.
  • Access Points: aws_efs_access_point allows for the creation of specific entry points to the file system, which is critical for multi-tenant applications or Kubernetes pods.

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

Integrating EFS with Amazon EKS

Deploying EFS for use with Amazon Elastic Kubernetes Service (EKS) requires a more complex integration involving the AWS EFS CSI (Container Storage Interface) driver.

EKS Integration Requirements

Before deploying the EFS integration, the following conditions must be satisfied:

Requirement Description
EKS Cluster A running Amazon EKS cluster (version 1.28 or newer recommended).
EFS CSI Driver Must be installed via Terraform (e.g., aws-ia/eks-blueprints-addons) or manually via Helm/kubectl.
OIDC Provider Must be enabled for the cluster to support IAM Roles for Service Accounts (IRSA).

EKS Workflow and Persistence

The integration follows a specific logical flow to translate Kubernetes storage requests into AWS resources:
1. KMS Encryption: Ensure the EFS file system is encrypted at rest.
2. IRSA: Use IAM Roles for Service Accounts to grant the EFS CSI driver permission to manage the file system.
3. Kubernetes Objects: Configure a StorageClass, PersistentVolume (PV), and PersistentVolumeClaim (PVC).
4. Application Access: Pods mount the PVC, and the CSI driver handles the mounting of the EFS volume using dedicated access points (e.g., /data/podinfo).

Utilizing Terraform Modules

For those seeking a more abstracted approach, community-maintained modules such as terraform-aws-modules/efs/aws offer a streamlined way to deploy EFS without writing every resource from scratch.

Module Implementation Example

Using a module reduces boilerplate code while still allowing for deep customization through arguments.

```hcl
module "efs" {
source = "terraform-aws-modules/efs/aws"

name = "example"
creationtoken = "example-token"
encrypted = true
kms
keyarn = "arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
# performance
mode = "maxIO"
}
```

Module Migration and Reversibility

When moving to specialized compliance-checked modules (such as those from compliance.tf), the transition is designed to be seamless. Because the underlying AWS resource addresses remain the same, users can switch source URLs and run terraform init -upgrade without altering the existing state of the infrastructure.

Output Management for Inter-Module Communication

In a complex infrastructure, the EFS module must export critical identifiers so that EC2 or EKS modules can mount the drive.

```hcl
output "efsid" {
value = aws
efsfilesystem.main.id
description = "EFS file system ID"
}

output "efsdnsname" {
value = awsefsfilesystem.main.dnsname
description = "EFS DNS name for mounting"
}

output "accesspointids" {
value = {
api = awsefsaccesspoint.api.id
worker = aws
efsaccesspoint.worker.id
}
description = "Access point IDs by service"
}
```

Conclusion

Implementing Amazon EFS via Terraform transforms a manual networking task into a scalable, audited architectural component. By carefully managing the relationship between the aws_efs_file_system, its aws_efs_mount_target instances, and the governing aws_security_group, engineers can create a robust shared storage environment.

The integration with Amazon EKS further demonstrates the flexibility of this approach, utilizing the EFS CSI driver and IRSA to provide pod-level persistence. Whether using raw resources for maximum control or leveraging optimized modules for speed and compliance, the priority remains the same: ensuring encryption at rest, implementing lifecycle policies to manage costs, and strictly controlling network ingress via NFS port 2049. For production environments, adhering to the mapped compliance frameworks—particularly those requiring CMK encryption—is non-negotiable to maintain a secure posture.

Sources

  1. The Cloud Panda
  2. Dev.to - Huzaifa Mushfiq
  3. Compliance.tf
  4. GitHub - Terraform AWS Modules
  5. OneUptime
  6. Dev.to - Santanu Das

Related Posts