이 글은 쿠버네티스 임시 볼륨(Ephemeral Volumes, 또는 임시 스토리지)을 잘못 사용했을 때 발생할 수 있는 서비스 장애 상황을 설명합니다. 이 글에서 다루는 예제는 github에 공개되어 있습니다.
1. 시나리오
이 시나리오는 임시 볼륨을 잘못 사용하는 Pod로 인해 동일한 노드에 있는 다른 Pod가 비정상 상태가 되는 상황을 재현합니다. 쿠버네티스는 EKS를 사용합니다.
서비스 pod는 nginx를 사용하고 외부에서 nginx pod를 접속할 수 있도록 ALB를 사용합니다. 장애가 발생하기 전에는 nginx pod는 아래 그림처럼 정상적으로 실행됩니다
하지만, 갑자기 임시 볼륨을 사용하는 pod의 영향으로 nginx pod를 접속하지 못합니다.
임시 볼륨의 pod manifest는 아래와 같습니다. pod는 emptyDir를 사용하여 임시 볼륨을 사용했습니다. 쿠버네티스 manifest는 저의 github에 공개되어 있습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: emptydir-stress
spec:
replicas: 2
selector:
matchLabels:
app: emptydir-stress
template:
metadata:
labels:
app: emptydir-stress
spec:
nodeSelector:
env: test
containers:
- name: fill-disk-container
image: busybox
command: ["/bin/sh", "-c"]
args:
- >
i=0; while true; do
echo "iteration $i";
dd if=/dev/zero of=/data/file$i bs=10M count=1024;
i=$((i+1));
done;
volumeMounts:
- mountPath: /data
name: temp-storage
volumes:
- name: temp-storage
emptyDir: {}
2. 시나리오에서 장애의 원인은?
장애가 발생한 이유는 pod가 임시 볼륨을 노드 디스크 용량보다 많이 사용했기 때문입니다. 노드 디스크 용량이 가득차서 노드가 비정상상태가 되고 노드에서 실행 중인 pod또한 비정상 상태가 되었습니다. 그래서 잘 접속되었던 nginx pod가 갑자기 접속이 안되었던 겁니다.
이제 임시 볼륨이 무엇인지, 그리고 왜 이러한 문제가 발생했는지에 대해 자세히 알아보겠습니다.
3. 임시 볼륨이란?
임시 볼륨은 pod가 종료되면 삭제되는 휘발성 볼륨입니다. pod에서 configmap, secret을 마운트해서 사용하거나 pod가 실행 중에만 필요한 비영구 데이터를 저장할 때 사용합니다. 임시 볼륨은 kubelet이 관리합니다.
4. 임시 볼륨 종류
4.1 rootfs 임시 볼륨
pod는 볼륨 마운트 설정이 없으면 모든 파일을 임시 볼륨으로 사용합니다. 따라서 pod의 모든 파일은 노드에 있습니다. 이러한 유형의 임시 볼륨을 rootfs라고 부릅니다.
pod가 생성되면 kubelet은 pod 루트 디렉터리를 노드 특정 경로에 마운트합니다. 디폴트 마운트 경로는 컨테이너 런타임에 따라 다릅니다. containerd는 /run/containerd입니다. 다른 컨테이너 런타임은 공식문서를 참고해주세요.
예를 들어 nginx pod에서 hello.txt파일을 생성합니다. 파일 내용은 “hello. node”로 했습니다.
저는 EKS를 사용합니다. EKS는 containerd를 사용하기 때문에, EKS노드의 /run/containerd 경로에 hello.txt파일이 저장되어 있습니다.
find /run/containerd -name hello.txt
4.2 emptyDir 임시 볼륨
emptyDir임시 스토리지는 pod 특정 경로에서 사용하는 전용 임시 볼륨입니다. emptyDir을 사용하는 pod는 voluems필드에 emptyDir를 정의합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: emptydir-example
spec:
replicas: 1
selector:
matchLabels:
app: emptydir-example
template:
metadata:
labels:
app: emptydir-example
spec:
containers:
- name: fill-disk-container
image: busybox
command: ["/bin/sh", "-c"]
volumeMounts:
- mountPath: /data
name: temp-storage
volumes:
- name: temp-storage
emptyDir: {}
emptyDir 임시 볼륨 또한 노드 특정 경로에 마운트됩니다. 마운트 경로는 /var/lib/kubelet입니다.
예를 들어 pod에서 emptyDir디렉터리에 hi.txt파일을 생성한다고 가정해봅시다.
pod에서 생성한 hi.txt파일은 노드의 /var/lib/kubelet경로에 있습니다.
5. 시나리오 정답 - 임시 볼륨을 잘못 사용하는 상황
임시 볼륨은 노드 디스크를 사용하므로 데이터 크기에 주의해야 합니다. 데이터 크기가 노드 디스크 용량을 초과하면, 노드는 디스크 용량 부족으로 인해 작동 불능 상태가 됩니다. 이로 인해 해당 노드에서 실행 중인 모든 Pod도 정상적으로 실행되지 못하고 먹통이 됩니다.
따라서, 임시 볼륨을 사용할 때는 반드시 데이터 크기를 고려하여 노드 디스크 용량을 초과하지 않도록 주의해야 합니다.
6. 디버깅 - 디스크 용량문제로 발생하는 쿠버네티스 이벤트
노드가 디스크 용량 문제로 비정상적인 상태가 되면, 노드는 쿠버네티스 API 서버에 디스크 관련 비정상 상황을 알립니다. 이 경우 쿠버네티스 이벤트에는 “NodeHasNoDiskPressure”로 기록됩니다. 노드는 부족한 디스크 용량을 확보하기 위해 임시 볼륨을 회수합니다. 임시 볼륨 회수 이벤트가 발생하면 “Attempting to reclaim ephemeral-storage” 메시지가 보입니다.
임시 볼륨을 회수하는 방법은 간단합니다. 임시 볼륨을 사용하는 Pod를 강제 종료(제거)시킵니다.
제거당한 pod 임시 볼륨때문에 제거당했다는 이벤트가 기록됩니다.
The node was low on resource: ephemeral-storage.
쿠버네티스는 임시 볼륨을 회수 노드에 pod를 스케쥴링하지 못하도록합니다. 스케쥴링을 막는 방법은 노드에 taint를 설정합니다. taint 이름은 “node.kubernetes.io/dis-pressure:NoSchedule”입니다.
kubectl describe node
7. 안전하게 임시 볼륨을 사용하도록 정책 설정
임시 볼륨을 안전하게 사용하려면 임시 볼륨 사용량을 제한해야 합니다.
rootfs임시 볼륨은 resources에서 제한합니다.
containers:
- name: busybox
image: busybox
resources:
requests:
ephemeral-storage: "500Mi"
limits:
ephemeral-storage: "1Gi"
emptydir 임시 볼륨은 voluems.emptyDir필드에서 사용 크기를 제한합니다.
volumes:
- name: temp-storage
emptyDir:
sizeLimit: 2Gi
8. 마치며
임시 볼륨 정책을 더 잘 관리하려면 Admission controller을 사용해야 합니다. validate을 설정해서 엄격하게 정책을 관리하거나 mutate를 사용해서 임시 볼륨 제한을 강제 설정할 수 있습니다.
그리고 상황을 관찰할 수 있도록 모니터링 또는 옵저벌리티 시스템을 갖춰야 합니다. 아쉽게도 EKS는 cloudwatch기본 설정으로 볼륨 메트릭이 제한됩니다. 그러므로 agent 등을 추가로 노드에 설치해야 합니다.
참고자료
- 공식문서: https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/
- 공식문서: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#configurations-for-local-ephemeral-storage
- 공식문서: https://kubernetes.io/blog/2024/01/23/kubernetes-separate-image-filesystem/#containerd
- meidum: https://fixit-xdu.medium.com/aws-eks-access-entry-4a7e25ed6c3a
- aws blog: https://aws.amazon.com/ko/blogs/containers/a-deep-dive-into-simplified-amazon-eks-access-management-controls/
- https://medium.com/binome/getting-started-eks-access-entries-6ae5eec82544
- https://securitylabs.datadoghq.com/articles/eks-cluster-access-management-deep-dive/
- 블로그: https://leftasexercise.com/2019/05/23/kubernetes-storage-under-the-hood-part-i-ephemeral-storage/
'전공영역 공부 기록' 카테고리의 다른 글
맥OS 터미널에서 pycharm 명령어 실행 방법 (0) | 2024.06.09 |
---|---|
파이썬 패키지 관리 도구 - poetry (0) | 2024.06.07 |
iterm 설정 (0) | 2024.06.02 |
Amazon Managed Prometheus를 지금 사용하는건 시기상조같다. (0) | 2024.05.26 |
EKS 클러스터 생성 시 부여되는 관리자 권한의 변화와 관리 방법 (0) | 2024.05.19 |