본 시리즈는 가시다님의 AEWS(AWS EKS Workshop) 1기 진행 내용입니다. (가시다님 노션)
스터디에 사용되는 링크 (AWS EKS Workshop)
목차
1. 스토리지의 이해
2. AWS EBS Controller
3. AWS Volume Snapshots Controller
4. AWS EFS Controller
5. AWS Persistent Volume for Instance Store & Add Node Group
1. 스토리지의 이해
https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/
기본 설명
- 파드 내부의 데이터는 파드가 정지되면 모두 삭제됨
- 즉, 모두 상태가 없는(Stateless) 애플리케이션: Temporary filesystem, Volume - 링크
- 데이터베이스(파드)처럼 데이터 보존이 필요 == 상태가 있는(Stateful) 애플리케이션 : PV & PVC
- 로컬 볼륨(hostPath) ⇒ 퍼시스턴트 볼륨(Persistent Volume, PV) - 어느 노드에서도 연결하여 사용 가능, 예시) NFS, AWS EBS, Ceph 등
- 파드가 생성될 때 자동으로 볼륨을 마운트하여 파드에 연결하는 기능을 동적 프로비저닝(Dynamic Provisioning)이라고 함(스토리지 클래스 사용)
- Reclaim Policy
- 퍼시스턴트 볼륨의 사용이 끝났을 때 해당 볼륨은 어떻게 초기화할 것인지 별도로 설정
- Retain(보존), Delete(삭제, 즉 EBS 볼륨도 삭제됨),
Recycle(deprecated) 방식
스토리지 소개 : 출처 - 김태민 기술 블로그 - 링크
- 볼륨 : emptyDir, hostPath, PV/PVC
- 다양한 볼륨 사용 : K8S 자체 제공(hostPath, local), 온프렘 솔루션(ceph 등), NFS, 클라우드 스토리지(AWS EBS 등)
- 동적 프로비저닝 & 볼륨 상태 , ReclaimPolicy
CSI (Contaier Storage Interface) 소개
- CSI Driver 배경
- Kubernetes source code 내부에 존재하는 AWS EBS provisioner는 당연히 Kubernetes release lifecycle을 따라서 배포
- provisioner 신규 기능을 사용하기 위해서는 Kubernetes version을 업그레이드해야 하는 제약 사항 존재
- 따라서, Kubernetes 개발자는 Kubernetes 내부에 내장된 provisioner (in-tree)를 모두 삭제하고, 별도의 controller Pod을 통해 동적 provisioning을 사용
- CSI 를 사용하면, K8S 의 공통화된 CSI 인터페이스를 통해 다양한 프로바이더를 사용 가능
- 일반적인 CSI driver의 구조
AWS EBS CSI driver 구조
- 오른쪽 StatefulSet 또는 Deployment로 배포된 controller Pod이 AWS API를 사용하여 실제 EBS volume을 생성하는 역할
- 왼쪽 DaemonSet으로 배포된 node Pod은 AWS API를 사용하여 Kubernetes node (EC2 instance)에 EBS volume을 attach
Node-specific Volume Limits - 링크
AWS EC2 Type에 따라 볼륨 최대 제한 : 25개 ~ 39개
# 확인
kubectl describe node | grep Allocatable: -A1
Allocatable:
attachable-volumes-aws-ebs: 25
- KUBE_MAX_PD_VOLS 환경 변수의 값을 설정한 후, 스케줄러를 재시작하여 이러한 한도를 변경 가능
기본 컨테이너 환경의 임시 파일시스템 사용
# 파드 배포
# date 명령어로 현재 시간을 10초 간격으로 /home/pod-out.txt 파일에 저장
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/date-busybox-pod.yaml
cat date-busybox-pod.yaml | yh
kubectl apply -f date-busybox-pod.yaml
# 파일 확인
kubectl get pod
kubectl exec busybox -- tail -f /home/pod-out.txt
Sat Jan 28 15:33:11 UTC 2023
Sat Jan 28 15:33:21 UTC 2023
...
# 파드 삭제 후 다시 생성 후 파일 정보 확인 > 이전 기록이 보존되어 있는지?
kubectl delete pod busybox
kubectl apply -f date-busybox-pod.yaml
kubectl exec busybox -- tail -f /home/pod-out.txt
# 실습 완료 후 삭제
kubectl delete pod busybox
호스트 Path 를 사용하는 PV/PVC : local-path-provisioner 스트리지 클래스 배포 - 링크
# 배포
curl -s -O https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
kubectl apply -f local-path-storage.yaml
# 확인
kubectl get-all -n local-path-storage
kubectl get pod -n local-path-storage -owide
kubectl describe cm -n local-path-storage local-path-config
kubectl get sc
kubectl get sc local-path
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path rancher.io/local-path Delete WaitForFirstConsumer false 34s
- PV/PVC 를 사용하는 파드 생성
# PVC 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath1.yaml
cat localpath1.yaml | yh
kubectl apply -f localpath1.yaml
# PVC 확인
kubectl get pvc
kubectl describe pvc
# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath2.yaml
cat localpath2.yaml | yh
kubectl apply -f localpath2.yaml
# 파드 확인
kubectl get pod,pv,pvc
kubectl describe pv # Node Affinity 확인
kubectl exec -it app -- tail -f /data/out.txt
Sun Jan 29 05:13:45 UTC 2023
...
# 워커노드 중 현재 파드가 배포되어 있다만, 아래 경로에 out.txt 파일 존재 확인
ssh ec2-user@$N1 tree /opt/local-path-provisioner
/opt/local-path-provisioner
└── pvc-f1615862-e4cd-47d0-b89c-8d0e99270678_default_localpath-claim
└── out.txt
# 해당 워커노드 자체에서 out.txt 파일 확인 : 아래 굵은 부분은 각자 실습 환경에 따라 다름
ssh ec2-user@$N1 tail -f /opt/local-path-provisioner/pvc-f1615862-e4cd-47d0-b89c-8d0e99270678_default_localpath-claim/out.txt
Sun Jan 29 05:13:45 UTC 2023
...
- 파드 삭제 후 파드 재생성해서 데이터 유지 되는지 확인다음 실습을 위해서 파드와 PVC 삭제
# 파드와 PVC 삭제
kubectl delete pod app
kubectl get pv,pvc
kubectl delete pvc localpath-claim
# 확인
kubectl get pv
ssh ec2-user@$N3 tree /opt/local-path-provisioner
ip-192-168-1-248.ap-northeast-2.compute.internal 노드에 배포됨
- 당연히 node에 귀속된 디스크 자원을 쓰는 형태로 볼륨을 잡았기 때문에 데이터(볼륨)가 있는 node로 pod를 배포
복습 겸 퀴즈
hostpath(local-path-provisioner)를 사용하는 Deployment를 배포하면 Pod는 어떤 node들에 배포될까?
정답
노드 하나에 다 배포된다.
다만, 기분이 나쁘니 단순히 pod가 노드마다 있었으면 좋겠다면 아래처럼 하면 된다.
대신 데이터는 당연히 3개 파드가 각각 다른 영구적볼륨에 저장된다.
번외편 (응용)
아까 StoageClassName을 잘 기억해뒀다 쓰면 됨이라고 표기해둔 이유
Helm Chart를 통해 배포할 때 용이하게 사용 가능
이건 local-path-provisioner 뿐만 아니라 모든 동적 프로비저닝 방식에서 지정한 StorageClassName을 사용하면 된다
예시 Jenkins Helm Chart
https://artifacthub.io/packages/helm/jenkinsci/jenkins
단 헬름 차트마다 만드는 사람이 value의 파라미터 명을 조금씩 바꿔서 기입하니 반드시 확인할 것.
values보다 정확하게 확인하려면 Templates 을 보자
## jenkins-values.yaml
persistence:
enabled: true
storageClass: "local-path"
annotations: {}
labels: {}
accessMode: "ReadWriteOnce"
size: "8Gi"
volumes:
- name: nothing
emptyDir: {}
mounts:
- mountPath: /var/nothing
name: nothing
readOnly: true
## helm repo add
helm repo add jenkins https://charts.jenkins.io
helm repo update
## jenkins-values.yaml 작성 후 실행
helm install jenkins jenkins/jenkins -f jenkins-values.yaml
이렇게 간단하게 사용 가능하다
결론
로컬 스토리지를 단계별로 실습했다.
1. 임시 스토리지 (휘발)
2. hostPath (node 귀속)
2-1. 수동 pvc
2-2. 동적 프로비저닝
번외. Helm Chart에서 StorageClass 사용
HostPath 의 장점
- Node의 컴퓨팅 리소스를 사용하여 빠르다(NFS나 외부 저장소를 마운트한 디렉토리 제외)
- 간편한 설정
- 비용 절감 (로컬 자원 사용)
HostPath의 단점
- Node에 Pod가 귀속된다.
- 확장성
- 데이터의 내구성
- 보안 (데이터 격리 및 액세스 제어 어려움)
- HostPath 동적 프로비저닝은 임시 데이터나 캐시 데이터와 같이 영구적인 스토리지가 필요하지 않은 경우에 적합
- 그러나 주의해야 할 점은 HostPath 스토리지가 로컬 노드에 있으므로 Pod가 스케줄링되는 노드 간에 데이터가 이동할 수 없다는 것.
- 따라서, 데이터의 내구성이 중요한 경우에는 클라우드 프로바이더의 외부 스토리지를 사용하는 것이 더 적합
'Tech > Kubernetes' 카테고리의 다른 글
[AEWS_1기] 3주차 - Amazon EKS Storage (3/5) - AWS Volume Snapshots Controller (0) | 2023.05.14 |
---|---|
[AEWS_1기] 3주차 - Amazon EKS Storage (2/5) - AWS EBS Controller (0) | 2023.05.14 |
[AEWS_1기] 1주차 - Amazon EKS 도전과제 (2/2) (0) | 2023.05.03 |
[AEWS_1기] 2주차 - EKS Networking (1/2) (0) | 2023.05.03 |
[AEWS_1기] 1주차 - Amazon EKS 설치 및 기본 사용 (1/2) (0) | 2023.04.25 |
댓글