Kubernetes 로컬 환경에 Private Registry 배포하고 이미지 Push/Pull 설정하기

2026. 5. 20. 11:06·Devops/Kubernetes

이번 글에서는 Kubernetes 클러스터 내부에 Private Registry를 배포하고, 로컬 Docker 환경과 Kubernetes 노드에서 해당 Registry를 사용할 수 있도록 설정하는 과정을 정리합니다.

 

구성은 다음과 같습니다.

  • Registry 데이터를 저장할 PersistentVolume / PersistentVolumeClaim
  • Registry Pod를 실행할 Deployment
  • 외부에서 Registry에 접근하기 위한 NodePort Service
  • Docker에서 HTTP Registry로 이미지를 push하기 위한 insecure registry 설정
  • Kubernetes 노드의 containerd에서 HTTP Registry 이미지를 pull할 수 있도록 하는 설정

이 예제에서는 NFS 볼륨을 Registry 저장소로 사용하고, registry:3 이미지를 이용해 Private Registry를 배포합니다.


Kubernetes Private Registry 배포

1. Registry Namespace 생성

Registry 관련 리소스를 별도 namespace에서 관리하기 위해 registry namespace를 생성합니다.

kubectl create namespace registry

2. PersistentVolume 생성

Registry에 push한 이미지 데이터는 Pod가 재시작되더라도 유지되어야 합니다.

이를 위해 NFS 기반 PersistentVolume을 생성합니다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: registry-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /nfsvolume
    server: 172.25.46.10

여기서 중요한 점은 PV가 namespace에 속하지 않는 클러스터 범위 리소스라는 점입니다. 따라서 일반적으로 PersistentVolume에는 namespace를 지정하지 않습니다.


3. PersistentVolumeClaim 생성

이제 Registry Pod에서 사용할 PersistentVolumeClaim을 생성합니다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  namespace: registry
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

생성 후 PV와 PVC가 정상적으로 바인딩되었는지 확인합니다.

kubectl get pv,pvc -n registry

PVC의 상태가 Bound이면 정상적으로 연결된 것입니다.


4. Registry Deployment 생성

registry:3 이미지를 사용해 Private Registry를 배포합니다.

Registry는 기본적으로 /var/lib/registry 경로에 이미지 데이터를 저장합니다. 따라서 앞에서 만든 PVC를 해당 경로에 마운트합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: registry
  namespace: registry
  labels:
    app: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: registry
  template:
    metadata:
      labels:
        app: registry
    spec:
      containers:
        - name: registry
          image: registry:3
          ports:
            - containerPort: 5000
          volumeMounts:
            - name: nfs
              mountPath: /var/lib/registry
      volumes:
        - name: nfs
          persistentVolumeClaim:
            claimName: registry-pvc

배포 후 Pod 상태를 확인합니다.

kubectl get pods -n registry

Pod가 Running 상태가 되면 Registry 컨테이너가 정상적으로 실행된 것입니다.


5. NodePort Service 생성

클러스터 외부에서 Registry에 접근할 수 있도록 NodePort 타입의 Service를 생성합니다.

apiVersion: v1
kind: Service
metadata:
  name: registry
  namespace: registry
  labels:
    app: registry
spec:
  type: NodePort
  selector:
    app: registry
  ports:
    - port: 5000
      targetPort: 5000
      nodePort: 32000
      protocol: TCP

Service 생성 후 상태를 확인합니다.

kubectl get svc -n registry

이제 Registry는 다음 주소로 접근할 수 있습니다.

172.25.46.10:32000

여기서 172.25.46.10은 Registry Service에 접근 가능한 Kubernetes 노드 IP이고, 32000은 Service에 지정한 NodePort입니다.


Docker에서 Private Registry로 이미지 Push하기

현재 구성한 Registry는 HTTPS가 아닌 HTTP로 열려 있습니다.

따라서 Docker에서 이미지를 push하려면 Docker Desktop에 insecure registry 설정을 추가해야 합니다.

운영 환경에서는 HTTP Registry보다 TLS가 적용된 HTTPS Registry 구성을 권장합니다.
여기서는 로컬 또는 내부 테스트 환경을 기준으로 HTTP Registry를 사용합니다.


1. Docker Desktop 설정

Docker Desktop을 사용하는 경우 다음 메뉴로 이동합니다.

Settings → Docker Engine

설정 JSON에 다음 항목을 추가합니다.

"insecure-registries": [
  "172.25.46.10:32000"
]

전체 설정 예시는 다음과 같습니다.

{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "insecure-registries": [
    "172.25.46.10:32000"
  ]
}

설정을 저장한 뒤 Docker Desktop을 재시작합니다.


2. 이미지 Push 테스트

예를 들어 nginx 이미지를 Private Registry로 push하려면 다음과 같이 실행합니다.

docker pull nginx
docker tag nginx 172.25.46.10:32000/nginx:latest
docker push 172.25.46.10:32000/nginx:latest

정상적으로 push되면 Registry의 NFS 저장소에 이미지 데이터가 저장됩니다.


Kubernetes 노드에서 Private Registry 이미지 Pull 설정하기

Docker Desktop의 insecure registry 설정은 로컬 Docker CLI에서 이미지를 push하기 위한 설정입니다.

하지만 Kubernetes에서 Pod를 실행할 때 이미지를 pull하는 주체는 Docker Desktop이 아니라 각 Kubernetes 노드의 CRI 런타임입니다. 이 예제에서는 containerd를 사용한다고 가정합니다.

따라서 Kubernetes 노드에서도 HTTP Registry를 사용할 수 있도록 containerd 설정을 추가해야 합니다.


1. containerd registry 설정 경로 지정

각 Kubernetes 노드에서 /etc/containerd/config.toml 파일을 수정합니다.

version = 3

[plugins."io.containerd.cri.v1.images".registry]
  config_path = "/etc/containerd/certs.d"

이 설정은 Registry별 설정 파일을 /etc/containerd/certs.d 아래에서 읽도록 지정합니다.

containerd 버전이나 Kubernetes 배포판에 따라 설정 구조가 다를 수 있습니다.
실제 환경의 /etc/containerd/config.toml 구조를 확인한 뒤 적용하는 것이 좋습니다.


2. Registry별 hosts.toml 생성

Registry 주소와 동일한 이름으로 디렉터리를 생성합니다.

sudo mkdir -p /etc/containerd/certs.d/172.25.46.10:32000

이후 hosts.toml 파일을 생성합니다.

sudo vi /etc/containerd/certs.d/172.25.46.10:32000/hosts.toml

다음 내용을 추가합니다.

server = "http://172.25.46.10:32000"

[host."http://172.25.46.10:32000"]
  capabilities = ["pull", "resolve", "push"]
  skip_verify = true
  plain_http = true

이 설정을 통해 containerd가 172.25.46.10:32000 Registry를 HTTP Registry로 인식하고 이미지를 pull할 수 있게 됩니다.


3. containerd 재시작

설정을 적용하기 위해 각 노드에서 containerd를 재시작합니다.

sudo systemctl restart containerd
sudo systemctl status containerd

재시작 후 Kubernetes 노드 상태도 확인합니다.

kubectl get nodes

노드가 Ready 상태이면 정상입니다.


4. Kubernetes에서 이미지 Pull 테스트

Private Registry에 push한 이미지를 사용하는 테스트 Pod를 생성합니다.

apiVersion: v1
kind: Pod
metadata:
  name: private-registry-test
spec:
  containers:
    - name: nginx
      image: 172.25.46.10:32000/nginx:latest
  restartPolicy: Always

Pod가 정상적으로 실행되는지 확인합니다.

kubectl get pod private-registry-test
kubectl describe pod private-registry-test

ImagePullBackOff 또는 ErrImagePull이 발생하지 않고 Pod가 Running 상태가 되면 설정이 정상적으로 적용된 것입니다.


정리

Kubernetes에 Private Registry를 배포할 때는 단순히 Registry Pod만 실행한다고 끝나지 않습니다.

크게 세 가지 구성이 필요합니다.

1. Registry 저장소 구성

  • NFS 기반 PV/PVC 생성
  • Registry Deployment에 /var/lib/registry 경로로 PVC 마운트
  • Pod가 재시작되어도 이미지 데이터가 유지되도록 구성

2. 외부 접근 구성

  • NodePort Service 생성
  • 172.25.46.10:32000 형태로 Registry 접근
  • Docker CLI에서 해당 주소로 이미지 push

3. HTTP Registry 허용 설정

  • Docker Desktop에서는 insecure-registries 설정
  • Kubernetes 각 노드에서는 containerd의 certs.d/hosts.toml 설정

이번 설정에서 가장 헷갈리기 쉬운 부분은 push하는 환경과 pull하는 환경이 다르다는 점입니다.

Docker Desktop의 설정은 로컬에서 이미지를 push하기 위한 설정이고, Kubernetes 노드의 containerd 설정은 Pod가 이미지를 pull하기 위한 설정입니다.

따라서 HTTP 기반 Private Registry를 사용할 때는 양쪽 설정을 모두 확인해야 합니다.


Reference

  • https://luvstudy.tistory.com/209
  • https://somaz.tistory.com/439

'Devops > Kubernetes' 카테고리의 다른 글

Helm으로 Argo CD 설치 후 Gateway API와 TLS로 접속 구성하기  (0) 2026.05.26
Kubernetes kubelet의 컨테이너 로그 로테이션 설정 정리  (0) 2026.05.25
로컬 Kubernetes에서 MetalLB로 LoadBalancer IP 할당하기  (0) 2026.05.20
Gateway API와 Envoy Gateway로 로컬 Kubernetes 서비스 노출하기  (0) 2026.05.20
Kubernetes에서 NFS 스토리지 구성하기  (0) 2026.05.20
'Devops/Kubernetes' 카테고리의 다른 글
  • Helm으로 Argo CD 설치 후 Gateway API와 TLS로 접속 구성하기
  • Kubernetes kubelet의 컨테이너 로그 로테이션 설정 정리
  • 로컬 Kubernetes에서 MetalLB로 LoadBalancer IP 할당하기
  • Gateway API와 Envoy Gateway로 로컬 Kubernetes 서비스 노출하기
hwara_
hwara_
배움의 기쁨
  • hwara_
    기록 저장소
    hwara_
  • 전체
    오늘
    어제
    • 분류 전체보기 (24)
      • 일상 (1)
        • 회고 (1)
      • 프로젝트 (0)
      • OS (2)
        • Mac (0)
        • Linux (2)
      • 클라우드 (1)
        • AWS (0)
        • CloudFlare (1)
      • Devops (10)
        • Docker (1)
        • Kubernetes (7)
        • Terraform (0)
        • GitHub Actions (2)
      • 알고리즘 (0)
      • Git (2)
      • Database (1)
      • Language (3)
        • Python (3)
      • 환경구성 (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
hwara_
Kubernetes 로컬 환경에 Private Registry 배포하고 이미지 Push/Pull 설정하기
상단으로

티스토리툴바