[Kubernetes] AWS EKS에 볼륨 마운트 해보기
안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 EKS
클러스터에 EFS
를 마운트해서 볼륨으로 사용하는 내용을 정리해보려고 합니다. 필자가 속한 프로젝트에서는 log, config 파일등을 어떻게 관리할지를 고민하고 있는 단계입니다. 우선 공유 해서 사용할 수 있는 것은 최대한 공융를 해서 사용해보려고 합니다.
지난 글들은 아래를 참고 해주시면 됩니다.
- 쿠버네티스 1편 : 설치 가이드
- 쿠버네티스 2편 : pod
- 쿠버네티스 3편 : service
- 쿠버네티스 4편 : deployment
- 쿠버네티스 5편 : pod 설정
- 쿠버네티스 6편 : 배포 전략
- 쿠버네티스 7편 : volume
- 쿠버네티스 8편 : daemonset
- 쿠버네티스 9편 : 테라폼을 통한 클러스터 구성
- 쿠버네티스 10편 : eks에서 volume 사용하기
- 쿠버네티스 11편 : helm
- 쿠버네티스 12편 : helm chart template
- 쿠버네티스 13편 : helm deploy
- 쿠버네티스 14편 : fluentd를 통한 log수집
- 쿠버네티스 15편 : chartmuseum
- 쿠버네티스 16편 : 배포툴(ArgoCD 설치방법/사용법)
- 쿠버네티스 17편 : 배포툴(ArgoCD 구성/알람)
- 쿠버네티스 18편 : 쿠버네티스 Autoscailing
- 쿠버네티스 19편 : 쿠버네티스 로깅 아키텍처
K8S
에서의 볼륨을 마운트 하는 방식에는 지난 시간에 정리해둔 포스팅을 참조해주시기 바랍니다.
다음의 세가지에 대해서 정리를 할예입니다.
- hostpath 마운트
- EBS 마운트
- EFS 마운트
1. hostpath로 로그 마운트 하기
hostpath같은 경우는 worker-nodes를 host로 보고 그 안에 생성된 POD
끼리 host 내부의 경로를 공유해서 사용하는 형태입니다. 필자 같은 경우, POD로 아파치 미들웨어를 띄웠는데 그안에 생성되는 log(access, error)파일들을 host에서 볼수 있도록 hostpath로 지정할 생각을 해보았습니다
그림은 위와 같은 형태가 되겠습니다. POD를 감싼 박스가 1개의 host이고, host를 감싸는 박스가 한개의 가용 zone을 나냅니다.
pod < host < AZ 의 순으로 집합 관계를 표현할 수 있겠습니다.
- deployment yaml 파일
apiVersion: apps/v1beta1
kind: Deployment
metadata:
# Deployment 객체의 Unique한 명칭
name: disp-example-author
spec:
# Deployment label selector for pod
selector:
matchLabels:
app: dispatcher-author
# 3 Pods should exist at all times.
replicas: 2
template:
metadata:
labels:
# Pod의 라벨
app: dispatcher-author
spec:
containers:
- name: dispatcher-author
# Run this image
imagePullPolicy: Always
image: author
volumeMounts:
- mountPath: /usr/local/apache2/logs
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /test
type: Directory
위와 같은 형태가 되는데, 우선 replica를 2개로 구성했습니다. 필자는 1개의 cli 인스턴스와 2개의 worke-nodes로 구성을 해두었습니다. 그래서 2개의 pod을 띄워 각각 host의 경로에 log를 쌓도록 해두었습니다.
기존에 deployment에서 추가되는 부분은 아래와 같습니다.
volumeMounts:
- mountPath: /usr/local/apache2/logs
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /test
type: Directory
보시면, volumes를 host의 경로로 지정을 합니다(단, 여기서 경로는 반드시 생성이 되어있어야 합니다. )
해당 volume을 POD의 특정 경로로 마운트 합니다. /usr/local/apache2/logs
도커의 -v
옵션과 동일하게 host의 특정경로를 POD에 마운트 시켜서 사용하겠다는 내용입니다. 그러면, pod에 쌓이는 로그들이 host에서 적재가 되어, host에 직접 접속을 하면 볼 수 있는 효과가 있습니다.
그런데 여기서 하나의 worker-nodes에 여러개의 POD들이 같은 경로에 마운트 되었을경우에는 같은 파일에 대해서 어떤 처리가 되는지는 테스트가 필요할 것 같습니다.
2. EBS 마운트 하기
우선 host 방식에서 같은 파일에 대한 점유 문제로 인해, EBS를 사용하면 어떻게 될까라는 생각을 해보았습니다. 그런데, EBS 자체가 1개의 인스턴스에 마운트 되어야 하고, 그것을 같은 POD들이 마운트해서 사용하면 역시 hostpath와 같은 문제가 발생할 것 같다는 생각을 해보았습니다
그런데, 제 생각과 달리, EBS를 마운트 하는 방식에서 문제가 생겼었습니다. 우선 파일들을 보면서 정리해보겠습니다
- EBS 생성
- EBS 볼륨 마운트
EBS를 직접 생성해준다음에 해당 volume id를 기반으로 hostpath와 동일하게 마운트 하는 방식입니다. 그런데, 제가 PV, PVC를 생성하지 않았기때문에 위의 그림과 같이 1개의 POD에만 물리는거 같습니다. replica를 2개로 해두면, 나머지 POD에 대해서는 이미 ebs 볼륨에 대한 자원이 마운트 되어 사용할 수 없다고 나오면서 에러가 납니다.
apiVersion: apps/v1beta1
kind: Deployment
metadata:
# Deployment 객체의 Unique한 명칭
name: disp-example-author
spec:
# Deployment label selector for pod
selector:
matchLabels:
app: dispatcher-author
# 3 Pods should exist at all times.
replicas: 3
template:
metadata:
labels:
# Pod의 라벨
app: dispatcher-author
spec:
containers:
- name: dispatcher-author
# Run this image
imagePullPolicy: Always
image: author
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: vol-0efbe085426300704
fsType: ext4
위에 보시는것처럼 hostpath와 동일하게, 다음이 중요합니다.
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: vol-0efbe085426300704
fsType: ext4
volumeID: vol-0efbe085426300704
실제로 이러한 볼륨을 내부 POD에 마운트 하여 사용한다고 보면됩니다.
**추가 수정할 부분은 직접 PV와 PVC 로 생성하여 마운트를 해볼 예정입니다. 아무래도 이렇게 하면 hostpath 와 동일하게 여러개의 POD에 마운트가 될것 같습니다.
3. EFS 마운트 하기
오늘의 정리하는 부분에서 제일 중요한 부분입니다.
EFS에서 보이는 차이점이 있으신가요? 우선 storage class
와 EFS provisioner
가 생성이 된것을 볼 수 있습니다. EKS 에서 EFS를 마운트해서 사용하기 위해서는 2가지 리소스가 필요합니다.
- storage class : 어떤 스토리지를 사용할 것인가?
- EFS provisioner : 생성된 EFS를 기반으로 어떠한 경로에 어떻게 마운트를 시킬까를 정의하는 POD입니다.
- 스토리지 클래스 및 컨피그 맵 정의
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/class.yaml
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/configmap.yaml
위의 configmap에서 아래 내용 수정
apiVersion: v1
kind: ConfigMap
metadata:
name: efs-provisioner
data:
file.system.id: fs-390f9d92 => 수정
aws.region: us-west-2 => 수정
provisioner.name: example.com/aws-efs
dns.name: ""
kubectl apply -f class.yaml
kubectl apply -f configmap.yaml
- 프로비저너 & 접근제어 설정
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/deployment.yaml
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/rbac.yaml
위의 프로비저너(deployment)에서 아래 내용 수정
volumeMounts:
- name: pv-volume
mountPath: /persistentvolumes
volumes:
- name: pv-volume
nfs:
server: fs-1234abcd.efs.us-east-1.amazonaws.com => 수정
path: /
kubectl apply -f rbac.yaml
kubectl apply -f deployment.yaml
- 테스트
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/claim.yaml
wget https://raw.githubusercontent.com/kubernetes-incubator/external-storage/master/aws/efs/deploy/test-pod.yaml
우선 필자의 deployment 파일을 보자.
apiVersion: apps/v1beta1
kind: Deployment
metadata:
# Deployment 객체의 Unique한 명칭
name: disp-example-author
spec:
# Deployment label selector for pod
selector:
matchLabels:
app: dispatcher-author
# 3 Pods should exist at all times.
replicas: 3
template:
metadata:
labels:
# Pod의 라벨
app: dispatcher-author
spec:
containers:
- name: dispatcher-author
# Run this image
imagePullPolicy: Always
image: author
volumeMounts:
- name: efs-pvc
mountPath: "/usr/local/apache2/logs"
volumes:
- name: efs-pvc
persistentVolumeClaim:
claimName: efs
중요한 부분은 아래와 같습니다.
volumeMounts:
- name: efs-pvc
mountPath: "/usr/local/apache2/logs"
volumes:
- name: efs-pvc
persistentVolumeClaim:
claimName: efs
PV는 이미 프로비저너를 통해서 생성이 되어있고, PVC 역시 생성이 되어있습니다. 이부분이 모두 프로비저너에서 진행이 되고, 사용자는 어떻게 매핑을 시킬지만 위와같이 정의를 하면됩니다.
4. 마치며..
이번시간에는 hostpath, ebs, efs에 대해서 알아봤습니다. 아직은 볼륨을 어떤식으로 적절하게 사용할 수 있을지는 정하지 못했지만, EFS는 zone을 넘어서 모든 POD에서 공유를 할 수 있다는 장점때문에, config파일이나 공유해서 사용하는 파일들에 대해서는 꽤나 큰 장점이 있는 것 같습니다.
하지만, log 파일들에 대해서는 한곳에 모아두는것은 파일점유때문에 안되는 것 같습니다. 그래서 다음시간에는 로그를 어떻게 모니터링할지에 대한 정리를 할 예정입니다.