[Kubernetes] ๐ containerd OverlayFS ์ค๋ ์ท ๋์คํฌ ์ ์ ์ปจํ ์ด๋ ์ถ์ ํ๊ธฐ
containerd OverlayFS ์ค๋ ์ท ๋๋ ํ ๋ฆฌ๊ฐ ๋์คํฌ๋ฅผ ๊ณผ๋ํ๊ฒ ์ ์ ํ ๋, Snapshot ID์์ Container ID, Pod Name๊น์ง ์ถ์ ํ๋ ๋ฐฉ๋ฒ์ ๋จ๊ณ๋ณ๋ก ์ ๋ฆฌํ์ต๋๋ค.
์ด ๊ธ์์๋ /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/ ํ์์ ํน์ ์ซ์ ํด๋๊ฐ ์์ญ GB๋ฅผ ์ฐจ์งํ๋ ์ํฉ์์, ์ด๋ค Pod๊ฐ ์์ธ์ธ์ง ์ฐพ์๋ด๋ ๊ณผ์ ์ ๋ค๋ฃน๋๋ค. Snapshot ID โ Container ID โ Pod Name ์์๋ก ์ญ์ถ์ ํ๋ฉฐ, crictl๊ณผ kubectl์ ์ค์ฌ์ผ๋ก ์ค๋ฌด์์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ๋ช
๋ น์ด๋ฅผ ์ ๋ฆฌํ์ต๋๋ค.
๐จ ๋ฌธ์ ์ํฉ: ๋์คํฌ ์ฉ๋ ๊ฒฝ๊ณ
์๋ฒ์ DiskPressure ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์์ธ์ ์ถ์ ํ๊ธฐ ์ํด du ๋ช
๋ น์ด๋ก ์ฉ๋์ ํ์ธํฉ๋๋ค.
1
2
3
4
# ์ต์์ ๋๋ ํ ๋ฆฌ๋ณ ์ฉ๋ ํ์ธ
du -sh /var/lib/containerd/*
# ๋๋ ์ปค์คํ
๋ฐ์ดํฐ ๊ฒฝ๋ก๋ผ๋ฉด
du -sh /appdata/cri/*
๊ณ์ ํ๊ณ ๋ค๋ค ๋ณด๋ฉด ์๋์ ๊ฐ์ ๊ฒฝ๋ก์์ ํน์ ์ซ์ ํด๋๊ฐ ์์ญ GB๋ฅผ ์ฐจ์งํ๋ ๊ฒ์ ๋ฐ๊ฒฌํฉ๋๋ค.
1
2
du -sh /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/* \
| sort -rh | head -20
1
2
3
38G /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/11773
2.1G /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/11201
...
์ด์ 11773์ด๋ผ๋ ์ค๋
์ท ํด๋๊ฐ ์ด๋ ์ปจํ
์ด๋ยทPod์ ๊ฒ์ธ์ง ์ถ์ ํด์ผ ํฉ๋๋ค.
๐งฉ OverlayFS์ Snapshotter ๊ฐ๋ ์ดํด
์ถ์ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ค๋ฉด containerd์ ๋ ์ด์ด ๊ตฌ์กฐ๋ฅผ ๋จผ์ ํ์ ํด์ผ ํฉ๋๋ค.
| ๋๋ ํ ๋ฆฌ | ์ญํ |
|---|---|
lowerdir | ์ฝ๊ธฐ ์ ์ฉ ์ด๋ฏธ์ง ๋ ์ด์ด (Image Layer) |
upperdir | ์ปจํ ์ด๋์ ์ฐ๊ธฐ ๋ ์ด์ด (Write Layer) |
workdir | OverlayFS ๋ด๋ถ ์์ ์์ ๋๋ ํ ๋ฆฌ |
merged | lowerdir + upperdir๋ฅผ ํฉ์ณ ์ปจํ ์ด๋์ ๋ณด์ด๋ ์ต์ข ๋ทฐ |
containerd์ Snapshotter๋ ๊ฐ ์ปจํ
์ด๋ ๋ ์ด์ด๋ฅผ ์ซ์ ID๋ก ๊ด๋ฆฌํฉ๋๋ค. ์ปจํ
์ด๋๊ฐ ์คํ๋๋ฉด ํด๋น ์ปจํ
์ด๋ ์ ์ฉ upperdir๊ฐ ์ค๋
์ท ํด๋ ์์ ์์ฑ๋๋ฉฐ, ์ด ๊ณต๊ฐ์ ๋ก๊ทธยท์์ ํ์ผ ๋ฑ์ด ์์
๋๋ค. ๋ก๊ทธ๊ฐ ํญ๋ฐํ๊ฑฐ๋ ์์ ํ์ผ์ด ๋์๋๋ฉด ์ค๋
์ท ํด๋๊ฐ ๋ฌดํ์ ์ปค์ง๊ฒ ๋ฉ๋๋ค.
Tip:
snapshots/<ID>/fs๋ ์ปจํ ์ด๋์ ์ค์ ํ์ผ์์คํ (upperdir)์ ๋๋ค. ์ด ์์ ํ์ผ์ด ์์ด๋ฉด ํด๋น ์ค๋ ์ท์ ํฌ๊ธฐ๊ฐ ์ฆ๊ฐํฉ๋๋ค.
๐ ๏ธ 1๋จ๊ณ: mount๋ก ์ค๋ ์ท ๋ง์ดํธ ์ ๋ณด ํ์ธ
๊ฐ์ฅ ๋จผ์ ์๋ํ ์ ์๋ ๋ฐฉ๋ฒ์ mount ๋ช
๋ น์ด๋ก ํด๋น ์ค๋
์ท ID๊ฐ ์ด๋ค ์ปจํ
์ด๋์ ๋ง์ดํธ๋์ด ์๋์ง ํ์ธํ๋ ๊ฒ์
๋๋ค.
1
2
SNAPSHOT_ID=11773
mount | grep "snapshots/${SNAPSHOT_ID}"
๊ฒฐ๊ณผ ์์:
1
2
3
overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/a3f2b1c0d4e5.../rootfs
type overlay (rw,relatime,lowerdir=.../11770/fs:.../11769/fs,
upperdir=.../11773/fs,workdir=.../11773/work)
upperdir ๊ฒฝ๋ก ์์ ์ปจํ
์ด๋์ Task ID(ํด์๊ฐ)๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. ์ด ํด์๋ฅผ ๋ฉ๋ชจํฉ๋๋ค.
โ ๏ธ ์ปจํ ์ด๋๊ฐ ์ด๋ฏธ ์ข ๋ฃ๋ ๊ฒฝ์ฐ mount ๊ฒฐ๊ณผ์ ๋ํ๋์ง ์์ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ 2๋จ๊ณ๋ก ๋์ด๊ฐ์ธ์.
๐ 2๋จ๊ณ: Task ID๋ก ์ปจํ ์ด๋ ์ฐพ๊ธฐ
mount ๊ฒฐ๊ณผ์์ ์ป์ Task ํด์๋ก ์ปจํ ์ด๋๋ฅผ ์กฐํํฉ๋๋ค.
1
2
TASK_HASH=a3f2b1c0d4e5...
ctr -n k8s.io c ls | grep ${TASK_HASH}
๋๋ crictl์ ์ฌ์ฉํฉ๋๋ค.
1
crictl ps -a | grep ${TASK_HASH}
๐ 3๋จ๊ณ: crictl inspect๋ก Snapshot ID ์ญ์ถ์
mount ๊ฒฐ๊ณผ ์์ด ์ค๋
์ท ID๋ง ์๊ณ ์์ ๋, crictl inspect์ snapshotKey ํ๋๋ฅผ ์ด์ฉํฉ๋๋ค.
1
2
3
4
5
6
7
8
# ๋ชจ๋ ์ปจํ
์ด๋๋ฅผ ์ํํ๋ฉด์ ์ค๋
์ท ID ๊ฒ์
crictl ps -a -q | while read CONTAINER_ID; do
RESULT=$(crictl inspect ${CONTAINER_ID} 2>/dev/null | grep -i "11773")
if [ -n "${RESULT}" ]; then
echo "Found in container: ${CONTAINER_ID}"
crictl inspect ${CONTAINER_ID} | grep -E '"name"|"image"|snapshotKey'
fi
done
๋๋ jq๊ฐ ์ค์น๋ ํ๊ฒฝ์์๋ ๋ ์ ํํ๊ฒ ์ถ์ถํ ์ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
SNAPSHOT_ID=11773
crictl ps -a -q | while read CID; do
SNAP=$(crictl inspect ${CID} 2>/dev/null \
| jq -r '.info.runtimeSpec.annotations["io.kubernetes.cri.sandbox-id"] // empty' 2>/dev/null)
ROOTFS=$(crictl inspect ${CID} 2>/dev/null \
| jq -r '.info.config.image.image // empty' 2>/dev/null)
if crictl inspect ${CID} 2>/dev/null | grep -q "snapshots/${SNAPSHOT_ID}"; then
echo "Container ID : ${CID}"
echo "Image : ${ROOTFS}"
fi
done
๐๏ธ 4๋จ๊ณ: Container ID โ Pod Name ์ฐ๊ฒฐ
์ปจํ ์ด๋ ID๋ฅผ ์ฐพ์๋ค๋ฉด, ํด๋น ์ปจํ ์ด๋๊ฐ ์ํ Pod๋ฅผ ํ์ธํฉ๋๋ค.
1
2
3
4
5
6
7
CONTAINER_ID=a3f2b1c0d4e5
# Pod ID(์๋๋ฐ์ค ID) ํ์ธ
crictl inspect ${CONTAINER_ID} | grep -i sandbox
# Pod ์์ธ ์ ๋ณด ํ์ธ
crictl inspectp <POD_SANDBOX_ID>
๋๋ crictl ps ์ถ๋ ฅ์์ ์ง์ Pod ์ด๋ฆ์ ํ์ธํ ์ ์์ต๋๋ค.
1
crictl ps -a --output=table | grep ${CONTAINER_ID}
์ถ๋ ฅ ์์:
1
2
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
a3f2b1c0d4e5 ... 2h ago Running app 0 b4c3d2e1 my-app-7d6f9b-xkpqr
Pod ์ด๋ฆ์ ํ์ธํ๋ค๋ฉด kubectl๋ก ์์ธ ์ ๋ณด๋ฅผ ์กฐํํฉ๋๋ค.
1
2
kubectl get pod my-app-7d6f9b-xkpqr -n <namespace> -o wide
kubectl describe pod my-app-7d6f9b-xkpqr -n <namespace>
๐ฌ 5๋จ๊ณ: ์ค๋ ์ท ๋ด๋ถ ํ์ผ ํ์ธ
์ด๋ค ํ์ผ์ด ์ฉ๋์ ์ ์ ํ๋์ง ์ง์ ํ์ธํฉ๋๋ค.
1
2
3
4
5
6
# ์ค๋
์ท์ upperdir(์ค์ ์ปจํ
์ด๋ ์ฐ๊ธฐ ๋ ์ด์ด) ํ์
ls -lh /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/11773/fs/
# ํ์ ๋๋ ํ ๋ฆฌ๋ณ ์ฉ๋ ํ์ธ
du -sh /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/11773/fs/* \
| sort -rh | head -20
๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋ค์ ๊ฒฝ๋ก์์ ํ์ผ์ด ํญ์ฆํฉ๋๋ค.
1
2
3
/var/log/ โ ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ ๋์
/tmp/ โ ์์ ํ์ผ ๋์
/var/cache/ โ ์บ์ ํ์ผ ๋ฏธ์ ๋ฆฌ
โ ํด๊ฒฐ ๋ฐฉ๋ฒ
๋ฒ์ธ Pod ์ฌ์์ ๋๋ ์ญ์
1
2
3
4
5
# Pod ์ฌ์์ (Deployment ๋ฑ ์์ ์ค๋ธ์ ํธ๊ฐ ์์ ๊ฒฝ์ฐ)
kubectl rollout restart deployment/<deployment-name> -n <namespace>
# Pod ์ง์ ์ญ์ (ReplicaSet์ด ์ Pod๋ฅผ ์์ฑ)
kubectl delete pod my-app-7d6f9b-xkpqr -n <namespace>
โ ๏ธ
rm -rf snapshots/11773๊ฐ์ ์ง์ ์ญ์ ๋ ์ ๋ ํ์ง ๋ง์ธ์. containerd ๋ฐํ์ ๋ฉํ๋ฐ์ดํฐ์ ๋ถ์ผ์น๊ฐ ๋ฐ์ํด ๋ ธ๋๊ฐ ๋ถ์์ ํด์ง ์ ์์ต๋๋ค.
๋ฏธ์ฌ์ฉ ์ด๋ฏธ์งยท์ปจํ ์ด๋ ์ ๋ฆฌ
1
2
3
4
5
6
7
8
9
10
11
12
# ์ข
๋ฃ๋ ์ปจํ
์ด๋ ์กฐํ ๋ฐ ์ญ์
crictl ps -a --state exited
crictl rm $(crictl ps -a --state exited -q)
# ๋ฏธ์ฌ์ฉ ์ด๋ฏธ์ง ์ ๋ฆฌ
crictl rmi --prune
# ctr๋ฅผ ์ด์ฉํ ์ ๋ฆฌ (24์๊ฐ ์ด์ ๋ฏธ์ฌ์ฉ)
ctr -n k8s.io images prune --all-unused --older-than 24h
# ์ค๋
์ท ์ ๋ฆฌ
ctr -n k8s.io snapshots prune
์ ํ๋ฆฌ์ผ์ด์ ๋ก๊ทธ ๋กํ ์ด์ ์ค์
์ปจํ ์ด๋ ๋ด๋ถ์์ ๋ก๊ทธ๊ฐ ์์ธ๋ค๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ก๊ทธ ๋กํ ์ด์ ์ ์ค์ ํฉ๋๋ค.
1
2
3
4
5
6
7
8
# Deployment์ ์ปจํ
์ด๋ ๋ก๊ทธ ํฌ๊ธฐ ์ ํ ์ถ๊ฐ
spec:
containers:
- name: app
# ...
resources:
limits:
ephemeral-storage: "2Gi" # ์์ ์คํ ๋ฆฌ์ง ์ํ ์ค์
๐ก๏ธ ์๋ฐฉ: Kubelet GC ๋ฐ containerd GC ์ค์
Kubelet ์ด๋ฏธ์ง GC ์ค์
/var/lib/kubelet/config.yaml์ ๋ค์ ํญ๋ชฉ์ ์ถ๊ฐํฉ๋๋ค.
1
2
imageGCHighThresholdPercent: 85 # 85% ์ด๊ณผ ์ GC ์์
imageGCLowThresholdPercent: 80 # 80%๊น์ง ์ ๋ฆฌ
containerd ์ฃผ๊ธฐ์ GC ์ค์
/etc/containerd/config.toml์ GC ์ค์ผ์ค๋ฌ๋ฅผ ์ค์ ํฉ๋๋ค.
1
2
3
4
5
6
[plugins."io.containerd.gc.v1.scheduler"]
pause_threshold = 0.02
deletion_threshold = 0
mutation_threshold = 100
schedule_delay = "0s"
startup_delay = "100ms"
๋์คํฌ ์ฌ์ฉ๋ ๋ชจ๋ํฐ๋ง
Prometheus๋ฅผ ์ฌ์ฉํ๋ค๋ฉด node_filesystem_avail_bytes ๋ฉํธ๋ฆญ์ ์๋์ ์ค์ ํ์ฌ DiskPressure ์ด์ ์ ์กฐ์น๋ฅผ ์ทจํ ์ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
# PrometheusRule ์์
- alert: NodeDiskPressureWarning
expr: |
node_filesystem_avail_bytes{mountpoint="/var/lib/containerd"} /
node_filesystem_size_bytes{mountpoint="/var/lib/containerd"} < 0.15
for: 5m
annotations:
summary: "containerd ๋์คํฌ ์ฌ์ ๊ณต๊ฐ 15% ๋ฏธ๋ง"
โ ์์ฃผ ๋ฌป๋ ์ง๋ฌธ
Q. ์ค๋ ์ท ํด๋๋ฅผ ์ง์ rm -rf ํด๋ ๋๋์?
์ ๋ฉ๋๋ค. containerd๋ ๋ด๋ถ bolt DB(meta.db)์ ์ค๋
์ท ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ํ์ผ๋ง ์ญ์ ํ๋ฉด DB์ ๋ถ์ผ์น๊ฐ ๋ฐ์ํด containerd๊ฐ ์ค์๋ํ๊ฑฐ๋ ๋
ธ๋๊ฐ NotReady ์ํ๊ฐ ๋ ์ ์์ต๋๋ค. ๋ฐ๋์ crictl rm, ctr snapshots rm ๋ฑ ๋ฐํ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ธ์.
Q. mount | grep ์ผ๋ก ์๋ฌด๊ฒ๋ ์ ๋์ฌ ๋๋์?
์ปจํ
์ด๋๊ฐ ์ด๋ฏธ ์ข
๋ฃ๋ ๊ฒฝ์ฐ์
๋๋ค. crictl ps -a๋ก ์ข
๋ฃ๋ ์ปจํ
์ด๋๊น์ง ํฌํจํ์ฌ ํ์ธํ๊ฑฐ๋, ctr -n k8s.io snapshots info <snapshot-key>๋ก ์ค๋
์ท ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ง์ ์กฐํํด ๋ณด์ธ์.
Q. ctr์ crictl ์ค ์ด๋ค ๊ฒ์ ์จ์ผ ํ๋์?
Kubernetes ํ๊ฒฝ์์๋ crictl์ ๊ถ์ฅํฉ๋๋ค. crictl์ CRI(Container Runtime Interface)๋ฅผ ํตํด Kubernetes Podยท์ปจํ ์ด๋ ์ ๋ณด์ ์ฐ๋๋๋ฏ๋ก, Pod ์ด๋ฆ ๋ฑ ์์ ์ ๋ณด๋ฅผ ์ป๊ธฐ ์ฝ์ต๋๋ค. ctr๋ containerd ๋ค์ดํฐ๋ธ CLI๋ก, Kubernetes ๋ฉํ๋ฐ์ดํฐ ์์ด ๋ ๋ก์ฐ๋ ๋ฒจ ์ ๊ทผ์ด ํ์ํ ๋ ์ฌ์ฉํฉ๋๋ค.
Q. ephemeral-storage ์ ํ์ ๊ฑธ๋ฉด Pod๊ฐ Evict๋์ง ์๋์?
๋ง์ต๋๋ค. ์ค์ ํ ์ํ์ ์ด๊ณผํ๋ฉด kubelet์ด ํด๋น Pod๋ฅผ evictํฉ๋๋ค. ์ด๋ ๋จ์ผ Pod์ ๋ฌด์ ํ ๋์คํฌ ์ ์ ๋ก ๋ ธ๋ ์ ์ฒด๊ฐ DiskPressure์ ๋น ์ง๋ ๊ฒ์ ๋ง์์ฃผ๋ ์์ ์ฅ์น์ ๋๋ค. limits๋ ๋๋ํ๊ฒ, requests๋ ์ค์ ์ฌ์ฉ๋ ๊ธฐ์ค์ผ๋ก ์ค์ ํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
๐ ์ฐธ๊ณ
- Find who own overlayfs snapshots/NN - containerd/containerd Discussion #10053
- How to Shrink the io.containerd.snapshotter.v1.overlayfs Folder in Kubernetes
- Debugging Kubernetes nodes with crictl - Kubernetes Docs
- containerd Snapshotters Explained: Overlayfs, Native, and More
- Overlay Filesystem and Its Use in Container Runtime
- Large containerd Snapshot Directories and Cleanup Assistance - kubespray Issue #10195