
여러 차이가 있지만 가장 큰 차이는 EBS는 특정 가용 영역에만 쓸 수 있고, 단일 EC2 인스턴스에만 연결가능하다는 것이고, EFS는 여러 인스턴스가 파일시스템을 공유하며 AZ에 제한되지 않는다는 점이다.
또한 여러개의 파드가 같은 EBS PV에 Write 할 수 없다는 것도 아주 큰 단점이다
Elastic Block Storage 이다. Block Storage란 데이터를 블록단위로 저장하는 방식을 뜻하며 클라우드 기반 저장 환경에서 사용된다. 데이터를 영구저장하려면 디스크에 저장해야한다. 결국 AWS에서 운영하는 디스크에 데이터를 저장하는데, 블록 단위로 저장해서 탄력적으로 요금을 내는 서비스이다.
AWS 인스턴스는 AWS에서 관리하는 컴퓨터에서 돌리는 하이퍼바이저에서 돌아가는 가상머신이다. 자체적으로 임시 스토리지를 가지고 있지만(그것조차 가상 하드웨어지만..) 영구저장할 수 없기 때문에… 해당 인스턴스를 껏/켯해도 영구저장할 수 있는 공간이 필요하고.. 그 때문에 EBS를 사용한다. 인스턴스의 데이터가 persistent하려면 결국엔 EBS에 저장해야하고, 그러기 위해 AWS 인스턴스는 EBS로 데이터를 전송해야한다.
Volume Attach & Mount
파일 I/O 요청이 발생하면, 커널은 이 요청을 전달받고 EBS로 데이터를 전송하게 된다. 그러기 위해 사전에 2가지 과정이 필요한다.
첫번째는 데이터를 전송할 수 있는 네트워크 경로를 설정하는 것이다. 이를 “Volume Attach” 라고 한다.
EC2 인스턴스는 가상 블록 장치로 EBS를 인식하고, 해당 장치를 디바이스 파일(/dev/xvdf 등)로 나타난다.
두번째는 EBS의 파일시스템을 인스턴스의 파일 시스템 트리에 연결하는 작업인데, 이를 “mount” 라고 한다.
EBS의 파일시스템과 인스턴스 파일 시스템은 구조적으로 다르지만, OS의 VFS 계층을 통해 통일된 방식으로 파일을 다룰 수 있다.
EFS는 Elastic File System이다. EBS가 블록단위로 디스크를 공유하는 것이라면 EFS는 파일 단위로 데이터를 다룬다. (Network File System Protocol) 그래서 이름자체도 File System이다.
EBS에 비해 EFS가 여러 인스턴스에서 파일시스템을 공유할 수 있는 이유는, 파일 lock 메커니즘이 있기 때문이다. 자원을 공유하려면 결국 경쟁상태가 발생하기 때문에... 동시성 제어가 필수적인데 블록단위로 데이터를 관리하는 EBS에서는 이게 안된다고 한다. NFS는 애초에 여러 클라이언트가 파일시스템을 공유하도록 설계되었다. 그래서 결국 여러 인스턴스가 파일 시스템을 공유할 수 있는 것이다.
하지만 NFS 프로토콜은 네트워크 통신을 거치게 된다. 예를 들면 RPC를 사용하여 원격 서버에 파일 시스템 요청을 보내고, 그에 대한 응답을 받는 방식으로 동작한다. 네트워크 상에서 데이터 패킷을 패키징하고.. 전달하고.. 까서 확인하고.. 등등의 작업이 있어서 오버헤드가 큰게 단점이다.
반면 EBS는 AWS 자체 인프라를 통해 마치 EBS와 인스턴스를 로컬 통신하듯이 빠르게 데이터를 송/수신 하도록 설계되었기 때문에 데이터 송/수신에서 오버헤드가 거의 없다.
실제 EFS를 써서 만든 PV는 어짜피 네트워크를 거치기 때문에 AZ에는 종속되지않아 AZ 관련한 정보는 없지만,

로컬 통신하는 것처럼 설계한 EBS는 파드가 스케줄링된 노드가 프로비저닝된 AZ가 노드 셀렉터로 포함되어있다.

이제 그럼 어떻게 쿠버네티스 환경에 EFS를 마운트하는지 알아보자


드라이버는 왜 설치해줄까?
컨테이너에서는 기본적으로 NFS 프로토콜 인식이 안되기 때문에 우선 그것과 관련된 설치를 해주고.. EFS 파일 시스템을 마운트하고 Read Write할 수 있는 작업을 지원한다.
또한 PVC에 따라 동적으로 PV를 생성하도록 하는 efs-controller파드가 자동으로 kube-system에 설치된다

그리고 IAM 롤은 IRSA에 사용되기 때문에 ServiceAccount에 부여된다.
동적으로 PV를 만드려면 AWS 리소스인 EFS에 접근해야하기때문에 policy가 필요한데, 파드는 AWS 리소스가 아니다.
그래서 신원인증을 위해 OIDC Provider를 사용하게 된다. 컨트롤 플레인 OIDC Provider는 EFS 관련 policy 권한이 명세된 JWT를 controller 파드에 넣어주고, efs contoller 파드는 그걸로 sts와 통신해서 EFS에 접근할 수 있는 엑세스키와 시크릿키를 가져오게된다.


EFS는 콘솔에서 쉽게 생성할 수 있다.

주의할점은 여기서 network aceess에서 보안그룹을 설정해줘야한다는 것이다
EFS는 NFS 프로토콜을 사용하여 데이터를 EC2 인스턴스나 다른 리소스에 연결하기 때문에, 네트워크 통신이 이루어진다. 그래서 보안그룹을 넣어줘야하고

인스턴스에 마운트된 파일시스템의 데이터를 송수신해야되서, 해당 eks-node 그룹의 보안그룹에 인바운드 통신 포트를 열어줘야한다
TCP 2049를 입력하면 알아서 NFS 타입으로 잡힌다!

이후 프로비저닝하려는 EFS를 다음과 같은 형태로 넣어준다
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: efs-test
provisioner: efs.csi.aws.com
parameters:
provisioningMode: efs-ap
fileSystemId: fs-dsadzdzd
directoryPerms: "700"
StorageClass를 바탕으로 아래와 같이 PVC를 만든다
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: MyPVCName
spec:
accessModes:
- ReadWriteMany
storageClassName: MystorageClassName
resources:
requests:
storage: 10Gi
EFS를 쓰려는 컨테이너의 파일시스템과 EFS 파일시스템을 공유시킨다. 이때 마운트경로 루트 경로가 되면, 기존 파일시스템이 컨테이너 ephemeral 파일 시스템을 덮어씌워버리므로, 루트경로를 쓰면 안된다. (에러가 난다)
volumeMounts:
- name: MyVolume
mountPath: MountPath #루트 경로가 되면 안됨
volumes:
- name: MyVolume
persistentVolumeClaim:
claimName: MyPVC
성공하면 요청된 Storage 크기만큼 PVC가 PV를 잘 만들어준다
