본문 바로가기

쿠버네티스

pause image 총 정리 - failed to pull image "registry.k8s.io/pause:3.9"

kubernetes를 사용하다가 이런 에러를 만나본 적 있나요?

failed to pull image "registry.k8s.io/pause:3.9"

 

pause 이미지는 kubernetes 운영을 위해서는 반드시 필요한 이미지로, 클러스터 운영에 있어 매우 중요한 역할을 수행합니다. 이번 글에선 pause 이미지가 무엇인지, 어떤 역할을 하는지, image pull 에러 원인과 조치방법에 대해 자세히 알아보겠습니다.

 

1. Kubernetes Pause 이미지란?

Kubernetes에서 가장 작은 단위는 Pod입니다. Pod는 하나 이상의 컨테이너를 묶어 놓은 논리적인 그룹으로, 동일한 네트워크와 스토리지 자원을 공유합니다. 마치 하나의 작은 가상 머신과 같다고 생각하시면 됩니다.

 

여기서 pause 이미지가 등장합니다. Pod가 생성될 때, Kubernetes는 가장 먼저 pause 컨테이너를 Pod 내부에 실행합니다. 이 pause 컨테이너는 매우 단순한 역할을 수행하지만, Pod의 핵심적인 기능을 가능하게 하는 데 필수적입니다.

Pod 의 내부 구조를 통해 pause 이미지를 표현하면 다음과 같습니다.

pod와 pause 이미지 관계
Pod에서의 Pause 이미지 도식화

 

2. pause:3.9 이미지의 주요 역할

pause container는 Pod 생성시 가장먼저 생성되어 Pod 내부의 컨테이너들이 공유할 공통 네임스페이스를 생성합니다. pause container의 주요 역할을 정리하면 다음과 같습니다.

  • Pod 네트워크 네임스페이스(Network Namespace) 유지:
    Kubernetes Pod 내의 모든 컨테이너는 동일한 IP 주소와 포트 공간을 공유합니다. 이는 pause 컨테이너가 Pod의 네트워크 네임스페이스를 먼저 확보하고 유지함으로써 가능해집니다. 다른 컨테이너들은 이 pause 컨테이너의 네트워크 네임스페이스에 조인(join)하여 동일한 네트워크 환경을 공유하게 됩니다. 마치 하나의 방에 여러 사람이 함께 살면서 동일한 우편 주소를 사용하는 것과 같습니다.
  • Pod 프로세스 네임스페이스(PID Namespace) 공유 (Kubernetes 1.20 이상):
    Kubernetes 1.20 버전부터는 Pod 내의 컨테이너들이 프로세스 네임스페이스를 공유할 수 있는 기능이 기본적으로 활성화되었습니다. pause 컨테이너는 이 프로세스 네임스페이스의 기준점이 되어 Pod 내의 컨테이너들이 서로의 프로세스를 볼 수 있고, 시그널을 보낼 수 있도록 합니다. 이는 Pod 내의 여러 컨테이너가 마치 하나의 시스템에서 실행되는 것처럼 상호 작용할 수 있게 해줍니다.
  • Pod 볼륨 마운트 지점 제공:
    Pod 내에서 여러 컨테이너가 공유하는 볼륨(Volume)은 pause 컨테이너를 기준으로 마운트됩니다. 다른 컨테이너들은 이 마운트 지점을 통해 공유 볼륨에 접근할 수 있습니다. 마치 여러 사람이 함께 사용하는 냉장고가 집의 특정 위치에 놓여 모두가 공동으로 사용하는 것과 같습니다.
  • Pod 생명주기 관리의 기준점:
    Kubernetes는 pause 컨테이너의 상태를 기준으로 Pod의 생명주기를 관리합니다. pause 컨테이너가 시작되면 Pod가 생성된 것으로 간주하고, pause 컨테이너가 종료되면 Pod가 종료되는 것으로 판단합니다.

 

3. pause 컨테이너가 필요한 이유

만약 첫 번째로 실행되는 애플리케이션 컨테이너가 Pod의 네트워크와 프로세스 네임스페이스를 관리하도록 설계한다면, 해당 애플리케이션 컨테이너가 실패하거나 재시작될 때마다 Pod의 네트워크 환경과 프로세스 공간이 변경될 수 있습니다. 이는 Pod 내의 다른 컨테이너들에게 예기치 않은 문제를 일으킬 수 있습니다.

 

pause 컨테이너는 매우 가볍고 안정적인 프로세스(대부분 단순히 무한 루프를 실행하는 형태)로 구성되어 있습니다. 이 컨테이너는 Pod의 핵심 인프라 역할을 안정적으로 수행하며, 애플리케이션 컨테이너의 생명주기와는 독립적으로 존재합니다. 따라서 애플리케이션 컨테이너가 실패하거나 재시작되더라도 Pod의 기본적인 네트워크 및 프로세스 환경은 유지될 수 있습니다.

 

pause 컨테이너 구성 예시 - pause 상태로 무한루프

command: ["/pause"]

 

4. pause:3.9 이미지가 삭제되는 이유

일반적으로 pause:3.9 이미지는 Kubernetes 클러스터의 각 노드에 존재하며, 새로운 Pod가 생성될 때마다 사용됩니다. 하지만 드물게 이 이미지가 노드에서 삭제되는 경우가 발생할 수 있습니다. 이미지가 삭제되더라도 신규 이미지를 pull 받으면 되지만, 네트워크 이슈가 발생하거나 pause이미지가 있는 레지스트리에 접근할 수 없다면 image pull 에 실패하여 큰 문제가 발생할 수 있습니다. pause 이미지 삭제가 발생할 수 있는 원인과 대처 방안에 대해 정리해보았습니다.

 

(1) 노드 디스크 공간 부족 (Node Disk Space Issues)

  • 원인:
    Kubernetes 노드의 디스크 공간이 부족해지면, kubelet은 디스크 공간을 확보하기 위해 사용하지 않거나 오래된 이미지를 자동으로 삭제하는 이미지 가비지 컬렉션(Image Garbage Collection)을 수행할 수 있습니다. pause:3.9 이미지가 오랫동안 사용되지 않았다고 판단되거나, 다른 더 큰 이미지들로 인해 디스크 공간이 심각하게 부족해 진다면 GC에 의해 삭제될 수 있습니다.
  • 확인 방법:
    kubelet 로그 확인 : 이미지 가비지 컬렉션 관련 메시지를 확인하여 pause:3.9 이미지가 삭제된 이유를 파악합니다.
journalctl -u kubelet | grep -i 'pause'

 

(2) 노드 드레인 또는 종료

  • 원인:
    노드를 유지보수하거나 클러스터에서 제거하기 위해 노드 드레인(drain) 작업을 수행하거나 노드를 종료하는 경우, kubelet은 해당 노드에서 실행 중인 Pod들을 다른 노드로 안전하게 이동시키려고 시도합니다. 이 과정에서 노드의 리소스를 정리할 수 있으며, 경우에 따라 이미지가 삭제될 수 있습니다.
  • 확인 방법:
      kubectl get events --field-selector involvedObject.kind=Node,involvedObject.name=<문제 발생 노드 이름>
  • 이벤트 확인:
    Kubernetes 이벤트(Events)를 확인하여 노드 드레인 또는 종료 작업이 수행되었는지 확인합니다.

 

(3) 사용자의 수동 삭제

  • 원인:

사용자가 실수로 또는 의도적으로 docker rmi 또는 crictl rmi 명령어를 사용하여 노드에서 pause:3.9 이미지를 삭제했을 수 있습니다.

 

  • 확인 방법 :
    해당 노드의 명령어 실행 기록을 확인하여 이미지 삭제 명령어가 실행되었는지 확인합니다.

 

(5) 컨테이너 런타임 문제 (Container Runtime Issues)

  • 원인:
    Docker 또는 containerd와 같은 컨테이너 런타임 자체에 오류가 발생하여 이미지가 손상되거나 예기치 않게 삭제될 수 있습니다.
  • 확인 방법:
    Docker 또는 containerd의 로그를 확인하여 오류 메시지를 찾습니다.
# docker log 확인
/var/log/daemon.log 
/var/log/docker.log

# containerd log 확인
/var/log/containerd/containerd.log

 

5. pause 이미지 삭제 방지를 위한 방안:

(1) kubelet이 사용하는 pause 이미지의 "프리로딩"

워커 노드에 pause 이미지를 미리 수동으로 pull해 두고, 절대 삭제되지 않도록 "사용 중인 상태"로 유지합니다.

# 수동 pull

ctr images pull registry.k8s.io/pause:3.9

이 이미지가 컨테이너 runtime에 등록되어 있으면 GC 대상에서 즉시 삭제되지는 않습니다. 단, 여전히 "사용되지 않음"으로 판단되면 시간이 지나면 삭제될 수 있습니다.

 

(2) pause 이미지가 항상 사용되도록 DaemonSet으로 고정 참조하기 

pause 이미지를 사용하는 Dummy Pod를 하나 만들어 계속해서 해당 이미지를 사용하는 상태로 유지하는 방법입니다.

  • 예시 YAML:
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pause-keeper
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: pause-keeper
  template:
    metadata:
      labels:
        app: pause-keeper
    spec:
      containers:
        - name: pause
          image: registry.k8s.io/pause:3.9
          command: ["/pause"]

이렇게 하면 모든 워커 노드에 pause:3.9 이미지를 참조하는 Pod가 하나씩 항상 존재하게 되어, kubelet이 GC 시에 "이 이미지는 사용 중"으로 인식하여 삭제하지 않습니다.

(3) GC 설정 자체를 완화하기 (보조 전략)

kubelet의 이미지 GC 설정을 조정해서 너무 자주 삭제되지 않도록 제한할 수 있습니다.

  • kubelet 설정 예시 (/var/lib/kubelet/config.yaml):
imageGCHighThresholdPercent: 85     # 디스크 사용량이 85% 넘으면 GC 시작
imageGCLowThresholdPercent: 80      # GC 후 80%까지 줄임

 

단, threshold 값을 너무 낮게 하면 자주 GC가 발생하므로 완화할 수 있습니다.
이 방식은 pause 이미지뿐 아니라 전체 이미지 삭제 빈도를 조절하는 것이므로, 전체 디스크 관리 정책에 영향을 미치므로 주의가 필요하며 초보자에게는 권장하지 않습니다.

 

(4) Private Registry 사용 시에는 이미지 Pull 실패 대비 

만약 private registry를 통해 pause 이미지를 제공하고 있다면 다음 내용을 참고해 보세요.

  • 이미지 imagePullPolicy: IfNotPresent 설정
  • 인증 문제로 Pull 실패하는 경우 대비하여 imagePullSecrets 명확히 구성
  • Node 간 레지스트리 접근 가능 여부 주기 점검

 

6. 결론

이번 블로그 포스팅을 통해 Kubernetes의 핵심 구성 요소 중 하나인 pause:3.9 이미지에 대해 자세히 알아보았습니다. pause 컨테이너는 Pod의 네트워크 및 프로세스 환경을 유지하고, 공유 볼륨의 마운트 지점을 제공하며, Pod 생명주기 관리의 기준점이 되는 중요한 역할을 수행합니다.

드물게 pause:3.9 이미지가 노드에서 삭제되는 경우가 발생할 수 있지만, 디스크 공간 부족, kubelet의 가비지 컬렉션 정책, 노드 드레인 또는 종료, kubelet 설정 변경, 사용자의 수동 삭제, 컨테이너 런타임 문제, 네트워크 문제 등 다양한 원인을 파악하고 적절한 해결 방안을 적용하면 문제를 해결할 수 있습니다.