컨테이너 이미지

컨테이너 이미지 (Images)

컨테이너 이미지는 애플리케이션과 모든 소프트웨어 의존성을 캡슐화하는 바이너리 데이터를 나타내요. 컨테이너 이미지는 독립적으로 실행될 수 있고 런타임 환경에 대해 매우 잘 정의된 가정을 하는 실행 가능한 소프트웨어 번들입니다.

보통 애플리케이션의 컨테이너 이미지를 만들어 레지스트리에 푸시한 뒤 파드에서 참조해요. 이 페이지는 컨테이너 이미지 개념의 개요를 제공합니다.

쿠버네티스 릴리스(예: v1.37, 최신 minor 릴리스)의 컨테이너 이미지를 찾고 있다면 Download Kubernetes를 방문하세요.

출처: 문서

본문

이미지 이름

컨테이너 이미지는 보통 pause, example/mycontainer, kube-apiserver 같은 이름이 주어집니다. 이미지에는 레지스트리 호스트 이름도 포함될 수 있고(예: fictional.registry.example/imagename), 포트 번호도 포함될 수 있어요(예: fictional.registry.example:10443/imagename).

레지스트리 호스트 이름을 지정하지 않으면 쿠버네티스는 Docker 공개 레지스트리를 의미한다고 가정합니다. 컨테이너 런타임 구성에서 기본 이미지 레지스트리를 설정해 이 동작을 바꿀 수 있습니다.

이미지 이름 부분 뒤에 _태그_나 _다이제스트_를 추가할 수 있어요(dockerpodman 같은 명령에서 사용하는 것과 같은 방식). 태그는 같은 계열 이미지의 서로 다른 버전을 식별하게 해줍니다. 다이제스트는 이미지의 특정 버전에 대한 고유한 식별자입니다. 다이제스트는 이미지 내용의 해시이며 불변입니다. 태그는 다른 이미지를 가리키도록 이동할 수 있지만 다이제스트는 고정되어 있습니다.

이미지 태그는 소문자와 대문자, 숫자, 밑줄(_), 마침표(.), 대시(-)로 구성됩니다. 태그는 최대 128자까지 가능하며 [a-zA-Z0-9_][a-zA-Z0-9._-]{0,127} 정규식 패턴을 따라야 합니다. 이에 대해 더 읽고 검증 정규식을 찾으려면 OCI Distribution Specification을 참고하세요. 태그를 지정하지 않으면 쿠버네티스는 latest 태그를 의미한다고 가정합니다.

이미지 다이제스트는 해시 알고리즘(sha256 같은)과 해시 값으로 구성됩니다. 예를 들어: sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07. 다이제스트 형식에 대한 더 많은 정보는 OCI Image Specification에서 찾을 수 있습니다.

쿠버네티스가 사용할 수 있는 몇 가지 이미지 이름 예시는 다음과 같습니다:

  • busybox — 태그나 다이제스트가 없는 이미지 이름만. 쿠버네티스는 Docker 공개 레지스트리와 latest 태그를 사용한다. docker.io/library/busybox:latest와 같다.
  • busybox:1.32.0 — 태그가 있는 이미지 이름. 쿠버네티스는 Docker 공개 레지스트리를 사용한다. docker.io/library/busybox:1.32.0와 같다.
  • registry.k8s.io/pause:latest — 커스텀 레지스트리와 latest 태그가 있는 이미지 이름.
  • registry.k8s.io/pause:3.5 — 커스텀 레지스트리와 non-latest 태그가 있는 이미지 이름.
  • registry.k8s.io/pause@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 — 다이제스트가 있는 이미지 이름.
  • registry.k8s.io/pause:3.5@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 — 태그와 다이제스트가 있는 이미지 이름. 가져오기에는 다이제스트만 사용된다.

이미지 업데이트

처음으로 Deployment, StatefulSet, Pod 또는 PodTemplate을 포함하는 다른 오브젝트를 만들고 가져오기 정책이 명시적으로 지정되지 않았다면, 기본적으로 그 Pod의 모든 컨테이너의 가져오기 정책이 IfNotPresent로 설정됩니다. 이 정책은 이미지가 이미 존재하면 kubelet이 가져오기를 건너뛰게 합니다.

이미지 가져오기 정책

컨테이너의 imagePullPolicy와 이미지의 태그는 모두 kubelet이 지정된 이미지를 언제 가져오려(다운로드) 시도하는지에 영향을 줍니다.

다음은 imagePullPolicy에 설정할 수 있는 값과 그 값들의 효과 목록입니다:

IfNotPresent : 이미지가 로컬에 이미 없을 때만 가져온다.

Always : kubelet이 컨테이너를 시작할 때마다 kubelet이 컨테이너 런타임에 이미지 가져오기를 요청한다. 컨테이너 런타임은 레지스트리에 접촉해 이미지 태그나 이름을 다이제스트로 해석하고, 로컬에 아직 캐시되지 않은 레이어를 다운로드한다. 모든 레이어가 이미 있으면 컨테이너 런타임은 다시 다운로드하지 않고 캐시된 이미지를 사용한다. kubelet 자체는 이미지가 로컬에 캐시되었는지 확인하지 않으며, 항상 컨테이너 런타임에 위임한다.

Never : kubelet은 이미지를 가져오려 하지 않는다. 이미지가 어쨌든 로컬에 이미 있으면 kubelet은 컨테이너를 시작하려 시도하고, 그렇지 않으면 시작이 실패한다. 자세한 내용은 미리 가져온 이미지를 참고하라.

컨테이너 런타임의 캐싱 의미론은 레지스트리에 안정적으로 접근할 수 있는 한 imagePullPolicy: Always조차 효율적으로 만듭니다. 컨테이너 런타임은 이미지 레이어가 이미 노드에 존재함을 알아차려 다시 다운로드할 필요가 없게 할 수 있습니다.

프로덕션에서 컨테이너를 배포할 때는 :latest 태그 사용을 피해야 해요. 어떤 버전의 이미지가 실행 중인지 추적하기 더 어렵고 제대로 롤백하기 더 어렵기 때문입니다.

대신 v1.42.0 같은 의미 있는 태그 및/또는 다이제스트를 지정하세요.

파드가 항상 같은 버전의 컨테이너 이미지를 사용하도록 하려면 이미지의 다이제스트를 지정할 수 있어요. <image-name>:<tag><image-name>@<digest>로 바꾸세요(예: image@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2).

이미지 태그를 사용할 때 이미지 레지스트리가 그 태그가 나타내는 코드를 변경한다면, 옛 코드와 새 코드를 실행하는 파드가 섞일 수 있습니다. 이미지 다이제스트는 이미지의 특정 버전을 고유하게 식별하므로, 쿠버네티스는 그 이미지 이름과 다이제스트가 지정된 컨테이너를 시작할 때마다 같은 코드를 실행합니다. 다이제스트로 이미지를 지정하면 실행하는 코드를 고정해, 레지스트리의 변경으로 버전이 섞이지 않게 합니다.

생성 시 파드(및 PodTemplate)를 변경해 실행 중인 워크로드가 태그가 아닌 다이제스트를 기반으로 정의되게 하는 서드파티 어드미션 컨트롤러가 있습니다. 레지스트리에서 무슨 태그 변경이 있어도 전체 워크로드가 같은 코드를 실행하게 하려면 유용할 수 있습니다.

기본 이미지 가져오기 정책

(여러분 또는 컨트롤러가) API 서버에 새 Pod를 제출하면 특정 조건이 충족될 때 클러스터가 imagePullPolicy 필드를 설정합니다:

  • imagePullPolicy 필드를 생략하고 컨테이너 이미지에 다이제스트를 지정하면, imagePullPolicy는 자동으로 IfNotPresent로 설정된다.
  • imagePullPolicy 필드를 생략하고 컨테이너 이미지의 태그가 :latest이면, imagePullPolicy는 자동으로 Always로 설정된다.
  • imagePullPolicy 필드를 생략하고 컨테이너 이미지에 태그를 지정하지 않으면, imagePullPolicy는 자동으로 Always로 설정된다.
  • imagePullPolicy 필드를 생략하고 :latest가 아닌 태그를 컨테이너 이미지에 지정하면, imagePullPolicy는 자동으로 IfNotPresent로 설정된다.

컨테이너의 imagePullPolicy 값은 오브젝트가 처음 _생성_될 때 항상 설정되며, 이미지의 태그나 다이제스트가 나중에 변경돼도 업데이트되지 않습니다.

예를 들어 태그가 :latest아닌 이미지로 Deployment를 만들고, 나중에 그 Deployment의 이미지를 :latest 태그로 업데이트해도 imagePullPolicy 필드는 Always로 바뀌지 않습니다. 초기 생성 후에는 어떤 오브젝트의 가져오기 정책도 수동으로 변경해야 합니다.

필수 이미지 가져오기

항상 가져오기를 강제하고 싶다면 다음 중 하나를 할 수 있어요:

  • 컨테이너의 imagePullPolicyAlways로 설정한다.
  • imagePullPolicy를 생략하고 이미지로 사용할 :latest 태그를 사용한다. 쿠버네티스는 Pod를 제출할 때 정책을 Always로 설정한다.
  • imagePullPolicy와 사용할 이미지의 태그를 모두 생략한다. 쿠버네티스는 Pod를 제출할 때 정책을 Always로 설정한다.
  • AlwaysPullImages 어드미션 컨트롤러를 활성화한다.

ImagePullBackOff

kubelet이 컨테이너 런타임을 사용해 파드의 컨테이너 생성을 시작할 때, 컨테이너가 ImagePullBackOff 때문에 Waiting 상태일 수 있습니다.

ImagePullBackOff 상태는 쿠버네티스가 컨테이너 이미지를 가져오지 못해(잘못된 이미지 이름, imagePullSecret 없이 프라이빗 레지스트리에서 가져오는 것 같은 이유) 컨테이너가 시작되지 못했음을 의미합니다. BackOff 부분은 쿠버네티스가 점점 증가하는 백오프 지연으로 이미지 가져오기를 계속 시도할 것임을 나타냅니다.

쿠버네티스는 컴파일된 한도인 300초(5분)에 도달할 때까지 각 시도 사이의 지연을 높입니다.

런타임 클래스별 이미지 가져오기

쿠버네티스는 파드의 RuntimeClass에 기반한 이미지 가져오기 수행에 대한 알파 지원을 포함합니다.

RuntimeClassInImageCriApi 피처 게이트를 활성화하면 kubelet은 이미지 이름과 런타임 핸들러의 튜플로 컨테이너 이미지를 참조하고, 단순히 이미지 이름이나 다이제스트만으로 참조하지 않습니다. 컨테이너 런타임은 선택된 런타임 핸들러에 기반해 동작을 적응시킬 수 있습니다. 런타임 클래스에 기반한 이미지 가져오기는 Windows Hyper-V 컨테이너 같은 VM 기반 컨테이너에 유용합니다.

직렬 및 병렬 이미지 가져오기

기본적으로 kubelet은 이미지를 직렬로 가져와요. 즉 kubelet은 한 번에 이미지 서비스에 이미지 가져오기 요청을 하나만 보냅니다. 다른 이미지 가져오기 요청은 처리 중인 것이 완료될 때까지 기다려야 합니다.

노드는 이미지 가져오기 결정을 격리해서 내립니다. 직렬화된 이미지 가져오기를 사용하더라도 서로 다른 두 노드가 같은 이미지를 병렬로 가져올 수 있습니다.

병렬 이미지 가져오기를 활성화하려면 kubelet 구성에서 serializeImagePulls 필드를 false로 설정할 수 있어요. serializeImagePulls를 false로 설정하면 이미지 가져오기 요청이 즉시 이미지 서비스로 보내지고, 여러 이미지가 동시에 가져와집니다.

병렬 이미지 가져오기를 활성화할 때 컨테이너 런타임의 이미지 서비스가 병렬 이미지 가져오기를 처리할 수 있는지 확인하세요.

kubelet은 하나의 파드를 대신해 여러 이미지를 병렬로 가져오지 않습니다. 예를 들어 init 컨테이너와 애플리케이션 컨테이너가 있는 파드가 있다면, 두 컨테이너의 이미지 가져오기는 병렬화되지 않습니다. 그러나 서로 다른 이미지를 사용하는 파드가 두 개 있고 병렬 이미지 가져오기가 활성화되어 있다면, kubelet은 두 서로 다른 파드를 대신해 이미지를 병렬로 가져옵니다.

최대 병렬 이미지 가져오기

serializeImagePulls가 false로 설정되면 kubelet은 동시에 가져오는 이미지 수에 기본 제한이 없어요. 병렬 이미지 가져오기 수를 제한하려면 kubelet 구성에서 maxParallelImagePulls 필드를 설정할 수 있습니다. maxParallelImagePulls를 _n_으로 설정하면 최대 _n_개의 이미지가 동시에 가져와질 수 있고, _n_을 넘는 이미지 가져오기는 진행 중인 이미지 가져오기가 하나라도 완료될 때까지 기다려야 합니다.

병렬 이미지 가져오기 수를 제한하면 병렬 이미지 가져오기가 활성화되었을 때 이미지 가져오기가 너무 많은 네트워크 대역폭이나 디스크 I/O를 소비하는 것을 방지합니다.

maxParallelImagePulls를 1보다 크거나 같은 양수로 설정할 수 있어요. maxParallelImagePulls를 2 이상으로 설정하면 serializeImagePulls를 false로 설정해야 합니다. 잘못된 maxParallelImagePulls 설정으로 kubelet은 시작에 실패할 것입니다.

이미지 인덱스가 있는 다중 아키텍처 이미지

컨테이너 레지스트리는 바이너리 이미지를 제공할 뿐 아니라 컨테이너 이미지 인덱스를 제공할 수 있어요. 이미지 인덱스는 컨테이너의 아키텍처별 버전에 대한 여러 이미지 매니페스트를 가리킬 수 있습니다. 아이디어는 이미지 이름(예: pause, example/mycontainer, kube-apiserver)을 가지게 하고, 서로 다른 시스템이 사용하는 머신 아키텍처에 맞는 올바른 바이너리 이미지를 가져오게 하는 것입니다.

쿠버네티스 프로젝트는 보통 릴리스용 컨테이너 이미지를 이름에 -$(ARCH) 접미사를 포함해 만듭니다. 하위 호환성을 위해 이전 이미지를 접미사로 생성합니다. 예를 들어 pause라는 이미지는 지원되는 모든 아키텍처의 매니페스트를 포함하는 다중 아키텍처 이미지인 반면, pause-amd64는 이전 구성이나 접미사가 있는 하드코딩된 이미지 이름이 있는 YAML 파일을 위한 하위 호환 버전입니다.

프라이빗 레지스트리 사용

프라이빗 레지스트리는 이미지를 발견 및/또는 가져오기 위해 인증을 요구할 수 있어요. 자격 증명은 여러 방식으로 제공될 수 있습니다:

이 옵션들에 대해 아래에서 더 자세히 설명합니다.

파드에 imagePullSecrets 지정

이것은 프라이빗 레지스트리의 이미지를 기반으로 컨테이너를 실행하는 권장 방법입니다.

쿠버네티스는 파드에 컨테이너 이미지 레지스트리 키 지정을 지원해요. 모든 imagePullSecrets는 파드와 같은 네임스페이스에 존재하는 Secrets이어야 합니다. 이 Secrets는 kubernetes.io/dockercfg 또는 kubernetes.io/dockerconfigjson 유형이어야 합니다.

노드를 프라이빗 레지스트리에 인증하도록 구성

자격 증명 설정의 구체적 지침은 선택한 컨테이너 런타임과 레지스트리에 따라 달라져요. 가장 정확한 정보는 솔루션의 문서를 참고해야 합니다.

프라이빗 컨테이너 이미지 레지스트리 구성 예시는 프라이빗 레지스트리에서 이미지 가져오기 작업을 참고하세요. 그 예시는 Docker Hub의 프라이빗 레지스트리를 사용합니다.

인증된 이미지 가져오기를 위한 kubelet credential provider

컨테이너 이미지의 레지스트리 자격 증명을 동적으로 가져오도록 kubelet이 플러그인 바이너리를 호출하도록 구성할 수 있어요. 이는 프라이빗 레지스트리의 자격 증명을 가져오는 가장 견고하고 다용도인 방법이지만, 활성화하려면 kubelet 레벨 구성도 필요합니다.

이 기법은 프라이빗 레지스트리에 호스팅된 컨테이너 이미지가 필요한 정적 파드를 실행할 때 특히 유용할 수 있습니다. 정적 파드의 스펙에서 프라이빗 레지스트리 자격 증명을 제공하기 위해 ConfigMap이나 Secret을 사용하는 것은 불가능합니다. 정적 파드는_ 자격 증명이 스펙에서 다른 API 리소스에 대한 참조를 가질 수 없기_ 때문입니다.

자세한 내용은 kubelet 이미지 credential provider 구성을 참고하세요.

config.json 해석

config.json의 해석은 원래 Docker 구현과 쿠버네티스 해석 사이에 차이가 있어요. Docker에서 auths 키는 루트 URL만 지정할 수 있는 반면, 쿠버네티스는 glob URL과 접두사 일치 경로를 모두 허용합니다. 유일한 제한은 glob 패턴(*)이 각 서브도메인에 대해 점(.)을 포함해야 한다는 것입니다. 일치된 서브도메인 수는 glob 패턴(*.) 수와 같아야 합니다. 예를 들어:

  • *.kubernetes.iokubernetes.io와는 일치하지 않지만 abc.kubernetes.io와는 일치한다.
  • *.*.kubernetes.ioabc.kubernetes.io와는 일치하지 않지만 abc.def.kubernetes.io와는 일치한다.
  • prefix.*.ioprefix.kubernetes.io와 일치한다.
  • *-good.kubernetes.ioprefix-good.kubernetes.io와 일치한다.

즉 다음과 같은 config.json은 유효합니다:

{
    "auths": {
        "my-registry.example/images": { "auth": "…" },
        "*.my-registry.example/images": { "auth": "…" }
    }
}

다음 컨테이너 이미지 이름은 유효한 패턴마다 CRI 컨테이너 런타임에 자격 증명을 전달합니다. 예를 들어:

  • my-registry.example/images
  • my-registry.example/images/my-image
  • my-registry.example/images/another-image
  • sub.my-registry.example/images/my-image

그러나 이 컨테이너 이미지 이름들은 일치하지 않습니다:

  • a.sub.my-registry.example/images/my-image
  • a.b.sub.my-registry.example/images/my-image

kubelet은 발견된 각 자격 증명에 대해 이미지 가져오기를 순차적으로 수행합니다. 즉 서로 다른 경로에 대한 config.json의 여러 항목도 가능합니다:

{
    "auths": {
        "my-registry.example/images": {
            "auth": "…"
        },
        "my-registry.example/images/subpath": {
            "auth": "…"
        }
    }
}

컨테이너가 가져올 이미지 my-registry.example/images/subpath/my-image를 지정하면, kubelet은 둘 중 하나가 실패할 경우 두 인증 소스를 모두 사용해 다운로드하려 시도합니다.

미리 가져온 이미지

이 접근 방식은 노드 구성을 제어할 수 있을 때 적합해요. 클라우드 제공자가 노드를 관리하고 자동으로 교체한다면 안정적으로 동작하지 않습니다.

기본적으로 kubelet은 각 이미지를 지정된 레지스트리에서 가져오려 시도해요. 그러나 컨테이너의 imagePullPolicy 속성이 IfNotPresent 또는 Never로 설정되면 로컬 이미지가 (각각 우선적으로 또는 배타적으로) 사용됩니다.

레지스트리 인증의 대체 수단으로 미리 가져온 이미지에 의존하려면, 클러스터의 모든 노드가 같은 미리 가져온 이미지를 가져야 합니다.

이는 속도를 위해 특정 이미지를 미리 로드하거나, 프라이빗 레지스트리에 인증하는 대안으로 사용할 수 있습니다.

kubelet credential provider의 사용과 유사하게, 미리 가져온 이미지는 프라이빗 레지스트리에 호스팅된 이미지에 의존하는 정적 파드를 시작하는 데도 적합합니다.

미리 가져온 이미지에 대한 접근은 이미지 가져오기 자격 증명 검증에 따라 인가될 수 있습니다.

이미지 가져오기 자격 증명 검증 보장

클러스터에 KubeletEnsureSecretPulledImages 피처 게이트가 활성화되어 있으면, 쿠버네티스는 가져오기에 자격 증명이 필요한 모든 이미지에 대해, 그 이미지가 이미 노드에 있어도 이미지 자격 증명을 검증합니다. 이 검증은 Pod 요청에 있는 이미지 중 제공된 자격 증명으로 성공적으로 가져오지 않은 이미지는 레지스트리에서 다시 가져와야 함을 보장합니다. 추가로, 이전에 성공적인 이미지 가져오기를 초래한 같은 자격 증명을 재사용하는 이미지 가져오기는 레지스트리에서 다시 가져올 필요 없이, (이미지가 로컬에서 사용 가능하다면) 레지스트리에 접근하지 않고 로컬에서 검증됩니다. 이는 Kubelet 구성imagePullCredentialsVerificationPolicy 필드로 제어됩니다.

이 구성은 이미지가 이미 노드에 있을 때 이미지 가져오기 자격 증명을 언제 검증해야 하는지 제어합니다:

  • NeverVerify: 이 피처 게이트가 비활성화된 것과 같은 동작을 모방한다. 이미지가 로컬에 있으면 이미지 가져오기 자격 증명을 검증하지 않는다.
  • NeverVerifyPreloadedImages: kubelet 밖에서 가져온 이미지는 검증되지 않지만, 다른 모든 이미지는 자격 증명이 검증된다. 이것이 기본 동작이다.
  • NeverVerifyAllowListedImages: kubelet 밖에서 가져오고 kubelet 구성에 지정된 preloadedImagesVerificationAllowlist에 언급된 이미지는 검증되지 않는다.
  • AlwaysVerify: 모든 이미지는 사용되기 전에 자격 증명이 검증된다.

이 검증은 미리 가져온 이미지, 노드 차원 시크릿으로 가져온 이미지, 파드 레벨 시크릿으로 가져온 이미지에 적용됩니다.

자격 증명 회전의 경우, 이전에 이미지를 가져오는 데 사용된 자격 증명은 레지스트리에 접근하지 않고도 계속 검증을 통과합니다. 새로 또는 회전된 자격 증명은 이미지를 레지스트리에서 다시 가져와야 합니다.

KubeletEnsureSecretPulledImages를 처음 활성화할 때

KubeletEnsureSecretPulledImages가 처음 활성화될 때, kubelet 업그레이드나 명시적 기능 활성화로든, 그 시점에 kubelet이 어떤 이미지에든 접근할 수 있다면 그것들은 모두 미리 가져온 것으로 간주됩니다. 이는 이 경우 kubelet이 이미지가 가져와진 기록을 가지고 있지 않기 때문입니다. kubelet은 어떤 이미지든 처음 가져와질 때만 이미지 가져오기 기록을 만들기 시작할 수 있습니다.

이것이 우려된다면 기능을 활성화하기 전에 미리 가져온 것으로 간주되어서는 안 되는 모든 이미지를 노드에서 정리하는 것이 좋습니다.

이미지 가져오기 기록을 담고 있는 디렉토리를 제거하면 kubelet 재시작에도 같은 효과가 있으며, 특히 컨테이너 런타임이 현재 노드에 캐시한 이미지는 모두 미리 가져온 것으로 간주됩니다.

Docker 구성으로 Secret 만들기

레지스트리에 인증하기 위한 사용자 이름, 레지스트리 비밀번호, 클라이언트 이메일 주소 및 그 호스트 이름을 알아야 해요. 다음 명령을 실행하고 자리 표시자를 적절한 값으로 바꿔주세요:

kubectl create secret docker-registry <name> \
  --docker-server=<docker-registry-server> \
  --docker-username=<docker-user> \
  --docker-password=<docker-password> \
  --docker-email=<docker-email>

이미 Docker 자격 증명 파일이 있다면 위 명령 대신 자격 증명 파일을 쿠버네티스 Secret으로 가져올 수 있어요. 기존 Docker 자격 증명에 기반한 Secret 만들기에서 설정 방법을 설명합니다.

이것은 여러 프라이빗 컨테이너 레지스트리를 사용할 때 특히 유용한데, kubectl create secret docker-registry는 단일 프라이빗 레지스트리에서만 작동하는 Secret을 만들기 때문입니다.

파드는 자신의 네임스페이스의 이미지 가져오기 시크릿만 참조할 수 있으므로, 이 과정은 네임스페이스마다 한 번씩 수행해야 합니다.

파드에서 imagePullSecrets 참조

이제 파드 정의에 imagePullSecrets 섹션을 추가해 그 시크릿을 참조하는 파드를 만들 수 있어요. imagePullSecrets 배열의 각 항목은 같은 네임스페이스의 Secret 하나만 참조할 수 있습니다.

예를 들어:

cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: awesomeapps
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey
EOF

cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF

이것은 프라이빗 레지스트리를 사용하는 각 파드에 대해 수행되어야 해요.

그러나 ServiceAccount 리소스에 imagePullSecrets 섹션을 지정하면 이 과정을 자동화할 수 있습니다. 자세한 지침은 서비스 어카운트에 ImagePullSecrets 추가를 참고하세요.

이것을 노드마다의 .docker/config.json과 함께 사용할 수 있습니다. 자격 증명이 병합됩니다.

사용 사례

프라이빗 레지스트리를 구성하는 여러 솔루션이 있습니다. 여기 몇 가지 일반적인 사용 사례와 제안된 솔루션이 있습니다.

  1. 비소유권(예: 오픈 소스) 이미지만 실행하는 클러스터. 이미지를 숨길 필요 없음.
    • 공개 레지스트리의 공개 이미지 사용
      • 구성 필요 없음.
      • 일부 클라우드 제공자는 공개 이미지를 자동으로 캐시하거나 미러링해 가용성을 높이고 가져오는 시간을 줄인다.
  2. 회사 밖 사람에게는 숨겨야 하지만 모든 클러스터 사용자에게는 보여야 하는 일부 소유권 이미지를 실행하는 클러스터.
    • 호스팅된 프라이빗 레지스트리 사용
      • 프라이빗 레지스트리에 접근해야 하는 노드에 수동 구성이 필요할 수 있다.
    • 또는 방화벽 뒤에서 공개 읽기 접근으로 내부 프라이빗 레지스트리를 실행.
      • 쿠버네티스 구성 필요 없음.
    • 이미지 접근을 제어하는 호스팅된 컨테이너 이미지 레지스트리 서비스 사용
      • 수동 노드 구성보다 Node 자동 스케일링과 더 잘 동작한다.
    • 또는 노드 구성을 바꾸기 불편한 클러스터에서 imagePullSecrets 사용.
  3. 일부는 더 엄격한 접근 제어가 필요한 소유권 이미지가 있는 클러스터.
    • AlwaysPullImages 어드미션 컨트롤러가 활성화되어 있는지 확인. 그렇지 않으면 모든 파드가 잠재적으로 모든 이미지에 접근한다.
    • 민감한 데이터를 이미지에 패키징하는 대신 Secret 리소스로 옮긴다.
  4. 각 테넌트마다 자체 프라이빗 레지스트리가 필요한 멀티 테넌트 클러스터.
    • AlwaysPullImages 어드미션 컨트롤러가 활성화되어 있는지 확인. 그렇지 않으면 모든 테넌트의 모든 파드가 잠재적으로 모든 이미지에 접근한다.
    • 인증이 필요한 프라이빗 레지스트리 실행.
    • 각 테넌트에 레지스트리 자격 증명을 생성해 Secret에 저장하고, 그 Secret을 각 테넌트 네임스페이스에 전파.
    • 그러면 테넌트가 그 Secret을 각 네임스페이스의 imagePullSecrets에 추가.

여러 레지스트리에 접근해야 한다면 레지스트리마다 Secret을 하나씩 만들 수 있어요.

레거시 내장 kubelet credential provider

쿠버네티스의 이전 버전에서 kubelet은 클라우드 제공자 자격 증명과 직접 통합되어 있었어요. 이는 이미지 레지스트리의 자격 증명을 동적으로 가져오는 능력을 제공했습니다.

kubelet credential provider 통합의 내장 구현이 세 가지 있었습니다: ACR(Azure Container Registry), ECR(Elastic Container Registry), GCR(Google Container Registry).

쿠버네티스 1.26부터 레거시 메커니즘이 제거되었으므로 다음 중 하나를 해야 합니다:

  • 각 노드에 kubelet 이미지 credential provider를 구성하거나;
  • imagePullSecrets와 최소 하나의 Secret으로 이미지 가져오기 자격 증명을 지정한다.

더 알아보기 (Learn more)