본문 바로가기
Kubernetes

Kubernetes 설치 과정에서 등장하는 용어 정리

by interlude-3 2026. 1. 19.

1. Kubernetes 설치 전 swap을 끄세요 (swapoff)

 
Swap = 가상 메모리

  • RAM(물리 메모리)이 부족할 때 디스크의 일부를 메모리처럼 사용하는 기능
  • RAM이 8GB인데 10GB가 필요한 경우, 2GB를 디스크(Swap)에 임시 저장
# Swap 상태 확인
free -h
              total        used        free      shared  buff/cache   available
Mem:           7.7Gi       2.1Gi       3.2Gi       123Mi       2.4Gi       5.1Gi
Swap:          2.0Gi          0B       2.0Gi  # ← Swap 영역

 
 
일반 서버/PC 환경에서 swap이 유용한 이유

  • RAM 부족 시 디스크를 사용하다보면 속도는 느려질 수는 있지만, 메모리 부족으로 시스템 전체가 다운되는건 막을 수 있을 수 있습니다.


Kubernetes 설치 시 왜 swap을 꺼야 할까요?

  • Kubernetes는 노드 자원을 직접 통제하고 관리할 수 있어야 합니다.
  • Swap은 이 통제권을 OS에게 넘겨버리는 행위이므로 클러스터의 안정성을 위해 꼭 비활성화 해야 합니다.

1. 리소스/성능 예측 불가능

resources:
  requests:
    memory: 1Gi  # 최소 필요 메모리
  limits:
    memory: 2Gi  # 최대 사용 가능 메모리
  • Swap을 키면 Pod가 메모리를 초과 사용해도 죽지 않고 디스크를 쓰면서 버팀
  • Kubernetes는 정상 Pod로 인식, 리소스 사용량 예측 불가능

2. Kubernetes의 리소스 관리 철학

  • 정상적인 리소스 관리 방법 - 메모리가 부족하면, Pod를 즉시 종료(OOMKilled) 시키고 다른 노드에서 재시작
  • 하지만 Swap이 켜져 있으면, 죽지 않고(재스케줄링 되지 않고) 느린 상태로 계속 실행 됨
  • 스케줄링 판단 오류 -> 노드 병목 지점 -> 전체 클러스터 성능 저하

 


2. OverlayFS 모듈을 활성화 하세요

 
OverlayFS = 여러 파일시스템 레이어를 하나로 겹쳐 보이게 만드는 기술

 [최종 보이는 파일시스템]
           ↑
      ┌────┴────┐
     [Upper Layer]          ← 컨테이너 내부 변경사항 (읽기/쓰기)
     [Lower Layer]          ← 이미지 원본 (읽기 전용)
  • Lower Layer
    • 컨테이너 이미지
    • 읽기 전용
  • Upper Layer
    • 컨테이너 실행 중 발생한 변경 사항
    • 읽기/쓰기 가능

=> 컨테이너 안에서는 이 두 Layer가 하나의 파일시스템처럼 보입니다.
 
동작 방식

  • Base Image(Lower Layer)는 수정되지 않음
  • 컨테이너에서 파일을 새로 만들면, Upper Layer 생성됨
  • 기본 이미지 내 파일을 수정하면, Lower를 Upper로 복사 후 Upper 복사본을 수정
  • 컨테이너가 삭제되면, Uppder Layer만 사라지고 Lower Layer는 그대로 유지

=> 이미지 재사용이 쉬워지고, 컨테이너는 가벼워집니다.
 
 
 
Kubernetes에서 OverlayFS가 필요한 이유
 
1. 컨테이너 이미지 생성

  • 컨테이너 이미지는 레이어 단위로 만들어짐 (각 명령어가 하나의 레이어)
  • OverlayFS는 이 레이어들을 하나로 합쳐서 보여주는 역할을 합니다.
FROM ubuntu:20.04          # Lower Layer 1 (100MB)
RUN apt-get update         # Lower Layer 2 (50MB)
RUN apt-get install nginx  # Lower Layer 3 (30MB)
COPY app.py /app/          # Lower Layer 4 (1MB)

 
2. 디스크 공간 절약

  • 같은 이미지를 쓰는 컨테이너가 많아질수록 디스크 효율 차이가 커집니다.
# 같은 Base Image 사용하는 컨테이너 100개
ubuntu:20.04 (100MB) ← 이건 한번만 저장
  ↓
Container 1 (변경사항만 1MB)
Container 2 (변경사항만 2MB)
Container 3 (변경사항만 1MB)
...
  • OverlayFS 없는 경우,
    • 100MB × 컨테이너 수
  • OverlayFS 있는 경우,
    • 100MB + 각 컨테이너의 변경분만 추가

3. 컨테이너 시작 속도

  • OverlayFS를 사용하면 전체 파일 시스템을 복사하지 않아도 됩니다.
  • 컨테이너가 시작하면 레이어 마운트를 수행하여 수백개 컨테이너도 빠르게 기동시킬 수 있습니다.  

 
 
OverlayFS 모듈 활성화란?

  • OverlayFS는 Linux 커널 기능입니다.
  • 커널에 overlay 모듈이 있어야 containerd가 OverlayFS를 사용할 수 있습니다.

일반 서버에서 OverlayFS가 활성화 되어 있지 않은 이유

  • 컨테이너를 안 쓰는 서버가 많고, 기본적으로 불필요한 커널 기능은 로드하지 않음
  • 메모리 절약과 안정성을 위해 OverlayFS 비활성화

컨테이너 런타임(containerd)은 OverlayFS 반드시 필요

  • Docker나 containerd는 OverlayFS 없이 정상 동작 불가
  • /merged 디렉터리 - 컨테이너에서 보는 최종 파일시스템 (Lower+Upper를 overlayfs로 합쳐서 만든 최종 뷰)
  • lower에 있던 파일들, upper에 새로 생긴 파일들, upper가 덮어쓴 파일들 모두 /merged를 통해서 볼 수 있음
  • 컨테이너는 그냥 하나의 파일시스템이라고 인식
# Docker에서 overlay 사용 확인
docker info | grep -i storage
Storage Driver: overlay2

# Overlay 마운트 확인
mount | grep overlay
overlay on /var/lib/docker/overlay2/xxxxx/merged type overlay ...

 

OverlayFS 모듈 확인하고 활성화하기

# 커널 모듈 로드 여부 확인
lsmod | grep overlay

# 없으면 로드
sudo modprobe overlay

# 부팅 시 자동 로드 설정
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

 


3. containerd의 Snapshotter를 확인하고 설정하세요

 
Snapshotter = 컨테이너 이미지의 레이어를 스냅샷 단위로 관리하는 시스템

  • containerd 내부 컴포넌트
  • 컨테이너가 실행되면 snapshotter는 이미지의 레이어와 컨테이너용 쓰기 레이어 경로를 정의하여 OverlayFS에 마운트 명령
  • OverlayFS 커널 모듈이 명령을 받아 실제 레이어 합치는 작업 실행

 

Snapshotter는 언제 필요할까?

 

1. 이미지 Pull 할 때

  • Layer = 스냅샷 체인
  • Layer가 3개인 nginx 이미지를 pull 하는 경우, Snopshotter은 다음과 같은 일을 수행합니다.
# nginx 이미지 pull
docker pull nginx

# Snapshotter가 하는 일
1. Layer 1 다운로드 → 스냅샷 생성
2. Layer 2 다운로드 → 이전 스냅샷 위에 추가
3. Layer 3 다운로드 → 이전 스냅샷 위에 추가

 
2. 컨테이너 실행할 때

  • OverlayFS - Layer를 합쳐서 보여주는 커널 기능
  • Snapshotter - 어떤 Layer를 어떻게 쌓을지 결정하는 관리자
docker run nginx

# Snapshotter가 하는 일:
1. nginx 이미지의 모든 읽기 전용 스냅샷 가져오기
2. 스냅샷 순서대로 쌓기
3. 맨 위에 쓰기 가능한 컨테이너 레이어(스냅샷) 추가
4. 이 구조를 컨테이너 rootfs로 마운트

 
 
 
Containerd의 Snapshotter 종류

  • containerd는 여러 Snapshotter 구현체를 제공합니다.
  • 대부분 기본값으로 'overlayfs'가 선택되지만,  운영 환경에서는 어떤 기술이 사용되는지 직접 확인하고 명시하는 것이 좋습니다.
  • (주의) 커널에 overlayfs 모듈이 없거나 특정 제약에 걸려 native로 fallback 하는 경우, 컨테이너 생성이 느려지거나 디스크 사용량이 급증할 수 있습니다.
# containerd 설정 확인
cat /etc/containerd/config.toml | grep snapshotter
Snapshotter 특징 사용 환경
overlayfs 빠르고 효율적 (사실상 표준) 리눅스 대부분
native 파일 복사 방식 (느림) overlayfs 불가 환경
btrfs Btrfs 스냅샷 기능 활용 Btrfs 사용 시
zfs ZFS 스냅샷 기능 활용 ZFS 사용 시
devmapper Device Mapper 기반 구형 RHEL

 
 
'overlayfs' Snapshotter 스냅샷 구조

  • 각 레이어는 부모 스냅샷을 가리키는 체인 구조로, 이미지 레이어 순서를 그대로 볼 수 있습니다.
# containerd 스냅샷 목록 보기
sudo ctr -n k8s.io snapshots ls

# 예시 출력:
KEY                                                                 PARENT                                              
sha256:abc123...                                                     -
sha256:def456...                                                     sha256:abc123...
sha256:ghi789...                                                     sha256:def456...

 
실제 파일 위치

ls -la /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/

1/
  ├─ fs/          # 실제 파일 데이터
  └─ work/        # Overlay 작업용
2/
  ├─ fs/
  └─ work/
...

# 이 디렉터리들이 OverlayFS의 Lower / Upper 레이어 재료가 됩니다.

 

 

 

Kubernetes에서의 Snapshotter의 역할

  • Pod 실행 시, Snapshotter가 하는 일은 다음과 같습니다.
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: nginx
    image: nginx:latest

---

# Pod 생성 시 Snapshotter가 하는 일

1) Image Pull

   kubelet → containerd → snapshotter

   "nginx 이미지 받아서 스냅샷으로 저장해"
   (각 레이어를 스냅샷으로 관리)


2) Container 생성

   kubelet → containerd → snapshotter
   
   "이 스냅샷들로 rootfs 만들어줘" 
   (읽기 전용 스냅샷 쌓고 쓰기 가능한 컨테이너 스냅샷 추가)
   

# Pod 삭제 시 Snapshotter가 하는 일

   kubelet → containerd → snapshotter
   
   "컨테이너 지워줘"
   (컨테이너 쓰기 레이어만 삭제하고, 이미지 스냅샷은 그대로 유지)

 
Snapshotter 설정 방법

  • overlayfs 기반 snapshotter를 사용하려면 다음과 같이 설정합니다.
# containerd config 파일 생성
sudo containerd config default | sudo tee /etc/containerd/config.toml

# 버전 확인
containerd --version

# 적용
## containerd 2.x
version = 3
[plugins.'io.containerd.cri.v1.images']
  snapshotter = "overlayfs"
  
## containerd 1.x  
version = 2
[plugins."io.containerd.grpc.v1.cri".containerd]
  snapshotter = "overlayfs"
  
# containerd 재시작
sudo systemctl restart containerd

 
 


4. kubelet과 containerd의 cgroup 드라이버를 확인하고 통일하세요

 
Cgroup = Control Group의 약자로, 프로세스의 리소스를 제한·격리·모니터링하는 Linux 커널 기능

  • 프로세스의 CPU, Limit 리소스 제한을 어플리케이션이 아닌 커널 레벨에서 통제
  • 주로 Container의 Resource 제어를 위해서 많이 사용
  • Container가 생성되면 생성된 Container의 Process들을 담당하는 Container Cgroup이 생성

출처 : Cgroup Driver 선택하기 - tech.kakao.com

 
(Container 내부 Process들이 Fork System Call을 통해 Child Process들을 생성해도, 생성된 Child Process들 모두 Container Cgroup에 소속되어 있기 때문에 Container의 Resource를 제어하려면 Container Cgroup을 제어하면 됨)
 
 
Cgroup은 누가 관리할까? 두 가지 Cgroup Driver가 있다
 
1. cgruopfs Driver

  • Cgroup 자체는 커널 기능.
  • 커널 기능은 사용자가 직접 접근할 수 없기 때문에 리눅스는 'cgroupfs'라는 가상 파일시스템 제공
  • 사용자는 이 파일시스템에 값을 읽고 쓰는 방식으로 cgroup 동작을 설정하고 확인할 수 있습니다.
  • cgruopfs 활성화 시 container runtime 또는 kubelet이 직접 cgroupfs를 통해서 Cgroup 제어
  • /sys/fs/cgroup/ 경로를 직접 생성하고 조작, 단순하고 직관적.
/sys/fs/cgroup/memory/docker/<container-id>/
└─ memory.limit_in_bytes

 
2. systemd Driver

  • systemd를 통해서 Cgroup 제어
  • container runtime은 systemd에게 해당 경로에 컨테이너를 넣어달라 요청
  • 컨테이너 생성 시 systemd가 만든 cgroup 디렉터리 아래에 포함
  • systemd는 현재 Kubernetes에서 권장되는 방식으로 OS 프로세스, 서비스, 컨테이너를 하나의 체계로 관리합니다.
kubepods.slice
└─ kubepods-pod<uid>.slice
   └─ container.scope

 
 
여기서 문제가 될수 있는 상황은?
 
1) kubelet과 containerd, 두 컴포넌트가 서로 다른 cgroup 관리 방식을 사용하는 경우 (과거 문제)

  • kubelet과 containerd가 서로 다른 cgroup 트리를 관리
  • 서로 다른 경로를 모니터링 하고 있어 실제 사용량 파악이 불가
  • cgroupfs이나 systemd로 통일

2) systemd가 init 시스템인 환경 (현재 문제)

  • 과거에는 kubelet과 containerd 두 컴포넌트만 동일한 cgroup 드라이버를 사용하면 됐었음
  • 현재 대부분의 리눅스 배포판은 systemd를 init 시스템(PID 1)으로 사용하며 systemd가 시스템 전체의 cgroup 관리자가 됨
  • 이 환경에서 kubelet과 containerd가 cgroupfs 방식으로 직접 /sys/fs/cgroup을 조작하면, systemd가 인지하지 못하는 cgroup이 생성되거나 관리 권한 충돌

그래서 systemd가 init 시스템인 환경에서는 kubelet과 containerd 모두 'systemd' 드라이버로 통일하는 것을 권장합니다.
 
 
 
Kubernetes에서 Cgroup 드라이버 설정하기 (k8s 권장 조합 : systemd + systemd)
 
1) 먼저, 커널이 쓰는 Cgroup 버전 확인

  • cgroup v2는 v1과 달리 모든 리소스를 하나의 트리로 통합
  • cpu/memory/IO 모두 같은 cgroup 노드에서 관리하고, 관리자는 한명만 두어 일관되게 관리할 수 있어야함
  • 즉, cgroup v2는 'systemd'식 관리 모델을 전제로 설계되었음

=> systemd를 권장하는 이유는 systmed가 init 시스템인 이유도 있지만 이처럼 cgroup v2인 경우에도 systmed를 쓰는 것이 좋습니다.

stat -fc %T /sys/fs/cgroup
cgroup2fs

findmnt
mount | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,...)

 
 
2) systemd가 cgroup을 실제로 관리중인지 확인

systemd-cgls --no-pager

 
 
 
3) containerd, kubelet의 cgroup 드라이버를 systemd로 설정
 
containerd

#기본 설정 파일 생성
containerd config default | tee /etc/containerd/config.toml

#확인
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

#false인 경우 true로 수정 후 containerd restart
cat /etc/containerd/config.toml | grep -i systemdcgroup
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

systemctl restart containerd

 
kubelet

# kubeadm에서는 기본값 systemd
--cgroup-driver=systemd

ps aux | grep kubelet | grep cgroup-driver
kubectl describe node | grep -i cgroup

 
 
 


출처
gasida님 k8s-deploy 스터디 자료
Cgroup Driver 선택하기 - tech.kakao.com