사용자 Docker 이미지를 생성하고 레지스트리에 푸시(push)하여 쿠버네티스 파드에서 참조되기 이전에 대비한다.
컨테이너의 image
속성은 docker
커맨드에서 지원하는 문법과 같은 문법을 지원한다. 이는 프라이빗 레지스트리와 태그를 포함한다.
기본 풀(pull) 정책은 IfNotPresent
이며, 이것은 Kubelet이 이미
존재하는 이미지에 대한 풀을 생략하게 한다. 만약 항상 풀을 강제하고 싶다면,
다음 중 하나를 수행하면 된다.
imagePullPolicy
를 Always
로 설정.imagePullPolicy
를 생략하고 :latest
를 사용할 이미지의 태그로 사용.imagePullPolicy
와 사용할 이미지의 태그를 생략.:latest
태그 사용은 피해야 한다는 것을 참고하고, 자세한 정보는 구성을 위한 모범 사례를 참고한다.
Docker CLI는 현재 docker manifest
커맨드와 create
, annotate
, push
와 같은 서브 커맨드를 함께 지원한다. 이 커맨드는 매니페스트를 빌드하고 푸시하는데 사용할 수 있다. 매니페스트를 보기 위해서는 docker manifest inspect
를 사용하면 된다.
다음에서 docker 문서를 확인하기 바란다. https://docs.docker.com/edge/engine/reference/commandline/manifest/
이것을 사용하는 방법에 대한 예제는 빌드 하니스(harness)에서 참조한다. https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
이 커맨드는 Docker CLI에 의존하며 그에 전적으로 구현된다. $HOME/.docker/config.json
편집 및 experimental
키를 enabled
로 설정하거나, CLI 커맨드 호출 시 간단히 DOCKER_CLI_EXPERIMENTAL
환경 변수를 enabled
로만 설정해도 된다.
참고: Docker 18.06 또는 그 이상 을 사용하길 바란다. 더 낮은 버전은 버그가 있거나 실험적인 명령줄 옵션을 지원하지 않는다. 예를 들어 https://github.com/docker/cli/issues/1135 는 containerd에서 문제를 일으킨다.
오래된 매니페스트 업로드를 실행하는 데 어려움을 겪는다면, $HOME/.docker/manifests
에서 오래된 매니페스트를 정리하여 새롭게 시작하면 된다.
쿠버네티스의 경우, 일반적으로 접미사 -$(ARCH)
가 있는 이미지를 사용해 왔다. 하위 호환성을 위해, 접미사가 있는 구형 이미지를 생성하길 바란다. 접미사에 대한 아이디어는 모든 아키텍처를 위한 매니페스트를 가졌다는 의미가 내포된 pause
이미지를 생성하고, 접미사가 붙은 이미지가 하드 코드되어 있을 오래된 구성 또는 YAML 파일에 대해 하위 호환된다는 의미가 내포되어 있는 pause-amd64
를 생성하기 위한 것이다.
프라이빗 레지스트리는 해당 레지스트리에서 이미지를 읽을 수 있는 키를 요구할 것이다. 자격 증명(credential)은 여러 가지 방법으로 제공될 수 있다.
각 옵션은 아래에서 더 자세히 설명한다.
쿠버네티스는 Google 컴퓨트 엔진(GCE)에서 동작할 때, Google 컨테이너 레지스트리(GCR)를 자연스럽게 지원한다. 사용자의 클러스터가 GCE 또는 Google 쿠버네티스 엔진에서 동작 중이라면, 간단히 이미지의 전체 이름(예: gcr.io/my_project/image:tag)을 사용하면 된다.
클러스터 내에서 모든 파드는 해당 레지스트리에 있는 이미지에 읽기 접근 권한을 가질 것이다.
Kubelet은 해당 인스턴스의 Google 서비스 계정을 이용하여 GCR을 인증할 것이다.
인스턴스의 서비스 계정은 https://www.googleapis.com/auth/devstorage.read_only
라서,
프로젝트의 GCR로부터 풀은 할 수 있지만 푸시는 할 수 없다.
쿠버네티스는 노드가 AWS EC2 인스턴스일 때, AWS EC2 컨테이너 레지스트리를 자연스럽게 지원한다.
간단히 이미지의 전체 이름(예: 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
요구 사항:
v1.2.0
이상을 사용해야 한다. (예: /usr/bin/kubelet --version=true
를 실행).v1.3.0
이상이 필요하다.문제 해결:
us-west-2
)의 자격 증명을 얻는다. 그 자격 증명을 사용하여 해당 호스트로 SSH를 하고 Docker를 수동으로 실행한다. 작동하는가?--cloud-provider=aws
로 실행 중인지 확인한다.journalctl -u kubelet
) 다음과 같은 로그 라인을 확인한다.
plugins.go:56] Registering credential provider: aws-ecr-key
provider.go:91] Refreshing cache for provider: *aws_credentials.ecrProvider
Azure 컨테이너 레지스트리를 사용하는 경우 관리자 역할의 사용자나 서비스 주체(principal) 중 하나를 사용하여 인증할 수 있다. 어느 경우라도, 인증은 표준 Docker 인증을 통해서 수행된다. 이러한 지침은 azure-cli 명령줄 도구 사용을 가정한다.
우선 레지스트리를 생성하고 자격 증명을 만들어야한다. 이에 대한 전체 문서는 Azure 컨테이너 레지스트리 문서에서 찾을 수 있다.
컨테이너 레지스트리를 생성하고 나면, 다음의 자격 증명을 사용하여 로그인한다.
DOCKER_USER
: 서비스 주체 또는 관리자 역할의 사용자명DOCKER_PASSWORD
: 서비스 주체 패스워드 또는 관리자 역할의 사용자 패스워드DOCKER_REGISTRY_SERVER
: ${some-registry-name}.azurecr.io
DOCKER_EMAIL
: ${some-email-address}
해당 변수에 대한 값을 채우고 나면 쿠버네티스 시크릿을 구성하고 그것을 파드 디플로이를 위해서 사용할 수 있다.
IBM 클라우드 컨테이너 레지스트리는 멀티-테넌트 프라이빗 이미지 레지스트리를 제공하여 사용자가 Docker 이미지를 안전하게 저장하고 공유할 수 있도록 한다. 기본적으로, 프라이빗 레지스트리의 이미지는 통합된 취약점 조언기(Vulnerability Advisor)를 통해 조사되어 보안 이슈와 잠재적 취약성을 검출한다. IBM 클라우드 계정의 모든 사용자가 이미지에 접근할 수 있도록 하거나, 레지스트리 네임스페이스에 접근을 승인하는 토큰을 생성할 수 있다.
IBM 클라우드 컨테이너 레지스트리 CLI 플러그인을 설치하고 사용자 이미지를 위한 네임스페이스를 생성하기 위해서는, IBM 클라우드 컨테이너 레지스트리 시작하기를 참고한다.
IBM 클라우드 퍼블릭 이미지 및 사용자의 프라이빗 이미지로부터 컨테이너를 사용자의 IBM 클라우드 쿠버네티스 서비스 클러스터의 default
네임스페이스에 디플로이하기 위해서 IBM 클라우드 컨테이너 레지스트리를 사용하면 된다. 컨테이너를 다른 네임스페이스에 디플로이하거나, 다른 IBM 클라우드 컨테이너 레지스트리 지역 또는 IBM 클라우드 계정을 사용하기 위해서는, 쿠버네티스 imagePullSecret
를 생성한다. 더 자세한 정보는, 이미지로부터 컨테이너 빌드하기를 참고한다.
참고: Google 쿠버네티스 엔진에서 동작 중이라면, 이미 각 노드에 Google 컨테이너 레지스트리에 대한 자격 증명과 함께.dockercfg
가 있을 것이다. 그렇다면 이 방법은 쓸 수 없다.
참고: AWS EC2에서 동작 중이고 EC2 컨테이너 레지스트리(ECR)을 사용 중이라면, 각 노드의 kubelet은 ECR 로그인 자격 증명을 관리하고 업데이트할 것이다. 그렇다면 이 방법은 쓸 수 없다.
참고: 이 방법은 노드의 구성을 제어할 수 있는 경우에만 적합하다. 이 방법은 GCE 및 자동 노드 교체를 수행하는 다른 클라우드 제공자에 대해서는 신뢰성 있게 작동하지 않을 것이다.
참고: 현재 쿠버네티스는 docker 설정의auths
와HttpHeaders
섹션만 지원한다. 이는 자격증명 도우미(credHelpers
또는credStore
)가 지원되지 않는다는 뜻이다.
Docker는 프라이빗 레지스트리를 위한 키를 $HOME/.dockercfg
또는 $HOME/.docker/config.json
파일에 저장한다. 만약 동일한 파일을
아래의 검색 경로 리스트에 넣으면, kubelete은 이미지를 풀 할 때 해당 파일을 자격 증명 공급자로 사용한다.
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
참고: 아마도 kubelet을 위한 사용자의 환경 파일에HOME=/root
을 명시적으로 설정해야 할 것이다.
프라이빗 레지스트리를 사용도록 사용자의 노드를 구성하기 위해서 권장되는 단계는 다음과 같다. 이 예제의 경우, 사용자의 데스크탑/랩탑에서 아래 내용을 실행한다.
docker login [서버]
를 실행한다. 이것은 $HOME/.docker/config.json
를 업데이트한다.$HOME/.docker/config.json
를 보고 사용하고 싶은 자격 증명만 포함하고 있는지 확인한다.nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')
nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
.docker/config.json
를 위의 검색 경로 리스트 중 하나에 복사한다.
for n in $nodes; do scp ~/.docker/config.json root@$n:/var/lib/kubelet/config.json; done
프라이빗 이미지를 사용하는 파드를 생성하여 검증한다. 예를 들면 다음과 같다.
kubectl create -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: private-image-test-1
spec:
containers:
- name: uses-private-image
image: $PRIVATE_IMAGE_NAME
imagePullPolicy: Always
command: [ "echo", "SUCCESS" ]
EOF
pod/private-image-test-1 created
만약 모든 것이 잘 작동한다면, 잠시 후에, 다음 메시지를 볼 것이다.
kubectl logs private-image-test-1
SUCCESS
만약 실패했다면, 다음 메시지를 볼 것이다.
kubectl describe pods/private-image-test-1 | grep "Failed"
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
클러스터의 모든 노드가 반드시 동일한 .docker/config.json
를 가져야 한다. 그렇지 않으면, 파드가
일부 노드에서만 실행되고 다른 노드에서는 실패할 것이다. 예를 들어, 노드 오토스케일링을 사용한다면, 각 인스턴스
템플릿은 .docker/config.json
을 포함하거나 그것을 포함한 드라이브를 마운트해야 한다.
프라이빗 레지스트리 키가 .docker/config.json
에 추가되고 나면 모든 파드는
프라이빗 레지스트리의 이미지에 읽기 접근 권한을 가지게 될 것이다.
참고: Google 쿠버네티스 엔진에서 동작 중이라면, 이미 각 노드에 Google 컨테이너 레지스트리에 대한 자격 증명과 함께.dockercfg
가 있을 것이다. 그렇다면 이 방법은 쓸 수 없다.
참고: 이 방법은 노드의 구성을 제어할 수 있는 경우에만 적합하다. 이 방법은 GCE 및 자동 노드 교체를 수행하는 다른 클라우드 제공자에 대해서는 신뢰성 있게 작동하지 않을 것이다.
기본적으로, kubelet은 지정된 레지스트리에서 각 이미지를 풀 하려고 할 것이다.
그러나, 컨테이너의 imagePullPolicy
속성이 IfNotPresent
또는 Never
으로 설정되어 있다면,
로컬 이미지가 사용된다(우선적으로 또는 배타적으로).
레지스트리 인증의 대안으로 미리 풀 된 이미지에 의존하고 싶다면, 클러스터의 모든 노드가 동일한 미리 풀 된 이미지를 가지고 있는지 확인해야 한다.
이것은 특정 이미지를 속도를 위해 미리 로드하거나 프라이빗 레지스트리에 대한 인증의 대안으로 사용될 수 있다.
모든 파드는 미리 풀 된 이미지에 대해 읽기 접근 권한을 가질 것이다.
참고: 이 방법은 현재 Google 쿠버네티스 엔진, GCE 및 노드 생성이 자동화된 모든 클라우드 제공자에게 권장된다.
쿠버네티스는 파드에 레지스트리 키를 명시하는 것을 지원한다.
대문자 값을 적절히 대체하여, 다음 커맨드를 실행한다.
kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret/myregistrykey created.
만약 다중 레지스트리에 접근이 필요하다면, 각 레지스트리에 대한 하나의 시크릿을 생성할 수 있다.
Kubelet은 파드를 위한 이미지를 풀링할 때 imagePullSecrets
를 단일의 가상 .docker/config.json
에 병합할 것이다.
파드는 이미지 풀 시크릿을 자신의 네임스페이스에서만 참조할 수 있다. 따라서 이 과정은 네임스페이스 당 한 번만 수행될 필요가 있다.
어떤 이유에서 단일 .docker/config.json
에 여러 항목이 필요하거나
위의 커맨드를 통해서는 주어지지 않는 제어가 필요한 경우, json 또는 yaml로
시크릿 생성을 수행할 수 있다.
다음 사항을 준수해야 한다.
.dockerconfigjson
에 해당 데이터 항목의 이름을 설정data[".dockerconfigjson"]
필드의 값으로써 깨짐 방지kubernetes.io/dockerconfigjson
에 type
을 설정예:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: awesomeapps
data:
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
type: kubernetes.io/dockerconfigjson
error: no objects passed to create
라는 에러 메시지가 나오면, 그것은 base64 인코딩된 문자열이 유효하지 않다는 것을 뜻한다.
Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...
와 유사한 에러 메시지가 나오면, 그것은
base64 인코딩 된 데이터가 성공적으로 디코딩되었지만, .docker/config.json
파일로는 파싱될 수 없었음을 의미한다.
이제, imagePullSecrets
섹션을 파드의 정의에 추가함으로써 해당 시크릿을
참조하는 파드를 생성할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
이것은 프라이빗 레지스트리를 사용하는 각 파드에 대해서 수행될 필요가 있다.
그러나, 이 필드의 셋팅은 서비스 어카운트 리소스에 imagePullSecrets을 셋팅하여 자동화할 수 있다. 자세한 지침을 위해서는 서비스 어카운트에 ImagePullSecrets 추가를 확인한다.
이것은 노드 당 .docker/config.json
와 함께 사용할 수 있다. 자격 증명은
병합될 것이다. 이 방법은 Google 쿠버네티스 엔진에서 작동될 것이다.
프라이빗 레지스트리를 구성하기 위한 많은 솔루션이 있다. 다음은 여러 가지 일반적인 유스케이스와 제안된 솔루션이다.
imagePullSecrets
를 사용한다.이 페이지가 도움이 되었나요?
Thanks for the feedback. If you have a specific, answerable question about how to use Kubernetes, ask it on Stack Overflow. Open an issue in the GitHub repo if you want to report a problem or suggest an improvement.