AWS

AWS EFS와 Kubernetes를 활용한 영구 스토리지 구축 가이드

Somaz 2026. 1. 6. 00:00
728x90
반응형

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은 다음과 같은 형태로 구성된다.

 

  1. 기본 형태: `fs-xxxxxxxxx`
    • EFS 파일 시스템 ID만 지정
    • 파일 시스템의 루트 디렉토리에 접근
  2. 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

 

 

 

 

728x90
반응형