kubelet 이미지 자격 증명 제공자 구성하기

kubelet 이미지 자격 증명 제공자 구성하기 (Configure a kubelet image credential provider)

기능 상태: Kubernetes v1.26부터 Stable.

Kubernetes v1.20부터 kubelet은 exec 플러그인을 사용해 컨테이너 이미지 레지스트리의 자격 증명을 동적으로 검색할 수 있어요. kubelet과 exec 플러그인은 쿠버네티스 버전별 API를 사용해 stdio(stdin, stdout, stderr)로 통신해요. 이 플러그인들은 kubelet이 정적 자격 증명을 디스크에 저장하는 대신 컨테이너 레지스트리의 자격 증명을 동적으로 요청할 수 있게 해 줘요. 예를 들어 플러그인은 로컬 메타데이터 서버와 통신해 kubelet이 가져오는 이미지의 단기 수명 자격 증명을 검색할 수 있어요.

다음 중 하나라도 해당된다면 이 기능을 사용하는 데 관심이 있을 거예요.

  • 레지스트리의 인증 정보를 검색하려면 클라우드 제공업체 서비스에 API 호출이 필요함
  • 자격 증명의 만료 시간이 짧고 새 자격 증명을 자주 요청해야 함
  • 레지스트리 자격 증명을 디스크나 imagePullSecrets에 저장하는 것이 허용되지 않음

이 가이드는 kubelet의 이미지 자격 증명 제공자 플러그인 메커니즘을 구성하는 방법을 보여드려요.

출처: 문서

본문

이미지 풀을 위한 서비스어카운트 토큰 (Service Account Token for Image Pulls)

기능 상태: Kubernetes v1.34부터 Beta; 기본적으로 활성화.

Kubernetes v1.33부터 kubelet은 이미지 풀이 수행되는 파드에 바인딩된 서비스어카운트 토큰을 자격 증명 제공자 플러그인에 보내도록 구성할 수 있어요.

이를 통해 플러그인이 토큰을 이미지 레지스트리에 접근하기 위한 자격 증명으로 교환할 수 있어요.

이 기능을 활성화하려면 kubelet에서 KubeletServiceAccountTokenForCredentialProviders 기능 게이트를 활성화해야 하고, 플러그인의 CredentialProviderConfig 파일에 tokenAttributes 필드를 설정해야 해요.

tokenAttributes 필드는 플러그인에 전달될 서비스어카운트 토큰에 대한 정보를 포함해요. 여기에는 토큰의 의도된 audience와 플러그인이 파드에 서비스어카운트가 필요로 하는지 여부가 포함돼요.

서비스어카운트 토큰 자격 증명을 사용하면 다음과 같은 사용 사례가 가능해져요.

  • 레지스트리에서 이미지를 가져오기 위해 kubelet/노드 기반 정체성이 필요하지 않게 함
  • 장기/영속 시크릿 없이 워크로드가 자신의 런타임 정체성에 기반해 이미지를 가져올 수 있게 함

시작하기 전에 (Before you begin)

  • kubelet 자격 증명 제공자 플러그인을 지원하는 노드가 있는 쿠버네티스 클러스터가 필요해요. 이 지원은 Kubernetes 1.37에서 사용할 수 있어요. Kubernetes v1.24와 v1.25는 이를 기본 활성화된 베타 기능으로 포함했어요.
  • 서비스어카운트 토큰을 요구하는 자격 증명 제공자 플러그인을 구성한다면, Kubernetes v1.33 이상을 실행하는 노드가 있는 클러스터와 kubelet에서 KubeletServiceAccountTokenForCredentialProviders 기능 게이트가 활성화된 클러스터가 필요해요.
  • 동작하는 자격 증명 제공자 exec 플러그인 구현이 필요해요. 직접 플러그인을 만들거나 클라우드 제공업체가 제공하는 것을 사용할 수 있어요.

쿠버네티스 서버가 최소 v1.26 버전이어야 해요. 버전을 확인하려면 kubectl version을 입력하세요.

노드에 플러그인 설치하기 (Installing Plugins on Nodes)

자격 증명 제공자 플러그인은 kubelet이 실행할 실행 바이너리예요. 플러그인 바이너리가 클러스터의 모든 노드에 존재하고 알려진 디렉터리(known directory)에 저장돼 있는지 확인하세요. 이 디렉터리는 나중에 kubelet 플래그를 구성할 때 필요해요.

Kubelet 구성하기 (Configuring the Kubelet)

이 기능을 사용하려면 kubelet이 두 개의 플래그를 설정해야 해요.

  • --image-credential-provider-config — 자격 증명 제공자 플러그인 구성 파일의 경로
  • --image-credential-provider-bin-dir — 자격 증명 제공자 플러그인 바이너리가 있는 디렉터리의 경로

kubelet 자격 증명 제공자 구성하기 (Configure a kubelet credential provider)

--image-credential-provider-config에 전달된 구성 파일은 kubelet이 어떤 exec 플러그인을 어떤 컨테이너 이미지에 호출해야 하는지 결정하는 데 읽어요. ECR 기반 플러그인을 사용하고 있다면 사용하게 될 구성 파일 예시는 다음과 같아요.

apiVersion: kubelet.config.k8s.io/v1
kind: CredentialProviderConfig
# providers는 kubelet이 활성화할 자격 증명 제공자 헬퍼 플러그인의 목록입니다.
# 여러 제공자가 단일 이미지와 일치할 수 있으며, 이 경우 모든 제공자의 자격 증명이
# kubelet으로 반환됩니다. 단일 이미지에 대해 여러 제공자가 호출되면 결과가 결합됩니다.
# 제공자가 겹치는 auth 키를 반환하면 이 목록의 앞쪽에 있는 제공자의 값이 사용됩니다.
providers:
  # name은 자격 증명 제공자의 필수 이름입니다. kubelet이 보는 제공자
  # 실행 파일의 이름과 일치해야 합니다. 실행 파일은 kubelet의
  # bin 디렉터리(--image-credential-provider-bin-dir 플래그로 설정)에 있어야 합니다.
  - name: ecr-credential-provider
    # matchImages는 이 제공자를 호출해야 하는지 결정하기 위해 이미지와 일치시키는
    # 데 사용되는 필수 문자열 목록입니다. 문자열 중 하나가 kubelet의 요청 이미지와
    # 일치하면 플러그인이 호출되고 자격 증명을 제공할 기회를 얻습니다.
    # 이미지는 레지스트리 도메인과 URL 경로를 포함할 것으로 예상됩니다.
    #
    # matchImages의 각 항목은 선택적으로 포트와 경로를 포함할 수 있는 패턴입니다.
    # 도메인에는 glob을 사용할 수 있지만 포트나 경로에는 사용할 수 없습니다.
    # glob은 '*.k8s.io' 또는 'k8s.*.io' 같은 하위 도메인과 'k8s.*' 같은
    # 최상위 도메인으로 지원됩니다. 'app*.k8s.io' 같은 부분 하위 도메인 일치도 지원됩니다.
    # 각 glob은 단일 하위 도메인 세그먼트만 일치시킬 수 있으므로 `*.io`는 `*.k8s.io`를
    # 일치시키지 **않습니다**.
    #
    # 이미지와 matchImage 사이에 일치가 존재하려면 아래 모두가 참이어야 합니다:
    # - 둘 다 동일한 수의 도메인 파트를 가지며 각 파트가 일치합니다.
    # - matchImages의 URL 경로는 대상 이미지 URL 경로의 접두사여야 합니다.
    # - matchImages에 포트가 포함되면 이미지에서도 포트가 일치해야 합니다.
    #
    # matchImages의 예시 값:
    # - 123456789.dkr.ecr.us-east-1.amazonaws.com
    # - *.azurecr.io
    # - gcr.io
    # - *.*.registry.io
    # - registry.io:8080/path
    matchImages:
      - "*.dkr.ecr.*.amazonaws.com"
      - "*.dkr.ecr.*.amazonaws.com.cn"
      - "*.dkr.ecr-fips.*.amazonaws.com"
      - "*.dkr.ecr.us-iso-east-1.c2s.ic.gov"
      - "*.dkr.ecr.us-isob-east-1.sc2s.sgov.gov"
    # defaultCacheDuration은 플러그인 응답에 캐시 기간이 제공되지 않을 때
    # 플러그인이 자격 증명을 메모리에 캐시할 기본 기간입니다. 필수 필드입니다.
    defaultCacheDuration: "12h"
    # exec CredentialProviderRequest의 필수 입력 버전입니다. 반환된 CredentialProviderResponse는
    # 입력과 동일한 인코딩 버전을 사용해야 합니다. 현재 지원되는 값:
    # - credentialprovider.kubelet.k8s.io/v1
    apiVersion: credentialprovider.kubelet.k8s.io/v1
    # 명령을 실행할 때 전달할 인자입니다.
    # +optional
    # args:
    #   - --example-argument
    # env는 프로세스에 노출할 추가 환경 변수를 정의합니다. 이들은 호스트의
    # 환경 및 client-go가 플러그인에 인자를 전달하는 데 사용하는 변수와 결합됩니다.
    # +optional
    env:
      - name: AWS_PROFILE
        value: example_profile

    # tokenAttributes는 플러그인에 전달될 서비스어카운트 토큰에 대한 구성입니다.
    # 자격 증명 제공자는 이 필드를 설정하여 이미지 풀에 서비스어카운트 토큰을
    # 사용하도록 선택합니다.
    # 이 필드가 `KubeletServiceAccountTokenForCredentialProviders` 기능 게이트가 활성화되지 않은
    # 상태로 설정되면 kubelet은 잘못된 구성 오류로 시작에 실패합니다.
    # +optional
    tokenAttributes:
      # serviceAccountTokenAudience는 프로젝션된 서비스어카운트 토큰의 의도된 audience입니다.
      # +required
      serviceAccountTokenAudience: "<audience for the token>"
      # cacheType은 서비스어카운트 토큰이 사용될 때 플러그인이 반환한 자격 증명을
      # 캐시하는 데 사용하는 캐시 키의 유형을 나타냅니다.
      # 가장 보수적인 옵션은 "Token"으로 설정하는 것인데, 이는 kubelet이 토큰별로
      # 반환된 자격 증명을 캐시한다는 뜻입니다. 반환된 자격 증명의 수명이
      # 서비스어카운트 토큰의 수명으로 제한되는 경우 이렇게 설정해야 합니다.
      # 플러그인의 자격 증명 검색 로직이 파드 특정 클레임이 아닌 서비스어카운트에만
      # 의존한다면 플러그인이 "ServiceAccount"로 설정할 수 있습니다. 이 경우
      # kubelet은 서비스어카운트별로 반환된 자격 증명을 캐시합니다. 반환된 자격 증명이
      # 같은 서비스어카운트를 사용하는 모든 파드에 유효할 때 이 옵션을 사용하세요.
      # +required
      cacheType: "<Token or ServiceAccount>"
      # requireServiceAccount는 플러그인이 파드에 서비스어카운트를 요구하는지 여부를 나타냅니다.
      # true로 설정하면 kubelet은 파드에 서비스어카운트가 있는 경우에만 플러그인을 호출합니다.
      # false로 설정하면 kubelet은 파드에 서비스어카운트가 없어도 플러그인을 호출하고
      # CredentialProviderRequest에 토큰을 포함하지 않습니다. 이는 서비스어카운트가 없는
      # 파드(예: 정적 파드)의 이미지를 가져오는 데 사용되는 플러그인에 유용합니다.
      # +required
      requireServiceAccount: true
      # requiredServiceAccountAnnotationKeys는 플러그인이 관심을 갖고 서비스어카운트에
      # 반드시 존재해야 하는 어노테이션 키의 목록입니다.
      # 이 목록에 정의된 키는 해당 서비스어카운트에서 추출되어 CredentialProviderRequest의
      # 일부로 플러그인에 전달됩니다. 이 목록에 정의된 키 중 하나라도 서비스어카운트에
      # 존재하지 않으면 kubelet은 플러그인을 호출하지 않고 오류를 반환합니다.
      # 이 필드는 선택 사항이며 비어 있을 수 있습니다. 플러그인은 이 필드를 사용해
      # 자격 증명을 가져오는 데 필요한 추가 정보를 추출하거나 워크로드가 이미지 풀에
      # 서비스어카운트 토큰을 사용하도록 선택하게 할 수 있습니다.
      # 비어 있지 않으면 requireServiceAccount가 true로 설정되어야 합니다.
      # 이 목록에 정의된 키는 unique해야 하며 optionalServiceAccountAnnotationKeys 목록에
      # 정의된 키와 겹치면 안 됩니다.
      # +optional
      requiredServiceAccountAnnotationKeys:
      - "example.com/required-annotation-key-1"
      - "example.com/required-annotation-key-2"
      # optionalServiceAccountAnnotationKeys는 플러그인이 관심을 갖고 서비스어카운트에
      # 존재할 수도 있고 아닐 수도 있는 어노테이션 키의 목록입니다.
      # 이 목록에 정의된 키는 해당 서비스어카운트에서 추출되어 CredentialProviderRequest의
      # 일부로 플러그인에 전달됩니다. 어노테이션의 존재와 값을 검증하는 것은 플러그인의
      # 책임입니다. 이 필드는 선택 사항이며 비어 있을 수 있습니다.
      # 플러그인은 이 필드를 사용해 자격 증명을 가져오는 데 필요한 추가 정보를 추출할 수 있습니다.
      # 이 목록에 정의된 키는 unique해야 하며 requiredServiceAccountAnnotationKeys 목록에
      # 정의된 키와 겹치면 안 됩니다.
      # +optional
      optionalServiceAccountAnnotationKeys:
      - "example.com/optional-annotation-key-1"
      - "example.com/optional-annotation-key-2"

providers 필드는 kubelet이 사용하는 활성화된 플러그인 목록이에요. 각 항목에는 몇 가지 필수 필드가 있어요.

  • name: --image-credential-provider-bin-dir에 전달된 디렉터리에 존재하는 실행 바이너리의 이름과 반드시 일치해야 하는 플러그인 이름
  • matchImages: 이 제공자를 호출해야 하는지 결정하기 위해 이미지와 일치시키는 데 사용되는 문자열 목록. 자세한 내용은 아래에 있어요.
  • defaultCacheDuration: 플러그인이 캐시 기간을 지정하지 않았을 때 kubelet이 자격 증명을 메모리에 캐시할 기본 기간
  • apiVersion: kubelet과 exec 플러그인이 통신할 때 사용할 API 버전

각 자격 증명 제공자에는 선택적 인자와 환경 변수도 줄 수 있어요. 특정 플러그인에 어떤 인자와 환경 변수 집합이 필요한지 결정하려면 플러그인 구현자와 상의하세요.

KubeletServiceAccountTokenForCredentialProviders 기능 게이트를 사용하고 tokenAttributes 필드를 설정해 플러그인이 서비스어카운트 토큰을 사용하도록 구성한다면 다음 필드가 필요해요.

  • serviceAccountTokenAudience: 프로젝션된 서비스어카운트 토큰의 의도된 audience. 빈 문자열일 수 없어요. ServiceAccountNodeAudienceRestriction 기능 게이트가 활성화되면 kubelet이 이 audience에 대한 토큰을 요청하도록 인가받아야 해요. 그렇지 않으면 자격 증명 제공자가 호출되지 않아요. system:nodes 그룹에 이 audience에 대한 request-serviceaccounts-token-audience 동사를 사용할 권한을 RBAC로 부여해야 해요. 자세한 내용과 예시는 서비스어카운트 토큰 audience 제한을 참고하세요.
  • cacheType: 서비스어카운트 토큰이 사용될 때 플러그인이 반환한 자격 증명을 캐시하는 데 사용하는 캐시 키 유형. 가장 보수적인 옵션은 Token으로 설정하는 것이며, kubelet이 토큰별로 반환된 자격 증명을 캐시한다는 뜻이에요. 반환된 자격 증명의 수명이 서비스어카운트 토큰의 수명으로 제한되는 경우 이렇게 설정해야 해요. 플러그인의 자격 증명 검색 로직이 파드 특정 클레임이 아닌 서비스어카운트에만 의존한다면 ServiceAccount로 설정할 수 있어요. 이 경우 kubelet이 서비스어카운트별로 반환된 자격 증명을 캐시해요. 반환된 자격 증명이 같은 서비스어카운트를 사용하는 모든 파드에 유효할 때 사용하세요.
  • requireServiceAccount: 플러그인이 파드에 서비스어카운트를 요구하는지 여부.
    • true로 설정하면 kubelet은 파드에 서비스어카운트가 있는 경우에만 플러그인을 호출해요.
    • false로 설정하면 kubelet은 파드에 서비스어카운트가 없어도 플러그인을 호출하고 CredentialProviderRequest에 토큰을 포함하지 않아요.
    • 이는 서비스어카운트가 없는 파드(예: 정적 파드)의 이미지를 가져오는 데 사용되는 플러그인에 유용해요.

이미지 일치 구성하기 (Configure image matching)

각 자격 증명 제공자의 matchImages 필드는 Pod가 사용하는 특정 이미지에 대해 플러그인을 호출해야 하는지 결정하는 데 kubelet이 사용해요. matchImages의 각 항목은 선택적으로 포트와 경로를 포함할 수 있는 이미지 패턴이에요. 도메인에는 glob을 사용할 수 있지만 포트나 경로에는 사용할 수 없어요. glob은 *.k8s.io 또는 k8s.*.io 같은 하위 도메인과 k8s.* 같은 최상위 도메인으로 지원돼요. app*.k8s.io 같은 부분 하위 도메인 일치도 지원돼요. 각 glob은 단일 하위 도메인 세그먼트만 일치시킬 수 있어서, *.io*.k8s.io를 일치시키지 않아요.

이미지 이름과 matchImage 항목 사이에 일치가 존재하려면 아래 모두가 참이어야 해요.

  • 둘 다 동일한 수의 도메인 파트를 가지며 각 파트가 일치해요.
  • match image의 URL 경로는 대상 이미지 URL 경로의 접두사여야 해요.
  • matchImages에 포트가 포함되면 이미지에서도 포트가 일치해야 해요.

matchImages 패턴의 예시 값:

  • 123456789.dkr.ecr.us-east-1.amazonaws.com
  • *.azurecr.io
  • gcr.io
  • *.*.registry.io
  • foo.registry.io:8080/path

다음 단계 (What's next)

  • kubelet 구성 API (v1) 참조에서 CredentialProviderConfig에 대한 세부 정보 읽기
  • kubelet 자격 증명 제공자 API 참조 (v1) 읽기

더 알아보기 (Learn more)