본문 바로가기
Development

모든 워커노드에서 특정 컨테이너 이미지 삭제 방법

by 토마스.dev 2024. 11. 6.
반응형

쿠버네티스에 이미지를 배포할때 imagePullPolicy를 보통 IfNotPresent로 하게 된다. 이때 만약 부득이한 상황으로 이미지 태그를 업데이트하지 않고 다시 빌드해서 레지스트리에 올렸을 때, 정상적으로 이미지가 재배포되지 않는다. 개발용으로 빌드할때도 이런 경우를 마주할수 있는데, 모든 워커노드에서 다운로드된 특정 컨테이너 이미지를 찾아서 삭제해주는 방법을 공유한다.

이 방식은 Containerd를 런타임으로 사용하는 쿠버네티스 1.24 버전부터 사용가능하다.

먼저, crictl (Containerd ctl) 을 가지고 이미지를 만들어야 한다.

FROM alpine:latest
 
ARG CRICTL_VERSION="v1.31.1"
 
# https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.31.1/crictl-v1.31.1-linux-amd64.tar.gz
RUN wget https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz && \
    tar zxvf crictl-${CRICTL_VERSION}-linux-amd64.tar.gz -C /usr/local/bin
 
ENTRYPOINT crictl

해당 이미지를 가진 Job 매니페스트는 다음과 같다.

apiVersion: batch/v1
kind: Job
metadata:
  name: {{JOB_NAME}}
spec:
  parallelism: {{PARALLELISM}}
  completions: {{PARALLELISM}}
  template:
    metadata:
      labels:
        job-name: {{JOB_NAME}}
    spec:
      nodeSelector:
        node-role.kubernetes.io/worker: "true"
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  job-name: {{JOB_NAME}}
              topologyKey: "kubernetes.io/hostname"
      containers:
        - name: delete-image         
          image: crictl:1.31.1
          imagePullPolicy: Always
          command:
            - sh
            - -c
            - |
              # List images and delete the specified image
              crictl images
              crictl -t 300s rmi {{IMAGE_NAME}} || true
          env:
            - name: CONTAINER_RUNTIME_ENDPOINT
              value: unix:///run/containerd/containerd.sock
            - name: IMAGE_SERVICE_ENDPOINT
              value: unix:///run/containerd/containerd.sock
          securityContext:
            privileged: true
          volumeMounts:
          - name: containerd
            mountPath: /run/containerd/containerd.sock
      restartPolicy: Never
      volumes:
        - name: containerd
          hostPath:
            path: /run/containerd/containerd.sock
            type: Socket

해당 Job을 돌려주는 쉘스크립트는 다음과 같다.

반응형
#!/bin/bash
 
# Exit immediately if a command exits with a non-zero status
set -e
 
# Function to display usage
usage() {
  echo "Usage: $0 -n|--name <image-name>"
  echo
  echo "Options:"
  echo "  -n, --name    Name of the image to delete"
  echo "  -h, --help    Display this help message"
  exit 1
}
 
# Parse arguments
IMAGE_NAME=""
while [[ $# -gt 0 ]]; do
  key="$1"
  case $key in
    -n|--name)
      IMAGE_NAME="$2"
      shift # past argument
      shift # past value
      ;;
    -h|--help)
      usage
      ;;
    *)    # unknown option
      echo "Unknown option: $1"
      usage
      ;;
  esac
done
 
if [[ -z "$IMAGE_NAME" ]]; then
  echo "Error: Image name is required."
  usage
fi
 
# Get the number of worker nodes with label node-role.kubernetes.io/worker=true
NODE_COUNT=$(kubectl get nodes -l node-role.kubernetes.io/worker=true --no-headers | wc -l)
 
if [[ "$NODE_COUNT" -eq 0 ]]; then
  echo "No worker nodes with label 'node-role.kubernetes.io/worker=true' found in the cluster."
  exit 1
fi
 
echo "Found $NODE_COUNT worker nodes."
 
# Generate a unique job name
JOB_NAME="cleanup-image-job-$(date +%s)"
 
# Generate the Job manifest by replacing placeholders
sed "s/{{JOB_NAME}}/$JOB_NAME/g; s/{{PARALLELISM}}/$NODE_COUNT/g; s|{{IMAGE_NAME}}|$IMAGE_NAME|g" job.yaml.tpl | kubectl apply -f -
 
echo "Job '$JOB_NAME' has been created to delete image '$IMAGE_NAME' across all worker nodes."
echo "Delete the job after finished"

사용방법은 다음과 같다.

$ bash ./cleanup-image.sh -n {이미지이름(태그포함)}

그러면 워커노드별로 파드가 하나씩 뜨면서 노드에 저정된 해당 이미지를 삭제한다.

반응형

'Development' 카테고리의 다른 글

데이터 엔지니어링 로드맵  (0) 2024.11.17
devops problem solving(이슈해결 역량 기르기 팁)  (0) 2024.11.14
GPT와 개발  (0) 2024.11.02
Jupyterhub with spark on k8s 설치 삽질기 & 팁  (0) 2024.10.26
Prometheus TSDB 분석  (0) 2024.01.28