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" {
creationtoken = "${var.project_name}-efs"
encrypted = true
lifecyclepolicy {
transitiontoia = "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"
vpcid = var.vpc_id
ingress {
description = "NFS from VPC"
fromport = 2049
toport = 2049
protocol = "tcp"
securitygroups = var.allowedsecuritygroupids
}
egress {
fromport = 0
toport = 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_policyensures that the file system is backed up automatically. - Access Points:
aws_efs_access_pointallows 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
kmskeyarn = "arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
# performancemode = "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 = awsefsfilesystem.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 = awsefsaccesspoint.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.