AWS EKS
AWS의 EKS는 쿠버네티스 환경을 Managed로 구축 할 수 있도록 도와주는 SaaS 서비스입니다. 리소스의 사용에 따라 유동적으로 노드를 다룰 수 있는 클러스터를 구축하는 것 뿐 아니라, Pod라는 단위의 컨테이너로 프로그램을 묶어 사용 할 수 있게 구축하여 추정 리소스를 구분하여 할당하고, 서비스 할 수 있도록 도와주는 서비스입니다.
EKS Storage
EKS는 Pod를 통해 서비스를 구축하기 때문에 데이터를 저장하는 공간에 대해 많은 어려운 점이 발생합니다. 컨테이너 환경에서 Storage를 사용하는 과정에서 생각 할 수 있는 걸 차근차근 풀어나가보겠습니다.
컨테이너가 떠있는 노드의 디스크에 저장하면 되는거 아니야?
가장 먼저 떠오르는 질문이 노드 내 디스크 용량을 활용하는 것 입니다. 사실 이 방식이 Docker를 사용 할 때 자주 사용하는 방식입니다.
Docker도 마찬가지로 컨테이너로 띄우는 방식이라서 컨테이너 내 저장 공간으로 사용 할 저장 공간이 필요합니다. 이때는 노드 내의 디스크의 특정 디렉토리에 컨테이너의 특정 경로를 마운트하여 노드의 디스크를 사용하도록 설정합니다.
그런데 여러 컨테이너가 띄워지면, 그리고 가장 큰 문제로 “어떤 Pod(컨테이너)가 이 Node에 뜨게 될 지 모르는 상황“이라면? 어떤 디렉토리에 컨테이너 Path를 마운트해야 할 지 알 수 없습니다. 이 문제는 가상화에 너무나 큰 장애지점으로 다가옵니다.
그래서 다른 방법을 찾습니다.
외부 저장공간을 별도로 두면 해결 할 수 있을 것 같은데?
이 방법은 상당히 많은 부분을 해결합니다. 유동적으로 생성되는 Pod에 대해서 외부 스토리지 또한 유동적으로 생성되게 한다면 Pod 별 스토리지를 가질 수 있으면서도, 특정 노드에 꼭 Pod가 뜨지 않고 다른 노드에 해당 Pod가 뜨더라도 데이터는 유실되지 않으면서 동작 할 수 있습니다.
AWS에서는 이러한 방식으로 EBS(Elastic Block Storage)를 만들었습니다.
EBS는 EC2 인스턴스에 부착하여 사용 할 수 있는 일종의 디스크라고 생각할 수 있습니다. 정말 해당 컴퓨터에 부착 된 HDD로써 로컬 디스크와는 개념이 다르지만, 동일한 가용 영역내에 존재하는 EC2 인스턴스에 자유롭게 부착하여 사용 할 수 있는 스토리지입니다.
실제로 공식 문서를 봐도 “you can use it as you would use a physical hard drive” 라는 문장을 사용하면서 EC2에서의 실제 하드 디스크처럼 사용 할 수 있음을 강조합니다.
우리는 여기서 하드 디스크를 중점으로 생각하면 이전에 알아 본 내용인 노드에 귀속 된 데이터를 저장하는 것이 아닌가? 라고 생각 할 수 있습니다. 하지만, 실제로는 EC2 인스턴스가 종료되어도 EBS는 독립적으로 유지되며 다른 인스턴스에 연결 할 수 있습니다.
즉 저장공간을 외부에 별도록 구축하는 방식이라고 할 수 있습니다. 이 방식을 사용하면 같은 가용영역을 가지는게 거의 확실한 EKS내에서 Pod 컨테이너를 띄울 때마다 해당 EBS를 연동하는 방식을 사용하면 얼마든지 데이터를 유실하거나 복잡한 스냅샷 복제 과정등을 거치지 않아도 서비스를 운영 할 수 있습니다.
또한 하나의 인스턴스에 여러 개의 EBS를 붙일 수 있습니다. 보통 우리가 리눅스에서 운영체제를 나누거나, 외부 저장공간을 사용 할 때 독립적인 저장공간으로 사용 할 때 파티션으로 나누는 것을 볼 수 있습니다. 이 경우 여러 저장공간이 하나의 컴퓨터에 존재하는 경우를 볼 수 있는데 이러한 경우와 유사합니다.
동일한 파일을 공유하려면 어떻게 하지?
사실 EBS로 인해 Pod가 가질 수 있는 독립적인 저장공간 문제를 완벽하게 해결했습니다. 그러면 우리가 단일 노드에서 도커를 통해 컨테이너를 띄우던 시절을 완벽하게 대체할 수 있을까요?
그렇지 않을 수 있습니다. 왜냐하면 데이터 공유 문제가 아직 해결되지 않았거든요.
데이터 공유는 사실 특별한 방법은 없습니다. 우리는 정말 다양한 데이터 공유 방식을 알고 있고, 그 중 어떤 것을 사용하더라도 문제를 해결 할 수 있습니다.
예를 들면, 데이터베이스가 있습니다. 정해진 스키마로 이루어진 경우 데이터를 공유 할 떄 영구성을 보장받고 트랜잭션이 완벽히 동작하는 훌륭한 데이터 저장 및 공유 방식입니다. 물론 커넥션과 데이터베이스의 연산(SQL은 오히려 좋을지도!)등이 포함 된 부하를 가지지만 여전히 훌륭한 방식입니다.
그러면 파일 공유는 어떨까요?
파일 공유도 여전히 훌륭한 방식이 있습니다. 대표적인 방식이 HDFS가 있죠. HDFS 클러스터를 구축해놓고 개별 스토리지 서버를 구축해 놓으면 심지어 Spark이나 HIVE기반의 프레임워크를 연산으로 사용 할 수 있는 훌륭한 방식입니다. 하지만 이 방식이 엄청난 인적 리소스와 비용 및 서버 리소스가 들어간다는 사실을 많은 사람은 알고 있을 것 입니다.
AWS에서도 대부분을 지원하지만, 파일 기반 스토리지로 EFS(Elastic File System)을 지원하고 있습니다.
EBS는 왜 공유가 불가능하지? 라는 질문을 할 수 있습니다. 하지만, 하드 디스크에 비유 한 내용을 생각하면 당연하다고 생각합니다. 하지만 EFS는 하드디스크라기보다 NFS를 적용 한 서비스라고 볼 수 있습니다. 정확히는 실제로 NFS 프로토콜을 사용합니다.
외부 스토리지이면서 동시에 네트워크 IO를 통한 통신을 수행하는 NFS 프로토콜을 채택한 EFS는 여러 서버에서 동일한 경로를 마운트 할 수 있습니다.
AWS EKS using AWS Storages
쿠버네티스에서 관리하는 Pod들의 파일들을 AWS Storage를 이용해 관리하려면 각 EC2(노드) 인스턴스에 EBS를 붙이는 것보다 한 단계 더 필요합니다.
바로 PV(Persistence Volume)와 PVC(Persistence Volume Claim)의 생성입니다. 그리고 PV의 주체가 되는 Storage Class도 알아두어야 합니다.
PV (Persistence Volume)
PV는 실제로 생성 된 저장소라고 생각하면 됩니다.
Storage Class
Storage Class는 쿠버네티스에서 저장소에 대한 메타데이터를 가진 설계도입니다. 자바에서 Class를 이용한 객체 생성을 통해 재사용성을 높이는 개념과 유사하게 Storage Class 또한 Storage를 만드는 기본 설계도처럼 사용됩니다.
예를 들면 다음과 같은 설계가 이루어 질 수 있습니다.
“Airflow Worker Pod가 올라가는 EC2 인스턴스들은 각기 다른 저장공간을 가져도 된다” 라는 설계 논리를 가지고 “각 인스턴스는 임시 파일의 사용을 위해 노드 이상의 저장공간이 필요하다” 라는 추가적인 니즈가 있을 때 우리는 각 인스턴스에 EBS를 붙이고 싶다는 생각을 할 수 있습니다.
EBS는 한 인스턴스에 N개 이상 붙일 수 있으며 하나의 EBS를 여러 노드에 동시에 마운트 할 수 없기 때문에 노드가 떠오를 때 사용 될 EBS를 만들 수 있어야 합니다.
그러면 우리는 Storage Class를 이용하여 쿠버네티스 서비스 내에 자동으로 생성 할 EBS 스토리지의 스펙을 정의해놓으면 됩니다.
PVC (Persistence Volume Claim)
PVC는 Storage Class를 기반으로 PV를 동적으로 생성해주거나 기존에 존재하는 PV를 연결하는 동작을 수행합니다. 이 때 어떤 Storage Class를 기반으로 할 것인지, 마운트 경로를 어디로 할 것인지 등 실제 스토리지 사용 시에 대한 설정이 포함됩니다.
이렇게 PVC를 만들면 Pod 생성 설정값에 추가하면 Pod의 생성에 따라 각자의 스토리지로 연결됩니다.
참고
https://zesty.co/blog/ebs-vs-efs-which-is-right/
https://kimjingo.tistory.com/153