Overview
AWS Elastic File System(EFS)은 확장 가능하고 완전 관리형 NFS 파일 시스템으로, 여러 EC2 인스턴스에서 동시에 접근할 수 있는 공유 스토리지를 제공한다. 특히 Kubernetes 환경에서는 여러 Pod가 동일한 데이터를 공유해야 하는 경우에 매우 유용하다.
본 글에서는 Terraform을 사용하여 EFS를 구성하고, Kubernetes에서 이를 활용하여 영구 스토리지를 구현하는 방법을 상세히 알아보겠다.

📅 관련 글
2022.02.13 - [AWS] - AWS IAM (Identity and Access Management) 개요 및 설정 방법
2022.02.07 - [AWS] - AWS EC2 인스턴스 생성
2022.02.13 - [AWS] - AWS S3 (Simple Storage Service) 개요 및 활용 방법
2023.03.30 - [AWS] - AWS Secrets Manager란?(OAuth, SSO)
2023.03.29 - [AWS] - AWS CLI 정리
2023.03.28 - [AWS] - AWS IAM이란?
2023.03.28 - [AWS] - AWS S3 권한이란?
2023.03.28 - [AWS] - AWS S3란?(개념, 속성)
2023.03.30 - [AWS] - AWS Cloudfront란? / Canary 및 Blue-Green 배포
2023.04.03 - [AWS] - AWS VPC란?
2023.05.26 - [AWS] - AWS IRSA(IAM Roles for Service Accounts)란?
2024.11.07 - [AWS] - AWS Ingress Annotations 정리
2024.11.04 - [AWS] - AWS Assume Role이란?
2024.11.16 - [AWS] - AWS Network ACL vs Security Group
2024.11.21 - [AWS] - ALB access Log 활성화 → S3 권한 설정 및 로그 저장
2024.11.24 - [AWS] - EKS Pod Identity Addon
2024.11.27 - [AWS] - AWS DynamoDB란?
2025.01.03 - [AWS] - AWS DynamoDB Local 설치
2025.09.02 - [AWS] - AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드
2025.09.05 - [AWS] - AWS CDN 구축 가이드: Kubernetes + AWS CloudFront로 API와 정적 파일 서빙 최적화
2025.09.05 - [AWS] - AWS 네트워크 연결 방식 완전 비교: VPC Peering vs Transit Gateway vs VPN
EFS란?
Amazon Elastic File System(EFS)은 AWS에서 제공하는 완전 관리형 NFS(Network File System) 서비스이다. 전통적인 온프레미스 환경에서 사용되던 네트워크 스토리지의 클라우드 버전으로 이해할 수 있다.
EFS vs 다른 AWS 스토리지 서비스
| 특성 | EFS | EBS | S3 |
| 접근 방식 | 네트워크 파일 시스템 | 블록 스토리지 | 객체 스토리지 |
| 동시 접근 | 다중 인스턴스 | 단일 인스턴스 | API 기반 |
| 사용 사례 | 공유 파일 스토리지 | 운영체제, 데이터베이스 | 백업, 아카이브, 웹 자산 |
| 확장성 | 자동 확장 | 수동 확장 | 무제한 |
언제 EFS를 사용해야 할까?
적합한 사용 사례
- 컨테이너 환경: 여러 Pod/Container가 동일한 설정 파일이나 데이터를 공유해야 하는 경우
- 콘텐츠 관리: 웹 서버들이 공통의 미디어 파일이나 정적 콘텐츠를 서빙하는 경우
- 데이터 분석: 여러 분석 작업자가 동일한 데이터셋에 동시 접근이 필요한 경우
- 백업 및 아카이빙: 여러 시스템의 백업 데이터를 중앙 집중식으로 관리하는 경우
부적합한 사용 사례
- 고성능 데이터베이스: 낮은 지연시간이 중요한 OLTP 데이터베이스
- 임시 스토리지: 인스턴스 생명주기와 함께하는 임시 데이터
- 단일 접근 워크로드: 오직 하나의 인스턴스만 접근하는 스토리지
EFS와 Access Point의 이해
EFS의 주요 특징
- 확장성: 자동으로 용량이 확장되며, 페타바이트 규모까지 지원
- 고가용성: 여러 가용 영역에 걸쳐 자동으로 복제
- 보안: KMS를 통한 저장 데이터 암호화 및 전송 중 암호화 지원
- 성능: General Purpose와 Max I/O 성능 모드 제공
Access Point의 역할
Access Point는 EFS 파일 시스템에 대한 애플리케이션별 진입점을 제공한다.
각 Access Point는
- 특정 디렉토리 경로를 루트로 설정
- POSIX 사용자 및 그룹 권한 적용
- 파일 시스템 정책과 독립적인 접근 제어 가능
Terraform을 이용한 EFS 구성
다음은 게임 서버 환경을 위한 EFS 구성 예시이다.
# KMS 키 생성 (EFS 저장 데이터 암호화용)
resource "aws_kms_key" "gameserver_efs_key" {
description = "KMS key for beta-gameserver-efs encryption"
deletion_window_in_days = 7
tags = {
Environment = var.environment
Terraform = var.terraform
}
}
resource "aws_kms_alias" "gameserver_efs_key_alias" {
name = "alias/beta-gameserver-efs"
target_key_id = aws_kms_key.gameserver_efs_key.id
}
# EFS 파일 시스템 생성
module "beta_gameserver_efs" {
source = "terraform-aws-modules/efs/aws"
# File system
name = var.beta_gameserver_efs
creation_token = "beta-gameserver-efs-token"
encrypted = true
kms_key_arn = aws_kms_key.gameserver_efs_key.arn
# 성능 및 처리량 모드
performance_mode = "generalPurpose"
throughput_mode = "provisioned"
provisioned_throughput_in_mibps = 100
# 파일 시스템 정책
attach_policy = true
bypass_policy_lockout_safety_check = false
policy_statements = [
{
sid = "BetaGameServerAccess"
actions = [
"elasticfilesystem:ClientMount",
"elasticfilesystem:ClientWrite",
"elasticfilesystem:ClientRootAccess"
]
principals = [
{
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
]
}
]
# 마운트 타겟 - 다중 가용 영역 구성
mount_targets = {
"ap-northeast-2a" = {
subnet_id = "subnet-0a1b2c3d4e5f6789a"
security_groups = ["sg-0123456789abcdef0"]
}
"ap-northeast-2b" = {
subnet_id = "subnet-0b2c3d4e5f6789abc"
security_groups = ["sg-0123456789abcdef0"]
}
"ap-northeast-2c" = {
subnet_id = "subnet-0c3d4e5f6789abcde"
security_groups = ["sg-0123456789abcdef0"]
}
}
# Access Points 구성
access_points = {
# 서버 설정 파일용 Access Point
server_config = {
name = "beta-gameserver-config"
posix_user = {
gid = 2000
uid = 2000
}
root_directory = {
path = "/server/config"
creation_info = {
owner_gid = 2000
owner_uid = 2000
permissions = "755"
}
}
tags = {
Purpose = "Server configuration directory"
Component = "server-config"
Environment = var.environment
}
}
# 게임 자산 파일용 Access Point
game_assets = {
name = "beta-gameserver-assets"
posix_user = {
gid = 2000
uid = 2000
}
root_directory = {
path = "/server/assets"
creation_info = {
owner_gid = 2000
owner_uid = 2000
permissions = "755"
}
}
tags = {
Purpose = "Game assets directory"
Component = "game-assets"
Environment = var.environment
}
}
# 플레이어 데이터용 Access Point
player_data = {
name = "beta-gameserver-playerdata"
posix_user = {
gid = 2000
uid = 2000
}
root_directory = {
path = "/server/playerdata"
creation_info = {
owner_gid = 2000
owner_uid = 2000
permissions = "750"
}
}
tags = {
Purpose = "Player data directory"
Component = "player-data"
Environment = var.environment
}
}
}
# 백업 정책 활성화
enable_backup_policy = true
tags = {
Environment = var.environment
Project = var.project
Terraform = var.terraform
Name = var.beta_gameserver_efs
}
}
Kubernetes에서 EFS 사용하기
PersistentVolume과 PersistentVolumeClaim 구성
apiVersion: v1
kind: PersistentVolume
metadata:
name: beta-gameserver-mysql-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: efs-sc
csi:
driver: efs.csi.aws.com
volumeHandle: fs-0e63cfa4272bcd819::fsap-0a1b2c3d4e5f67890
volumeAttributes:
path: "/mysql-data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: beta-gameserver-mysql-pvc
namespace: gameserver
spec:
storageClassName: efs-sc
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
volumeName: beta-gameserver-mysql-pv
MySQL Deployment 예시
apiVersion: v1
kind: Service
metadata:
name: beta-gameserver-mysql
namespace: gameserver
spec:
type: ClusterIP
ports:
- port: 3306
targetPort: 3306
protocol: TCP
selector:
app: beta-gameserver-mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: beta-gameserver-mysql
namespace: gameserver
labels:
app: beta-gameserver-mysql
spec:
replicas: 1
selector:
matchLabels:
app: beta-gameserver-mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: beta-gameserver-mysql
spec:
nodeSelector:
eks.amazonaws.com/nodegroup: GameServerNodeGroup-MainNodes
containers:
- image: mysql:8.0
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: root-password
- name: MYSQL_DATABASE
value: gameserver_db
ports:
- containerPort: 3306
protocol: TCP
name: mysql
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 2048Mi
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: beta-gameserver-mysql-pvc
volumeAttributes.path와 Access Point 활용
volumeHandle 구성 방식
volumeHandle은 다음과 같은 형태로 구성된다.
- 기본 형태: `fs-xxxxxxxxx`
- EFS 파일 시스템 ID만 지정
- 파일 시스템의 루트 디렉토리에 접근
- Access Point 사용: `fs-xxxxxxxxx::fsap-yyyyyyyy`
- EFS 파일 시스템 ID와 Access Point ID를 함께 지정
- Access Point에서 정의한 특정 디렉토리로 루트 경로가 제한됨
volumeAttributes.path의 역할
`volumeAttributes.path` 는 EFS 파일 시스템 내에서 마운트할 특정 경로를 지정
csi:
driver: efs.csi.aws.com
volumeHandle: fs-0e63cfa4272bcd819
volumeAttributes:
path: "/mysql-data" # EFS 내의 /mysql-data 디렉토리를 마운트
Access Point vs volumeAttributes.path
- Access Point 사용 시: 보다 강력한 보안 및 권한 제어 가능
- volumeAttributes.path 사용 시: 단순한 경로 지정, 유연성 높음
- 조합 사용: Access Point로 기본 권한 설정 후, path로 세부 디렉토리 지정
실제 사용 예시
# Access Point를 활용한 보안 강화 방식
apiVersion: v1
kind: PersistentVolume
metadata:
name: secure-data-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
csi:
driver: efs.csi.aws.com
volumeHandle: fs-0e63cfa4272bcd819::fsap-0a1b2c3d4e5f67890 # Access Point 사용
# volumeAttributes.path는 생략 (Access Point에서 경로 제어)
# 단순 경로 지정 방식
apiVersion: v1
kind: PersistentVolume
metadata:
name: shared-logs-pv
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteMany
csi:
driver: efs.csi.aws.com
volumeHandle: fs-0e63cfa4272bcd819 # 파일 시스템 ID만 사용
volumeAttributes:
path: "/shared/logs" # 특정 디렉토리 지정
보안 및 최적화 고려사항
보안 설정
- KMS를 통한 저장 데이터 암호화 활성화
- 전송 중 암호화(TLS) 설정
- IAM 정책을 통한 세밀한 접근 제어
- Security Group을 통한 네트워크 접근 제한
성능 최적화
- 적절한 성능 모드 선택 (General Purpose vs Max I/O)
- Throughput 모드 설정 (Bursting vs Provisioned)
- 지역별 마운트 타겟 분산 배치
비용 최적화
- Storage Class 설정 (Standard vs Infrequent Access)
- 백업 정책 적절한 설정
- 사용하지 않는 Access Point 정리
마무리
AWS EFS와 Kubernetes를 함께 활용하면 확장 가능하고 안정적인 영구 스토리지 솔루션을 구축할 수 있다. 특히 Access Point 기능을 활용하면 애플리케이션별로 격리된 환경을 제공하면서도 강력한 보안 제어가 가능하다.
본 글에서 소개한 구성을 통해 여러분의 Kubernetes 환경에서도 안정적이고 확장 가능한 스토리지 인프라를 구축하시기 바란다.
`volumeAttributes.path` 와 Access Point의 적절한 조합을 통해 보안과 유연성을 모두 확보할 수 있을 것이다.
EFS는 단순한 파일 공유를 넘어서, 현대적인 컨테이너 환경에서 필수적인 데이터 관리 솔루션으로 자리잡고 있습니다. 지속적인 모니터링과 최적화를 통해 더욱 효율적인 운영이 가능할 것이다.
Reference
'AWS' 카테고리의 다른 글
| AWS 네트워크 연결 방식 완전 비교: VPC Peering vs Transit Gateway vs VPN (0) | 2025.09.22 |
|---|---|
| AWS CDN 구축 가이드: Kubernetes + AWS CloudFront로 API와 정적 파일 서빙 최적화 (0) | 2025.09.15 |
| AWS DynamoDB Local 설치 (2) | 2025.01.03 |
| AWS DynamoDB란? (0) | 2024.11.27 |
| EKS Pod Identity Addon (0) | 2024.11.24 |