`:latest` 태그 사용은 피해야 한다는 것을 참고하고, 자세한 정보는 [구성을 위한 모범 사례](/docs/concepts/configuration/overview/#container-images)를 참고한다.
## 매니페스트로 멀티-아키텍처 이미지 빌드
Docker CLI는 현재 `docker manifest` 커맨드와 `create`, `annotate`, `push`와 같은 서브 커맨드를 함께 지원한다. 이 커맨드는 매니페스트를 빌드하고 푸시하는데 사용할 수 있다. 매니페스트를 보기 위해서는 `docker manifest inspect`를 사용하면 된다.
이 커맨드는 Docker CLI에 의존하며 그에 전적으로 구현된다. `$HOME/.docker/config.json` 편집 및 `experimental` 키를 `enabled`로 설정하거나, CLI 커맨드 호출 시 간단히 `DOCKER_CLI_EXPERIMENTAL` 환경 변수를 `enabled`로만 설정해도 된다.
{{<note>}}
Docker *18.06 또는 그 이상* 을 사용하길 바란다. 더 낮은 버전은 버그가 있거나 실험적인 명령줄 옵션을 지원하지 않는다. 예를 들어 https://github.com/docker/cli/issues/1135 는 containerd에서 문제를 일으킨다.
{{</note>}}
오래된 매니페스트 업로드를 실행하는 데 어려움을 겪는다면, `$HOME/.docker/manifests`에서 오래된 매니페스트를 정리하여 새롭게 시작하면 된다.
쿠버네티스의 경우, 일반적으로 접미사 `-$(ARCH)`가 있는 이미지를 사용해 왔다. 하위 호환성을 위해, 접미사가 있는 구형 이미지를 생성하길 바란다. 접미사에 대한 아이디어는 모든 아키텍처를 위한 매니페스트를 가졌다는 의미가 내포된 `pause` 이미지를 생성하고, 접미사가 붙은 이미지가 하드 코드되어 있을 오래된 구성 또는 YAML 파일에 대해 하위 호환된다는 의미가 내포되어 있는 `pause-amd64`를 생성하기 위한 것이다.
## 프라이빗 레지스트리 사용
프라이빗 레지스트리는 해당 레지스트리에서 이미지를 읽을 수 있는 키를 요구할 것이다.
자격 증명(credential)은 여러 가지 방법으로 제공될 수 있다.
- Google 컨테이너 레지스트리 사용
- 각 클러스터에 대하여
- Google 컴퓨트 엔진 또는 Google 쿠버네티스 엔진에서 자동적으로 구성됨
- 모든 파드는 해당 프로젝트의 프라이빗 레지스트리를 읽을 수 있음
- AWS EC2 컨테이너 레지스트리(ECR) 사용
- IAM 역할 및 정책을 사용하여 ECR 저장소에 접근을 제어함
- ECR 로그인 자격 증명은 자동으로 갱신됨
- Azure 컨테이너 레지스트리(ACR) 사용
- IBM 클라우드 컨테이너 레지스트리 사용
- 프라이빗 레지스트리에 대한 인증을 위한 노드 구성
- 모든 파드는 구성된 프라이빗 레지스트리를 읽을 수 있음
- 클러스터 관리자에 의한 노드 구성 필요
- 미리 풀링(pre-pulling)된 이미지
- 모든 파드는 노드에 캐시된 모든 이미지를 사용 가능
- 셋업을 위해서는 모든 노드에 대해서 root 접근이 필요
- 파드에 ImagePullSecrets을 명시
- 자신의 키를 제공하는 파드만 프라이빗 레지스트리에 접근 가능
각 옵션은 아래에서 더 자세히 설명한다.
### Google 컨테이너 레지스트리 사용
쿠버네티스는 Google 컴퓨트 엔진(GCE)에서 동작할 때, [Google 컨테이너
레지스트리(GCR)](https://cloud.google.com/tools/container-registry/)를 자연스럽게
지원한다. 사용자의 클러스터가 GCE 또는 Google 쿠버네티스 엔진에서 동작 중이라면, 간단히
이미지의 전체 이름(예: gcr.io/my_project/image:tag)을 사용하면 된다.
클러스터 내에서 모든 파드는 해당 레지스트리에 있는 이미지에 읽기 접근 권한을 가질 것이다.
Kubelet은 해당 인스턴스의 Google 서비스 계정을 이용하여 GCR을 인증할 것이다.
인스턴스의 서비스 계정은 `https://www.googleapis.com/auth/devstorage.read_only`라서,
프로젝트의 GCR로부터 풀은 할 수 있지만 푸시는 할 수 없다.
### AWS EC2 컨테이너 레지스트리 사용
쿠버네티스는 노드가 AWS EC2 인스턴스일 때, [AWS EC2 컨테이너
레지스트리](https://aws.amazon.com/ecr/)를 자연스럽게 지원한다.
간단히 이미지의 전체 이름(예: `ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag`)을
파드 정의에 사용하면 된다.
파드를 생성할 수 있는 클러스터의 모든 사용자는 ECR 레지스트리에 있는 어떠한
이미지든지 파드를 실행하는데 사용할 수 있다.
kubelet은 ECR 자격 증명을 가져오고 주기적으로 갱신할 것이다. 이것을 위해서는 다음에 대한 권한이 필요하다.
-`ecr:GetAuthorizationToken`
-`ecr:BatchCheckLayerAvailability`
-`ecr:GetDownloadUrlForLayer`
-`ecr:GetRepositoryPolicy`
-`ecr:DescribeRepositories`
-`ecr:ListImages`
-`ecr:BatchGetImage`
요구 사항:
- Kubelet 버전 `v1.2.0` 이상을 사용해야 한다. (예: `/usr/bin/kubelet --version=true`를 실행).
- 노드가 지역 A에 있고 레지스트리가 다른 지역 B에 있다면, 버전 `v1.3.0` 이상이 필요하다.
- 사용자의 지역에서 ECR이 지원되어야 한다.
문제 해결:
- 위의 모든 요구 사항을 확인한다.
- 워크스테이션에서 $REGION (예: `us-west-2`)의 자격 증명을 얻는다. 그 자격 증명을 사용하여 해당 호스트로 SSH를 하고 Docker를 수동으로 실행한다. 작동하는가?
- kubelet이 `--cloud-provider=aws`로 실행 중인지 확인한다.
- kubelet 로그에서 (예: `journalctl -u kubelet`) 다음과 같은 로그 라인을 확인한다.
[쿠버네티스 시크릿을 구성하고 그것을 파드 디플로이를 위해서 사용](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod)할 수 있다.
### IBM 클라우드 컨테이너 레지스트리 사용
IBM 클라우드 컨테이너 레지스트리는 멀티-테넌트 프라이빗 이미지 레지스트리를 제공하여 사용자가 Docker 이미지를 안전하게 저장하고 공유할 수 있도록 한다. 기본적으로,
프라이빗 레지스트리의 이미지는 통합된 취약점 조언기(Vulnerability Advisor)를 통해 조사되어 보안 이슈와 잠재적 취약성을 검출한다. IBM 클라우드 계정의 모든 사용자가 이미지에 접근할 수 있도록 하거나, 레지스트리 네임스페이스에 접근을 승인하는 토큰을 생성할 수 있다.
IBM 클라우드 컨테이너 레지스트리 CLI 플러그인을 설치하고 사용자 이미지를 위한 네임스페이스를 생성하기 위해서는, [IBM 클라우드 컨테이너 레지스트리 시작하기](https://cloud.ibm.com/docs/services/Registry?topic=registry-index#index)를 참고한다.
[IBM 클라우드 퍼블릭 이미지](https://cloud.ibm.com/docs/services/Registry?topic=registry-public_images#public_images) 및 사용자의 프라이빗 이미지로부터 컨테이너를 사용자의 IBM 클라우드 쿠버네티스 서비스 클러스터의 `default` 네임스페이스에 디플로이하기 위해서 IBM 클라우드 컨테이너 레지스트리를 사용하면 된다. 컨테이너를 다른 네임스페이스에 디플로이하거나, 다른 IBM 클라우드 컨테이너 레지스트리 지역 또는 IBM 클라우드 계정을 사용하기 위해서는, 쿠버네티스 `imagePullSecret`를 생성한다. 더 자세한 정보는, [이미지로부터 컨테이너 빌드하기](https://cloud.ibm.com/docs/containers?topic=containers-images#images)를 참고한다.
그러나, 이 필드의 셋팅은 [서비스 어카운트](/docs/user-guide/service-accounts) 리소스에
imagePullSecrets을 셋팅하여 자동화할 수 있다.
자세한 지침을 위해서는 [서비스 어카운트에 ImagePullSecrets 추가](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account)를 확인한다.
이것은 노드 당 `.docker/config.json`와 함께 사용할 수 있다. 자격 증명은
병합될 것이다. 이 방법은 Google 쿠버네티스 엔진에서 작동될 것이다.
### 유스케이스
프라이빗 레지스트리를 구성하기 위한 많은 솔루션이 있다. 다음은 여러 가지
일반적인 유스케이스와 제안된 솔루션이다.
1. 비소유 이미지(예를 들어, 오픈소스)만 실행하는 클러스터의 경우. 이미지를 숨길 필요가 없다.
- Docker hub의 퍼블릭 이미지를 사용한다.
- 설정이 필요 없다.
- GCE 및 Google 쿠버네티스 엔진에서는, 속도와 가용성 향상을 위해서 로컬 미러가 자동적으로 사용된다.
1. 모든 클러스터 사용자에게는 보이지만, 회사 외부에는 숨겨야하는 일부 독점 이미지를
실행하는 클러스터의 경우.
- 호스트 된 프라이빗 [Docker 레지스트리](https://docs.docker.com/registry/)를 사용한다.
- 그것은 [Docker Hub](https://hub.docker.com/signup)에 호스트 되어 있거나, 다른 곳에 되어 있을 것이다.
- 위에 설명된 바와 같이 수동으로 .docker/config.json을 구성한다.
- 또는, 방화벽 뒤에서 읽기 접근 권한을 가진 내부 프라이빗 레지스트리를 실행한다.
- 쿠버네티스 구성은 필요 없다.
- 또는, GCE 및 Google 쿠버네티스 엔진에서는, 프로젝트의 Google 컨테이너 레지스트리를 사용한다.
- 그것은 수동 노드 구성에 비해서 클러스터 오토스케일링과 더 잘 동작할 것이다.
- 또는, 노드의 구성 변경이 불편한 클러스터에서는, `imagePullSecrets`를 사용한다.
1. 독점 이미지를 가진 클러스터로, 그 중 일부가 더 엄격한 접근 제어를 필요로 하는 경우.
- [AlwaysPullImages 어드미션 컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)가 활성화되어 있는지 확인한다. 그렇지 않으면, 모든 파드가 잠재적으로 모든 이미지에 접근 권한을 가진다.
- 민감한 데이터는 이미지 안에 포장하는 대신, "시크릿" 리소스로 이동한다.
1. 멀티-테넌트 클러스터에서 각 테넌트가 자신의 프라이빗 레지스트리를 필요로 하는 경우.
- [AlwaysPullImages 어드미션 컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)가 활성화되어 있는지 확인한다. 그렇지 않으면, 모든 파드가 잠재적으로 모든 이미지에 접근 권한을 가진다.
- 인가가 요구되도록 프라이빗 레지스트리를 실행한다.
- 각 테넌트에 대한 레지스트리 자격 증명을 생성하고, 시크릿에 넣고, 각 테넌트 네임스페이스에 시크릿을 채운다.