이번 글에서는 Kubernetes에서 “이미지 보안”을 다룰 때 가장 먼저 알아야 하는 두 가지를 정리합니다.
- 이미지 이름이 실제로 무엇을 의미하는지(어디서 가져오는지)
- Private Registry 이미지를 Pod가 안전하게 Pull하도록 설정하는 방법
1) image: nginx는 정확히 어디서 뭘 가져오는 걸까?
Pod 스펙에서 흔히 이렇게 씁니다.
containers:
- name: web
image: nginx
겉보기엔 단순하지만, nginx는 Docker 이미지 명명 규칙에 의해 “풀 네임”으로 해석됩니다.
이미지 이름의 정식 형태
일반적으로 컨테이너 이미지는 아래 구조로 이해하면 됩니다.
[registryhost[:port]/][namespace/]repository[:tag][@digest]
예를 들어:
nginxlibrary/nginx:1.27docker.io/library/nginx:1.27ghcr.io/my-org/my-app:1.0.3registry.mycorp.com/platform/api@sha256:...
nginx가 풀 네임으로 바뀌는 규칙
image: nginx처럼 registry/namespace를 생략하면 대부분의 런타임이 다음처럼 간주합니다.
- registry:
docker.io(Docker Hub) - namespace:
library(공식 이미지가 모이는 기본 네임스페이스/계정) - tag:
latest(tag를 생략했을 때 기본값)
즉,
nginx ≈ docker.io/library/nginx:latest
library는 Docker Hub의 “공식 이미지(Official Images)”가 위치한 기본 네임스페이스로 이해하면 됩니다.
2) Registry(레지스트리)란?
레지스트리는 “이미지를 저장/배포하는 저장소 서버”입니다.
- 이미지를 빌드/업데이트하면 레지스트리에 push
- 다른 시스템(노드)이 배포하려면 레지스트리에서 pull
대표적으로:
- Docker Hub:
docker.io - GitHub Container Registry:
ghcr.io - Google 계열:
gcr.io/ Artifact Registry(*.pkg.dev) - 클라우드 프라이빗 레지스트리: AWS ECR, Azure ACR 등
- 사내 레지스트리: Harbor, Nexus 등
공개 이미지(누구나 pull 가능)도 있고, 비공개 이미지(인증 필요)도 있습니다.
3) Private Registry 이미지를 Kubernetes에서 쓰려면?
로컬 PC에서는 보통 이렇게 합니다.
docker login registry.mycorp.com
docker pull registry.mycorp.com/team/app:1.0.0
하지만 Kubernetes에서는 “Pod가 뜨는 워커 노드에서” 이미지 pull이 발생합니다.
즉, 노드의 런타임(containerd/docker)이 레지스트리 인증정보를 알아야 합니다.
Kubernetes는 이 문제를 Secret + imagePullSecrets로 해결합니다.
4) 방법 1: Docker Registry 타입 Secret 만들기 (가장 흔함)
4.1 Secret 생성 (명령형)
kubectl create secret docker-registry regcred \
--docker-server=registry.mycorp.com \
--docker-username=myuser \
--docker-password='mypassword' \
--docker-email=myuser@mycorp.com \
-n default
docker-registry타입 Secret은 내부적으로 레지스트리 인증정보를 저장하는 전용 형태입니다.- 결과 Secret은 보통
kubernetes.io/dockerconfigjson타입으로 만들어집니다.
확인:
kubectl get secret regcred -n default
kubectl describe secret regcred -n default
실무 팁: 비밀번호를 CLI 인자로 직접 넣으면 쉘 히스토리에 남을 수 있습니다. 가능하면 안전한 입력 방식(환경변수/CI secret/파일)을 사용하세요.
5) Pod에 imagePullSecrets 지정하기
Pod 스펙에 imagePullSecrets를 추가합니다.
apiVersion: v1
kind: Pod
metadata:
name: private-nginx
namespace: default
spec:
containers:
- name: nginx
image: registry.mycorp.com/library/nginx:1.27
imagePullSecrets:
- name: regcred
이제 Pod가 생성되면, kubelet이 API 서버에서 regcred를 받아 런타임에 전달하고, 런타임이 해당 자격증명으로 이미지를 pull합니다.
6) 방법 2: ServiceAccount에 imagePullSecrets를 붙여 “기본 적용”하기
Pod마다 imagePullSecrets를 반복해서 넣기 싫다면, ServiceAccount에 연결할 수 있습니다.
6.1 ServiceAccount에 regcred 연결
kubectl patch serviceaccount default \
-p '{"imagePullSecrets":[{"name":"regcred"}]}' \
-n default
이렇게 하면 default SA를 사용하는 Pod들은 별도 설정 없이도 해당 Secret을 사용해 이미지를 pull할 수 있습니다.
또는 전용 SA를 만들어서 특정 워크로드에만 적용하는 게 더 안전합니다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: default
imagePullSecrets:
- name: regcred
그리고 Deployment(또는 Pod)에:
spec:
template:
spec:
serviceAccountName: app-sa
7) 트러블슈팅: ImagePullBackOff / ErrImagePull가 뜰 때
가장 먼저 Pod 이벤트를 보세요.
kubectl describe pod <pod-name> -n <ns>
자주 나오는 원인:
- 레지스트리 주소 오타 (
registry.mycorp.comvsregistry.mycorp.co) - 이미지 경로/태그 오타 (
repo:tag) - Secret이 다른 네임스페이스에 있음
- Secret은 네임스페이스 리소스라 Pod와 같은 네임스페이스에 있어야 합니다.
- 권한 부족(해당 계정이 repo pull 권한 없음)
- TLS/인증서 이슈(사내 레지스트리 자체 서명 인증서 등)
8) “이미지 보안” 관점에서 꼭 같이 챙길 베스트 프랙티스
이 강의는 “인증을 통해 private image pull”에 초점이지만, 실무에서 이미지 보안은 여기까지 같이 묶어 생각하는 경우가 많습니다.
8.1 latest 태그 지양
latest는 내용이 바뀔 수 있어 재현성이 떨어집니다.
- 권장: 명시적 버전 태그(
:1.0.3) 또는 digest pinning(@sha256:...)
8.2 최소 권한 원칙
- 레지스트리 계정은 pull 전용으로
- Secret은 필요한 네임스페이스/SA에만
8.3 스캔/서명/정책
- 이미지 취약점 스캔(레지스트리 스캔/CI 스캔)
- 이미지 서명(cosign 등) + Admission 정책(OPA/Gatekeeper, Kyverno)로 “서명된 이미지만 허용”
- 허용된 레지스트리만 사용하도록 정책화
요약
image: nginx는 보통docker.io/library/nginx:latest로 해석된다.- Private Registry 이미지를 쓰려면 “노드가 pull할 때 쓸 인증정보”가 필요하다.
- Kubernetes는 이를
Secret(docker-registry)+imagePullSecrets로 해결한다. - 반복을 줄이려면 ServiceAccount에
imagePullSecrets를 붙이는 방식이 유용하다. - 실무에서는
latest지양, 최소권한, 스캔/서명/정책까지 같이 묶어서 이미지 보안을 완성한다.
Practice Test: https://uklabs.kodekloud.com/topic/practice-test-image-security-2/
'CKA' 카테고리의 다른 글
| Security - NetworkPolicy (0) | 2026.01.02 |
|---|---|
| Security - 도커 보안 기초 + 쿠버네티스의 Security Context (0) | 2026.01.02 |
| Security - Service Account (0) | 2026.01.02 |
| Security - ClusterRole / ClusterRoleBinding (0) | 2026.01.02 |
| Security - Authorization(RBAC) (0) | 2026.01.01 |