레지스트리 다이제스트로 이미지 설치하기
오퍼레이터 설치에서 이미지 태그 대신 변경 불가능한 컨테이너 레지스트리 다이제스트로 Calico 이미지를 배포하는 방법을 안내해요. ImageSet 리소스로 각 이미지를 고정하면 보안 팀이 이미지를 검토하고 검증할 수 있어요.
출처: 문서
본문
큰 그림
오퍼레이터 설치에서 컨테이너 레지스트리 다이제스트로 이미지를 배포해요.
가치
일부 배포 환경은 태그 대신 변경 불가능한 다이제스트로 이미지를 배포하도록 엄격한 보안 요구 사항을 갖고 있어요. 공식 Calico 이미지와 태그는 한번 릴리스되면 수정되지 않지만, 변경 불가능한 다이제스트를 사용하면 보안 팀이 특정 이미지를 검토하고 검증할 수 있어요.
개념
컨테이너 레지스트리
컨테이너 레지스트리는 태그나 다이제스트로 참조되는 컨테이너 이미지에 접근할 수 있게 해줘요.
이미지 태그
버전이 붙은 컨테이너 이미지는 보통 이미지 참조 뒤에 붙는 태그로 참조해요. 예: <repo>/<image>:<tag>. 컨테이너 이미지 태그는 보통 변경되거나 업데이트되지 않을 것으로 기대하지만, 대부분의 이미지 레지스트리는 이를 요구하거나 강제하지 않아요. 즉 같은 이미지 태그에 새 코드를 푸시할 수도 있어요.
이미지 다이제스트
컨테이너 이미지는 컨테이너 레지스트리에 추가될 때 고유한 해시가 만들어져요. 이 해시를 사용하면 변경하거나 업데이트할 수 없는 특정 버전의 이미지를 pull할 수 있어요.
시작하기 전에
필수 요건
- 오퍼레이터가 관리하는 Calico
- 이미지가 저장된 컨테이너 레지스트리에서 이미지를 pull하도록 구성된 Docker 클라이언트
- ImageSet 매니페스트를 클러스터에 적용할 수 있는 Kubernetes 권한
방법
다른 작업
문제 해결
오퍼레이터 배포를 다이제스트로 업데이트하기
tigera-operator.yaml를 적용하기 전에 오퍼레이터 배포가 오퍼레이터 이미지 다이제스트를 사용하도록 수정해요.
다음과 같은 명령으로 이미지 다이제스트를 구해요 (다른 오퍼레이터 이미지를 사용한다면 명령의 이미지를 조정하세요):
docker pull quay.io/tigera/operator:v1.44.0
docker inspect quay.io/tigera/operator:v1.44.0 -f '{{range .RepoDigests}}{{printf "%s\n" .}}{{end}}'
여러 다이제스트가 반환되면 사용 중인 레지스트리와 일치하는 것을 고르세요.
tigera-operator 배포를 업데이트해요:
sed -ie "s|\(image: .*/operator\):.*|?\1@<put-digest-here>|" tigera-operator.yaml
ImageSet 만들기
다음과 같이 imageset.yaml이라는 이름의 ImageSet 매니페스트 파일을 만들어요:
apiVersion: operator.tigera.io/v1
kind: ImageSet
metadata:
name: calico-v3.33.0
spec:
images:
- image: 'calico/apiserver'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'calico/cni'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'calico/kube-controllers'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'calico/node'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'calico/typha'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'calico/pod2daemon-flexvol'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'calico/node-windows'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'tigera/operator'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
- image: 'tigera/key-cert-provisioner'
digest: 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
ImageSet 매니페스트는 수동으로 만들 수도 있고 스크립트로 만들 수도 있어요.
Tab: 수동
-
위 예시를
imageset.yaml파일로 복사하고 아래 단계에서 그 파일을 편집해요. -
ImageSet 이름을
calico-<version>으로 정해요 (예:calico-v3.33.0). 버전은 다음 명령으로 알 수 있어요:docker run quay.io/tigera/operator:v1.44.0 --version -
각 이미지에 올바른 다이제스트를 추가해요. 프라이빗 레지스트리를 사용한다면 프라이빗 레지스트리에서 이미지를 pull하고 프라이빗 레지스트리와 연결된 다이제스트를 사용해야 해요.
-
기본 이미지를 사용한다면 다음 명령으로 목록을 구해요:
docker run quay.io/tigera/operator:v1.44.0 --print-images=listSECONDARY: 기본 이미지 레지스트리나 경로를 사용하지 않는다면 이미지 목록을 직접 만들어야 해요 (위 명령은 적용되지 않아요).
SECONDARY: 목록에는 Enterprise 배포용 이미지도 포함되지만 ImageSet에 추가할 필요는 없어요.
-
위 단계에서 반환된 이미지를 다음 명령에 사용해 필요한 다이제스트를 구해요:
docker pull <repo/image:tag> && docker inspect <repo/image:tag> -f '{{range .RepoDigests}}{{printf "%s\n" .}}{{end}}' -
사용할 repo/image와 일치하는 이미지의 다이제스트를 사용해요. 프라이빗 레지스트리를 사용하거나 imagePath를 지정했더라도
image필드에는 여전히 "기본"<owner>/<image>를 사용해요. 예를 들어 노드 이미지가example.com/registry/imagepath/node에서 온다면 ImageSet의 image 필드에는 여전히calico/node를 사용해요.SECONDARY: 이미지
quay.io/tigera/operator@sha256:d111db2f94546415a30eff868cb946d47e183faa804bd2e9a758fd9a8a4eaff1의 경우@뒤의 내용을 모두 복사해tigera/operator이미지의 다이제스트로 추가해요.
-
Tab: 스크립트
다음 스크립트를 파일로 복사하고 실행 권한을 준 다음 실행해요. 스크립트는 실행된 디렉터리에 imageset.yaml 파일을 만들어요.
SECONDARY: 이 스크립트는 기본 레지스트리와 이미지 경로를 사용할 때만 동작해요.
#!/bin/bash -e
images=(calico/apiserver calico/cni calico/kube-controllers calico/node calico/typha calico/pod2daemon-flexvol calico/node-windows tigera/key-cert-provisioner tigera/operator)
OPERATOR_IMAGE=quay.io/tigera/operator:v1.44.0
echo "Pulling $OPERATOR_IMAGE"
echo
docker pull $OPERATOR_IMAGE -q >/dev/null
versions=$(docker run $OPERATOR_IMAGE --version)
ver=$(echo -e "$versions" | grep 'Calico:')
imagelist=($(docker run $OPERATOR_IMAGE --print-images=list))
cat > ./imageset.yaml <<EOF
apiVersion: operator.tigera.io/v1
kind: ImageSet
metadata:
name: calico-$(echo $ver | sed -e 's|^.*: *||')
spec:
images:
EOF
for x in "${imagelist[@]}"; do
for y in ${images[*]}; do
if [[ $x =~ $y: ]]; then
digest=$(docker run --rm gcr.io/go-containerregistry/crane:v0.7.0 digest ${x})
echo "Adding digest for $x"
echo
echo " - image: \"$(echo $x | sed -e 's|^.*/\([^/]*/[^/]*\):.*$|\1|')\"" >> ./imageset.yaml
echo " digest: \"$digest\"" >> ./imageset.yaml
fi
done
done
만든 imageset.yaml을 클러스터에 적용해요.
올바른 ImageSet이 사용되고 있는지 확인하기
-
kubectl get tigerastatus로 Degraded 상태인 컴포넌트가 있는지 확인해요.- Degraded로 표시되는 컴포넌트가 있다면 더 자세히 조사하세요.
-
모든 컴포넌트의 tigerastatus가 Available True를 보이면 ImageSet이 적용된 거예요.
NAME AVAILABLE PROGRESSING DEGRADED SINCE calico True False False 54s -
올바른 ImageSet이 사용되고 있는지 확인해요. Installation 상태에서
imageset필드가 여러분이 만든 ImageSet으로 설정됐는지 확인해요. 다음 명령으로 필드를 확인할 수 있어요:kubectl get installation default -o yaml | grep imageSet다음과 비슷한 출력이 보여야 해요:
imageSet: calico-v3.33.0
다른 작업
업그레이드 또는 다운그레이드할 때 새 ImageSet 만들기
새 릴리스로 업그레이드하거나 다운그레이드하기 전에, 새 릴리스에 맞는 이미지 참조와 이름으로 새 ImageSet을 만들어야 해요. 클러스터를 업그레이드하기 전에 이 작업을 해야 새 매니페스트를 적용할 때 적절한 ImageSet이 준비돼 있어요.
문제 해결
Installation 리소스 상태에 내 ImageSet이 없는 이유는?
Installation 리소스의 status.imageset 필드는 calico 컴포넌트가 완전히 배포되기 전까지는 업데이트되지 않아요. kubectl get tigerastatus calico가 Progressing과 Degraded가 False인 상태에서 Available True를 보고하면 calico가 완전히 배포된 거예요.
ImageSet에 문제가 있는지 어떻게 알 수 있나요?
ImageSet에 문제가 의심되면 kubectl get tigerastatus로 확인해요. Degraded 상태인 컴포넌트가 있다면 kubectl get tigerastatus <component-name> -o yaml로 추가 정보를 얻을 수 있어요. 이미지에 제공한 다이제스트가 잘못됐거나 pull할 수 없는 경우 tigerastatus가 그 정보를 직접 보고하지는 않지만, Deployment나 Daemonset, Job을 롤아웃하는 데 문제가 있다는 정보는 보게 돼요. 이미지 문제로 리소스 롤아웃에 문제가 의심되면 특정 파드를 get이나 describe해서 문제의 세부 사항을 확인해야 해요.
더 알아보기 (Learn more)
이미지 태그는 언제든 바뀔 수 있지만 다이제스트는 변경 불가능하다는 점이 핵심이에요. ImageSet을 활용하면 보안 요구 사항이 엄격한 환경에서도 검증된 이미지 버전을 고정해 배포할 수 있어요.