
GSP479
개요
Kubernetes 클러스터를 실행할 때의 주요 보안 문제 중 하나는 각 포드 내에서 실행되는 컨테이너 이미지가 무엇인지 알고 그 출처를 알아야 한다는 것입니다. '컨테이너 출처'를 설정한다는 것은 컨테이너의 소스를 신뢰할 수 있는 원래의 지점으로 추적하고 조직에서 아티팩트(컨테이너) 생성 중에 그 과정을 따라 요구되는 프로세스를 따르도록 할 수 있다는 의미입니다.
주요 우려사항은 다음과 같습니다.
-
안전한 출처 - 클러스터에서 실행되는 모든 컨테이너 이미지가 승인된 출처에서 제공되도록 하려면 어떻게 해야 하는가?
-
일관성 및 검증 - 모든 컨테이너 빌드 및 모든 배포에 대해 원하는 모든 검증 단계가 성공적으로 완료되었는지 어떻게 확인할 것인가?
-
무결성 - 출처가 증명된 후 실행되기 전에 컨테이너가 수정되지 않았는지 어떻게 확인할 수 있는가?
보안 관점에서 이미지가 어디에서 왔는지 설정하지 않으면 다음과 같은 여러 위험이 발생합니다.
- 컨테이너를 보안 침해한 악의적인 행위자는 알 수 없는 소스에서 시행 없이 다른 컨테이너를 실행할 수 있는 충분한 클러스터 권한을 획득할 수 있습니다.
- 포드 생성 권한이 있는 승인된 사용자가 실수나 악의적으로 클러스터 내에서 권한 없는 컨테이너를 직접 실행할 수 있습니다.
- 권한 있는 사용자가 의도치 않게 또는 악의적으로 권한 없는 코드가 자동으로 추가된 기능 컨테이너로 Docker 이미지 태그를 덮어쓸 수 있으며, Kubernetes는 배포의 일부로 해당 컨테이너를 자동으로 가져와 배포합니다.
시스템 운영자가 이러한 문제를 해결할 수 있도록 Google Cloud에서는 Binary Authorization이라는 기능을 제공합니다. Binary Authorization은 GKE와 긴밀하게 연동되어 신뢰할 수 있는 컨테이너 이미지만 배포되도록 배포 시점 보안 제어를 시행하는 Google Cloud 관리형 서비스입니다. Binary Authorization을 사용하면 아티팩트 레지스트리를 허용 목록에 추가하고, 신뢰할 수 있는 기관에서 이미지에 서명하도록 요구하고, 이러한 정책을 중앙에서 적용할 수 있습니다. 이 정책을 시행하면 승인되거나 확인된 이미지만 빌드 및 출시 프로세스에 통합되어 컨테이너 환경을 보다 확실하게 제어할 수 있습니다.
이 실습에서는 Binary Authorization 기능이 사용 설정된 Kubernetes Engine 클러스터를 배포하고, 승인된 아티팩트 레지스트리를 허용 목록에 추가하는 방법을 보여주며, 서명된 컨테이너를 만들고 실행하는 과정을 안내합니다.
이 실습은 GKE Binary Authorization을 더 잘 이해할 수 있도록 GKE Helmsman 엔지니어가 제작했습니다. 누구나 Google의 애셋에 참여할 수 있습니다.
아키텍처
Binary Authorization 및 Container Analysis API는 오픈소스 프로젝트인 Grafeas 및 Kritis를 기반으로 합니다.
- Grafeas는 컨테이너 이미지, 가상 머신(VM) 이미지, JAR 파일, 스크립트와 같은 소프트웨어 리소스에 관한 메타데이터를 관리하기 위한 API 사양을 정의합니다. Grafeas를 사용하여 프로젝트 구성요소에 관한 정보를 정의하고 집계할 수 있습니다.
- Kritis는 아티팩트(컨테이너 이미지)가 중앙 정책을 준수하고 필요한 증명(선택사항)이 있는 경우에만 배포가 허용되도록 하는 API를 정의합니다.
다음과 같은 간단한 컨테이너 배포 파이프라인에서

컨테이너는 다음 4단계를 거칩니다.
- 컨테이너를 만드는 소스 코드가 소스 제어에 저장됩니다.
- 소스 제어 시스템에 변경사항을 커밋하면 컨테이너가 빌드되고 테스트됩니다.
- 빌드 및 테스트 단계가 완료되면 컨테이너 이미지 아티팩트가 중앙 아티팩트 레지스트리에 배치되어 배포할 준비를 마칩니다.
- 해당 컨테이너 버전의 배포가 Kubernetes API에 제출되면 컨테이너 런타임이 아티팩트 레지스트리에서 해당 컨테이너 이미지를 가져와 포드로 실행합니다.
컨테이너 빌드 파이프라인에서는 각 단계가 성공적으로 완료되었음을 나타내거나 '증명'하기 위해 추가 프로세스를 삽입할 수 있습니다. 예를 들어 단위 테스트 실행, 소스 제어 분석 검사, 라이선스 확인, 취약점 분석 등이 있습니다. 각 단계에 해당 단계가 완료되었음을 서명할 수 있는 권한 또는 '증명 기관'이 부여될 수 있습니다. '증명 기관'은 올바른 PGP 키를 보유하고 Container Analysis API에 '증명'을 등록할 수 있는 사람 또는 시스템입니다.
각 단계에 별도의 PGP 키를 사용하면 각 증명 단계를 파이프라인의 서로 다른 사람, 시스템 또는 빌드 단계에서 실행할 수 있습니다(a). 각 PGP 키는 Container Analysis API에 저장된 '증명 메모'와 연결됩니다. 빌드 단계에서 이미지를 '서명'하면 해당 이미지에 관한 JSON 메타데이터 스니펫이 PGP를 통해 서명되고 서명된 스니펫이 API에 '메모 발생'으로 제출됩니다.

(b).컨테이너 이미지가 빌드되고 필요한 증명이 중앙에 저장되면 정책 결정 프로세스의 일부로 쿼리할 수 있습니다. 이 경우 Kubernetes 허용 컨트롤러는 포드를 create하거나 update하는 API 요청을 수신하면 다음을 실행합니다.
- 정책 결정을 위해 Binary Authorization API에 웹훅을 보냅니다.
- 그러면 Binary Authorization 정책을 참조합니다.
- 필요한 경우 Container Analysis API에 필요한 증명 발생도 쿼리됩니다.
- 컨테이너 이미지가 정책을 준수하면 실행이 허용됩니다.
- 컨테이너 이미지가 정책을 충족하지 않으면 차단된 이유를 설명하는 메시지와 함께 오류가 API 클라이언트에 표시됩니다.

설정 및 요건
실습 시작 버튼을 클릭하기 전에
다음 안내를 확인하세요. 실습에는 시간 제한이 있으며 일시중지할 수 없습니다. 실습 시작을 클릭하면 타이머가 시작됩니다. 이 타이머는 Google Cloud 리소스를 사용할 수 있는 시간이 얼마나 남았는지를 표시합니다.
실무형 실습을 통해 시뮬레이션이나 데모 환경이 아닌 실제 클라우드 환경에서 실습 활동을 진행할 수 있습니다. 실습 시간 동안 Google Cloud에 로그인하고 액세스하는 데 사용할 수 있는 새로운 임시 사용자 인증 정보가 제공됩니다.
이 실습을 완료하려면 다음을 준비해야 합니다.
- 표준 인터넷 브라우저 액세스 권한(Chrome 브라우저 권장)
참고: 이 실습을 실행하려면 시크릿 모드(권장) 또는 시크릿 브라우저 창을 사용하세요. 개인 계정과 학습자 계정 간의 충돌로 개인 계정에 추가 요금이 발생하는 일을 방지해 줍니다.
- 실습을 완료하기에 충분한 시간(실습을 시작하고 나면 일시중지할 수 없음)
참고: 이 실습에는 학습자 계정만 사용하세요. 다른 Google Cloud 계정을 사용하는 경우 해당 계정에 비용이 청구될 수 있습니다.
실습을 시작하고 Google Cloud 콘솔에 로그인하는 방법
-
실습 시작 버튼을 클릭합니다. 실습 비용을 결제해야 하는 경우 결제 수단을 선택할 수 있는 대화상자가 열립니다.
왼쪽에는 다음과 같은 항목이 포함된 실습 세부정보 창이 있습니다.
- Google Cloud 콘솔 열기 버튼
- 남은 시간
- 이 실습에 사용해야 하는 임시 사용자 인증 정보
- 필요한 경우 실습 진행을 위한 기타 정보
-
Google Cloud 콘솔 열기를 클릭합니다(Chrome 브라우저를 실행 중인 경우 마우스 오른쪽 버튼으로 클릭하고 시크릿 창에서 링크 열기를 선택합니다).
실습에서 리소스가 가동되면 다른 탭이 열리고 로그인 페이지가 표시됩니다.
팁: 두 개의 탭을 각각 별도의 창으로 나란히 정렬하세요.
참고: 계정 선택 대화상자가 표시되면 다른 계정 사용을 클릭합니다.
-
필요한 경우 아래의 사용자 이름을 복사하여 로그인 대화상자에 붙여넣습니다.
{{{user_0.username | "Username"}}}
실습 세부정보 창에서도 사용자 이름을 확인할 수 있습니다.
-
다음을 클릭합니다.
-
아래의 비밀번호를 복사하여 시작하기 대화상자에 붙여넣습니다.
{{{user_0.password | "Password"}}}
실습 세부정보 창에서도 비밀번호를 확인할 수 있습니다.
-
다음을 클릭합니다.
중요: 실습에서 제공하는 사용자 인증 정보를 사용해야 합니다. Google Cloud 계정 사용자 인증 정보를 사용하지 마세요.
참고: 이 실습에 자신의 Google Cloud 계정을 사용하면 추가 요금이 발생할 수 있습니다.
-
이후에 표시되는 페이지를 클릭하여 넘깁니다.
- 이용약관에 동의합니다.
- 임시 계정이므로 복구 옵션이나 2단계 인증을 추가하지 않습니다.
- 무료 체험판을 신청하지 않습니다.
잠시 후 Google Cloud 콘솔이 이 탭에서 열립니다.
참고: Google Cloud 제품 및 서비스에 액세스하려면 탐색 메뉴를 클릭하거나 검색창에 제품 또는 서비스 이름을 입력합니다.
Cloud Shell 활성화
Cloud Shell은 다양한 개발 도구가 탑재된 가상 머신으로, 5GB의 영구 홈 디렉터리를 제공하며 Google Cloud에서 실행됩니다. Cloud Shell을 사용하면 명령줄을 통해 Google Cloud 리소스에 액세스할 수 있습니다.
-
Google Cloud 콘솔 상단에서 Cloud Shell 활성화
를 클릭합니다.
-
다음 창을 클릭합니다.
- Cloud Shell 정보 창을 통해 계속 진행합니다.
- 사용자 인증 정보를 사용하여 Google Cloud API를 호출할 수 있도록 Cloud Shell을 승인합니다.
연결되면 사용자 인증이 이미 처리된 것이며 프로젝트가 학습자의 PROJECT_ID, (으)로 설정됩니다. 출력에 이 세션의 PROJECT_ID를 선언하는 줄이 포함됩니다.
Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}
gcloud는 Google Cloud의 명령줄 도구입니다. Cloud Shell에 사전 설치되어 있으며 명령줄 자동 완성을 지원합니다.
- (선택사항) 다음 명령어를 사용하여 활성 계정 이름 목록을 표시할 수 있습니다.
gcloud auth list
-
승인을 클릭합니다.
출력:
ACTIVE: *
ACCOUNT: {{{user_0.username | "ACCOUNT"}}}
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (선택사항) 다음 명령어를 사용하여 프로젝트 ID 목록을 표시할 수 있습니다.
gcloud config list project
출력:
[core]
project = {{{project_0.project_id | "PROJECT_ID"}}}
참고: gcloud 전체 문서는 Google Cloud에서 gcloud CLI 개요 가이드를 참고하세요.
작업 1. 리소스 복사
- 이제 다음을 실행하여 이 실습에 필요한 리소스를 복사합니다.
gsutil -m cp -r gs://spls/gke-binary-auth/* .
- 이 데모의 디렉터리로 이동합니다.
cd gke-binary-auth-demo
리전 및 영역 설정하기
특정 Compute Engine 리소스는 여러 리전과 영역에 위치합니다. 리전은 리소스를 실행할 수 있는 특정한 지리적 위치로, 각 리전에는 영역이 하나 이상 있습니다.
참고: 리전 및 영역 문서에서 리전과 영역에 관해 자세히 알아보고 전체 목록을 확인하세요.
실습에서 리전과 영역을 설정하려면 다음을 실행하세요(자신에게 가장 적합한 리전/영역을 사용할 수 있음).
gcloud config set compute/region {{{ project_0.default_region | REGION }}}
gcloud config set compute/zone {{{ project_0.default_zone | ZONE }}}
파일 권한 업데이트
- 이제 이 실습에 필요한 리소스에 대해 파일을 읽기, 쓰기, 실행 가능하도록 설정합니다.
chmod +x create.sh
chmod +x delete.sh
chmod 777 validate.sh
작업 2. 기본 클러스터 버전 설정
-
create.sh의 GKE_VERSION 변수를 defaultClusterVersion으로 변경합니다.
sed -i 's/validMasterVersions\[0\]/defaultClusterVersion/g' ./create.sh
참고: 기본 클러스터 버전은 이 실습의 다른 종속 항목과 호환됩니다.
작업 3. 배포 단계
참고: 다음 안내는 Cloud Shell을 사용하거나 사용하지 않고 실행한 배포에 적용됩니다.
- 클러스터를 배포하려면 다음 명령어를 실행합니다.
my-cluster-1 텍스트를 만들려는 클러스터의 이름으로 바꿔도 됩니다.
./create.sh -c my-cluster-1
create 스크립트가 완료되면 다음 메시지가 출력됩니다.
kubeconfig entry generated for my-cluster-1.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
my-cluster-1 {{{project_0.default_zone | Zone}}} 1.14.8-gke.17 104.154.181.211 n1-standard-1 1.14.8-gke.17 2 RUNNING
Fetching cluster endpoint and auth data.
kubeconfig entry generated for my-cluster-1.
스크립트는 다음을 수행합니다.
- 프로젝트에서 필요한 API를 사용 설정합니다. 구체적으로
container, containerregistry, containeranalysis, binaryauthorization입니다.
- 기본 영역, VPC, 네트워크에 새 Kubernetes Engine 클러스터를 만듭니다.
-
kubectl 사용을 위해 클러스터 사용자 인증 정보를 가져옵니다.
경고는 무시해도 됩니다.
작업 4. 검증
- 다음 스크립트는 데모가 올바르게 배포되었는지 확인합니다.
./validate.sh -c my-cluster-1
스크립트가 실패하면 다음이 출력됩니다.
Validation Failed: the BinAuthZ policy was NOT available
및/또는
Validation Failed: the Container Analysis API was NOT available
스크립트가 통과되면 다음이 출력됩니다.
Validation Passed: the BinAuthZ policy was available
Validation Passed: the Container Analysis API was available
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. Binary Authorization으로 Kubernetes 클러스터를 생성하면 평가 점수가 표시됩니다.
Binary Authorization으로 Kubernetes 클러스터 만들기
작업 5. Binary Authorization 사용
Binary Authorization 정책 관리
Binary Authorization 정책 구성 UI에 액세스하려면 다음 단계를 수행하세요.
- Google Cloud 콘솔에서 보안 > Binary Authorization으로 이동합니다.

-
정책 수정을 클릭합니다.

참고: gcloud를 통해 Binary Authorization 정책 구성에 액세스하려면 다음을 따르세요.
gcloud beta container binauthz policy export > policy.yaml을 실행합니다.
policy.yaml을 필요한 대로 수정합니다.
gcloud beta container binauthz policy import policy.yaml을 실행합니다.
수정 중인 정책은 '기본' 정책이며, 클러스터별 정책이 없는 한 Google Cloud 프로젝트의 모든 GKE 클러스터에 적용됩니다.
각 클러스터에 맞는 정책을 만들어 성공적인 작업을 달성(필요에 따라 레지스트리 허용 목록에 추가)한 다음 기본 프로젝트 수준 정책을 '모든 이미지 거부'로 설정하는 것이 좋습니다. 이 프로젝트의 새 클러스터에는 클러스터별 정책이 필요합니다.
-
정책 수정을 클릭하면 다음이 표시됩니다.

기본 정책 규칙은 Allow all images입니다. 이는 클러스터에서 Binary Authorization이 사용 설정되지 않은 것과 같은 동작을 모방합니다.
기본 규칙이 Disallow all images 또는 Allow only images that have been approved by all of the following attestors로 변경되면 면제된 레지스트리 이미지 경로와 일치하지 않거나 필요한 증명이 없는 이미지가 각각 차단됩니다.
다음으로 정책을 수정합니다.
-
기본 규칙을 Disallow all images로 변경합니다.
-
'GKE 및 Anthos 배포를 위한 추가 설정'에서 특정 규칙 만들기를 클릭합니다.
-
드롭다운에서 GKE 클러스터를 선택하고 변경을 클릭합니다.
-
GKE 클러스터별 규칙에서 특정 규칙 추가를 클릭합니다.
-
GKE 클러스터별 규칙 추가 필드에 location.clustername 형식으로 위치와 클러스터 이름을 입력합니다. 예를 들면 .my-cluster-1입니다(영역 , 클러스터 이름 my-cluster-1).
-
클러스터의 기본 규칙으로 Allow all images를 선택합니다.
-
추가를 클릭합니다.

-
정책 저장을 클릭합니다.
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. 프로젝트 수준에서 '모든 이미지 허용 안 함' 규칙을 추가하고 클러스터 수준에서 모든 이미지를 허용하도록 Binary Authorization 정책을 업데이트하면 평가 점수가 표시됩니다.
프로젝트 수준에서 '모든 이미지 허용 안 함' 규칙을 추가하고 클러스터 수준에서 허용하도록 Binary Authorization 정책 업데이트
작업 6. 비공개 GCR 이미지 만들기
-
실제 구성을 시뮬레이션하려면 프로젝트에서 비공개 GCR 컨테이너 이미지를 만드세요.
-
nginx 프로젝트에서 nginx 컨테이너를 가져와 수정 없이 자체 GCR 저장소에 푸시합니다.
-
Cloud Shell에서 latest nginx 컨테이너를 가져옵니다.
docker pull nginx:latest
- 프로젝트에 Docker를 인증합니다.
gcloud auth configure-docker
Do you want to continue (Y/n)? 메시지가 표시되면 Y를 입력합니다.
- PROJECT_ID 셸 변수를 설정합니다.
PROJECT_ID="$(gcloud config get-value project)"
- 태그를 지정하고 현재 프로젝트의 GCR로 푸시합니다.
docker tag nginx "gcr.io/${PROJECT_ID}/nginx:latest"
docker push "gcr.io/${PROJECT_ID}/nginx:latest"
- 자체 GCR 저장소에서 '비공개' nginx 이미지를 나열합니다.
gcloud container images list-tags "gcr.io/${PROJECT_ID}/nginx"
작업 7. 모든 이미지 거부
정책에 의한 이미지 거부가 결국 의도한 대로 작동하는지 증명하려면 먼저 클러스터별 allow 규칙이 적용되어 모든 컨테이너가 실행되도록 허용하는지 확인합니다.
- 이렇게 하려면 단일
nginx 포드를 실행하세요.
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "gcr.io/${PROJECT_ID}/nginx:latest"
ports:
- containerPort: 80
EOF
pod/nginx created라는 메시지가 표시됩니다.
- 포드를 나열합니다.
kubectl get pods
출력:
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 1m
이 경우 클러스터별 리전과 이름을 다시 확인하고 다시 시도하세요.
- 이제 이 포드를 삭제합니다.
kubectl delete pod nginx
- 그런 다음 Binary Authorization 정책이 원치 않는 이미지가 클러스터에서 실행되지 않도록 차단할 수 있음을 증명합니다.
Binary Authorization 페이지에서 정책 수정을 클릭합니다.
-
GKE 클러스터별 규칙 오른쪽에 있는 세로 점 3개를 클릭하고 수정을 클릭합니다.
-
그런 다음 Disallow all images를 선택하고 제출을 클릭합니다.
정책은 다음과 유사해야 합니다.

- 마지막으로 정책 저장을 클릭하여 변경사항을 적용합니다.
참고: 정책이 적용될 때까지 최소 30초 동안 기다린 후 다음 단계를 진행하세요.
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. 클러스터 수준에서 '모든 이미지 허용 안 함' 규칙을 적용하도록 Binary Authorization 정책을 업데이트하면 평가 점수가 표시됩니다.
모든 이미지를 허용하지 않도록 클러스터별 정책 업데이트
- 이제 이전과 동일한 명령어를 실행하여 정적
nginx 포드를 만듭니다.
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "gcr.io/${PROJECT_ID}/nginx:latest"
ports:
- containerPort: 80
EOF
이번에는 정책으로 인해 이 포드가 성공적으로 실행되지 않았음을 나타내는 API 서버의 메시지가 표시됩니다.
Error from server (VIOLATES_POLICY): error when creating "STDIN": admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/qwiklabs-gcp-00-ce851250686b/nginx:latest denied by Binary Authorization cluster admission rule for {{{project_0.default_zone | Zone}}}.my-cluster-1. Denied by always_deny admission rule
Binary Authorization 정책에 의해 이미지가 차단되는 시점을 확인하려면 Stackdriver의 GKE 감사 로그로 이동하여 이 활동과 관련된 오류 메시지를 필터링하세요.
- Google Cloud 콘솔에서 탐색 메뉴 > Logging > 로그 탐색기로 이동합니다.
-
쿼리 빌더 상자를 다음으로 채웁니다.
resource.type="k8s_cluster" protoPayload.response.reason="VIOLATES_POLICY"

-
쿼리 실행을 클릭합니다.
-
nginx 포드의 실행이 차단됨에 해당하는 오류가 표시됩니다.
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. 클러스터 허용 규칙이 확인되면 평가 점수가 표시됩니다.
Nginx 포드를 만들어 클러스터 허용 규칙이 모든 이미지 허용 안 함(생성 거부)에 적용되었는지 확인
작업 8. 허용 목록에 추가된 아티팩트 레지스트리를 제외한 이미지 거부
-
실제로 해당 nginx 컨테이너만 실행하도록 허용하고 싶다고 가정해 보겠습니다. 이 기능을 사용 설정하는 가장 빠른 방법은 레지스트리가 제공되는 레지스트리를 허용 목록에 추가하는 것입니다.
-
다음 명령어의 출력을 이미지 경로로 사용합니다.
echo "gcr.io/${PROJECT_ID}/nginx*"
-
이미지 경로 출력을 버퍼에 복사합니다.
-
탐색 메뉴 > 보안 > Binary Authorization으로 이동합니다.
-
Binary Authorization 정책을 수정하고 커스텀 예외 규칙에서 이미지 경로를 표시한 다음 이미지 패턴 추가를 클릭합니다.
-
앞서 복사한 이미지 경로를 붙여넣습니다. 아래 이미지는 경로의 예를 보여줍니다.

-
정책 저장을 클릭한 후 다음을 실행합니다.
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "gcr.io/${PROJECT_ID}/nginx:latest"
ports:
- containerPort: 80
EOF
이제 이 포드를 실행하고 레지스트리 허용 목록이 올바르게 작동하는지 증명할 수 있습니다.
- 다음 명령어를 실행하여 정리하고 다음 단계를 준비합니다.
kubectl delete pod nginx
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. 아티팩트 레지스트리를 허용 목록에 추가하도록 Binary Authorization 정책을 업데이트하면 평가 점수가 표시됩니다.
허용 목록에 추가된 아티팩트 레지스트리(프로젝트 아티팩트 레지스트리)를 제외한 이미지를 거부하도록 BA 정책 업데이트
작업 9. 증명 시행
컨테이너 이미지 레지스트리를 허용 목록에 추가하는 것은 클러스터 내에서 원치 않는 컨테이너 이미지가 실행되지 않도록 하는 좋은 첫 단계이지만, 컨테이너가 올바르게 빌드되었는지 확인하기 위해 할 수 있는 작업이 더 있습니다.
특정 컨테이너 이미지가 배포 승인을 받았는지 암호화 방식으로 확인하고 싶다고 합시다. 이는 특정 단계가 완료되었다고 명시하거나 증명하는 '증명 기관'에 의해 실행됩니다. 증명 기관은 PGP 키를 사용하여 컨테이너 이미지의 SHA256 해시를 설명하는 메타데이터 스니펫에 서명하고 중앙 메타데이터 저장소인 Container Analysis API에 제출하여 이를 수행합니다.
나중에 허용 컨트롤러가 이미지에 증명이 있어야 하는 Binary Authorization 정책을 참조하여 컨테이너 이미지를 실행할 수 있는지 검증할 때 Container Analysis API에 완료된 단계를 나타내는 서명된 메타데이터 스니펫이 있는지 확인합니다. 이 정보를 통해 허용 컨트롤러는 해당 포드의 실행을 허용할지 거부할지 알 수 있습니다.
다음으로 컨테이너 이미지의 수동 증명을 실행합니다. 인간 증명 기관의 역할을 맡아 컨테이너 이미지에 서명하고, 클러스터 내에서 실행되는 이미지에 증명이 있어야 하는 정책을 만들고, 포드에서 해당 이미지를 성공적으로 실행하는 모든 단계를 수행합니다.
필요한 변수 설정
- 증명자 이름/이메일 세부정보:
ATTESTOR="manually-verified" # No spaces allowed
ATTESTOR_NAME="Manual Attestor"
ATTESTOR_EMAIL="$(gcloud config get-value core/account)" # This uses your current user/email
- 컨테이너 분석 메모 ID/증명 기관 설명:
NOTE_ID="Human-Attestor-Note" # No spaces
NOTE_DESC="Human Attestation Note Demo"
- 페이로드/요청을 만들 파일의 이름:
NOTE_PAYLOAD_PATH="note_payload.json"
IAM_REQUEST_JSON="iam_request.json"
증명 메모 만들기
첫 번째 단계는 증명 기관을 Container Analysis API를 사용하여 컨테이너 분석 메모로 등록하는 것입니다. 이렇게 하려면 ATTESTATION 메모를 만들어 API에 제출합니다.
-
ATTESTATION 메모 페이로드를 만듭니다.
cat > ${NOTE_PAYLOAD_PATH} << EOF
{
"name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
"attestation_authority": {
"hint": {
"human_readable_name": "${NOTE_DESC}"
}
}
}
EOF
- Container Analysis API에
ATTESTATION 메모를 제출합니다.
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @${NOTE_PAYLOAD_PATH} \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
이전 명령어의 출력에 생성된 메모가 표시되지만 다음 명령어에도 생성된 메모가 나열됩니다.
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
PGP 서명 키 만들기
증명 기관에서 PGP 키를 사용하여 이미지 메타데이터의 암호화 서명을 실행하므로 새 PGP 키를 만들고 공개 PGP 키를 내보냅니다.
참고: 이 오류 메시지는 이 활동과 관련이 있습니다. PGP 키는 이 실습에서 비밀번호로 보호되지 않습니다. 프로덕션 시스템에서는 비공개 PGP 키를 적절하게 보호해야 합니다.
- 다른 셸 변수를 설정합니다.
PGP_PUB_KEY="generated-key.pgp"
- PGP 키를 만듭니다.
sudo apt-get install rng-tools
sudo rngd -r /dev/urandom
gpg --quick-generate-key --yes ${ATTESTOR_EMAIL}
-
Enter 키를 눌러 빈 암호를 사용하고 경고를 확인합니다.
-
공개 PGP 키를 추출합니다.
gpg --armor --export "${ATTESTOR_EMAIL}" > ${PGP_PUB_KEY}
Binary Authorization API에 증명자 등록
다음 단계는 Binary Authorization API에서 '증명자'를 만들고 여기에 공개 PGP 키를 추가하는 것입니다.
- Binary Authorization API에서 증명자를 만듭니다.
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors create "${ATTESTOR}" \
--attestation-authority-note="${NOTE_ID}" \
--attestation-authority-note-project="${PROJECT_ID}"
- 공개 PGP 키를 증명자에 추가합니다.
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors public-keys add \
--attestor="${ATTESTOR}" \
--pgp-public-key-file="${PGP_PUB_KEY}"
- 새로 만든 증명자를 나열합니다.
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors list
출력은 다음과 비슷하게 표시됩니다.
NAME: manually-verified
NOTE: projects//notes/Human-Attestor-Note
NUM_PUBLIC_KEYS: 1
작업 10. 컨테이너 이미지에 '서명'
이전 단계는 한 번만 실행하면 됩니다. 이후부터는 새 컨테이너 이미지마다 이 단계만 반복하면 됩니다.
nginx:latest의 nginx 이미지는 이미 빌드되어 사용할 수 있습니다. 자체 프로세스로 빌드한 이미지인 것처럼 수동 증명을 실행하고 빌드 단계를 저장합니다.
- 몇 가지 셸 변수를 설정합니다.
GENERATED_PAYLOAD="generated_payload.json"
GENERATED_SIGNATURE="generated_signature.pgp"
- PGP 지문을 가져옵니다.
PGP_FINGERPRINT="$(gpg --list-keys ${ATTESTOR_EMAIL} | head -2 | tail -1 | awk '{print $1}')"
- 컨테이너 이미지의 SHA256 다이제스트를 가져옵니다.
IMAGE_PATH="gcr.io/${PROJECT_ID}/nginx"
IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
- JSON 형식의 서명 페이로드를 만듭니다.
gcloud beta container binauthz create-signature-payload \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" > ${GENERATED_PAYLOAD}
- 생성된 서명 페이로드를 확인합니다.
cat "${GENERATED_PAYLOAD}"
- PGP 키로 페이로드에 '서명'합니다.
gpg --local-user "${ATTESTOR_EMAIL}" \
--armor \
--output ${GENERATED_SIGNATURE} \
--sign ${GENERATED_PAYLOAD}
- 생성된 서명(PGP 메시지)을 확인합니다.
cat "${GENERATED_SIGNATURE}"
- 증명을 만듭니다.
gcloud beta container binauthz attestations create \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" \
--attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}" \
--signature-file=${GENERATED_SIGNATURE} \
--public-key-id="${PGP_FINGERPRINT}"
- 새로 만든 증명을 확인합니다.
gcloud beta container binauthz attestations list \
--attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR}"
작업 11. 증명 시행이 사용 설정된 이미지 실행
다음 단계는 허용 목록 패턴과 일치하지 않는 모든 이미지에 증명이 있어야 함을 강제 적용하도록 Binary Authorization 정책을 변경하는 것입니다.
- 증명을 요구하도록 정책을 변경하려면 다음을 실행한 후 증명 기관의 전체 경로/이름을 복사합니다.
echo "projects/${PROJECT_ID}/attestors/${ATTESTOR}" # Copy this output to your copy/paste buffer
- 다음으로 Binary Authorization 정책을 수정하여 GKE 클러스터별 규칙을
edit합니다.
클러스터 이름 옆에 있는 점 3개를 클릭하여 클러스터별 규칙을 수정합니다.
- 팝업 창에서
Disallow all images 대신 Require attestations (Allow only images that have been verified by all of the following attestors)를 선택합니다.

- 그런 다음
Add Attestors를 클릭하고 Add by attestor resource ID를 클릭합니다. 복사/붙여넣기 버퍼의 내용을 projects/${PROJECT_ID}/attestors/${ATTESTOR} 형식으로 입력한 다음 증명자 1명 추가를 클릭하고 제출을 클릭한 후 정책 저장을 클릭합니다.

기본 정책에는 여전히 Disallow all images가 표시되지만 클러스터별 규칙에는 증명이 필요합니다.
- 이제 이전 단계에서 서명된 이미지의 최신 SHA256 다이제스트를 가져옵니다.
IMAGE_PATH="gcr.io/${PROJECT_ID}/nginx"
IMAGE_DIGEST="$(gcloud container images list-tags --format='get(digest)' $IMAGE_PATH | head -1)"
- Binary Authorization 정책이 업데이트된 후 30초 이상 기다린 후 포드를 실행하고 성공 여부를 확인합니다.
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: "${IMAGE_PATH}@${IMAGE_DIGEST}"
ports:
- containerPort: 80
EOF
수고하셨습니다. 이제 컨테이너 이미지를 수동으로 증명하고 GKE 클러스터 내에서 해당 이미지에 대한 정책을 시행했습니다.
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. 증명자가 승인한 이미지만 허용하도록 클러스터별 규칙을 수정하여 Binary Authorization 정책을 업데이트했다면 평가 점수가 표시됩니다.
증명자가 승인한 이미지만 허용하도록 클러스터별 규칙을 수정하여 BA 정책 업데이트
작업 12. 긴급 상황 처리
사용자 관점에서 Binary Authorization 정책이 이미지를 잘못 차단하거나 허용 컨트롤러 웹훅의 성공적인 작동에 다른 문제가 있을 수 있습니다.
이러한 '긴급' 상황에는 특정 주석을 활용하여 허용 컨트롤러에 포드를 실행하고 정책 시행을 건너뛰도록 신호를 보내는 '긴급 대비' 기능이 있습니다.
참고: 악의적인 사용자가 포드를 만들 수 있는 경우 이를 악용할 수 있으므로 이 문제가 발생하면 보안팀에 알려야 합니다.
이 경우 활동이 발생한 후 몇 초 이내에 대응 절차를 시작할 수 있습니다. 로그는 Stackdriver에서 확인할 수 있습니다.
- 'breakglass' 주석으로 서명되지 않은
nginx 컨테이너를 실행하려면 다음을 실행합니다.
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-alpha
annotations:
alpha.image-policy.k8s.io/break-glass: "true"
spec:
containers:
- name: nginx
image: "nginx:latest"
ports:
- containerPort: 80
EOF
-
Google Cloud 콘솔에서 탐색 메뉴 > Logging > 로그 탐색기 페이지로 이동합니다.
-
쿼리 빌더 상자를 아래로 채운 다음 쿼리 실행을 클릭합니다.
resource.type="k8s_cluster" protoPayload.request.metadata.annotations."alpha.image-policy.k8s.io/break-glass"="true"
-
주석이 있어 허용 컨트롤러가 포드를 허용한 경우 이벤트가 표시됩니다. 이 필터에서 필터와 일치하는 로그를 외부 대상으로 전송하는 Sink를 만들 수 있습니다.

참고: 로그가 표시되려면 최소 5~10분 정도 기다려야 합니다.
작업 13. 해체
Qwiklabs는 이 실습을 위해 만든 모든 리소스를 삭제하지만, 자체 환경을 정리하는 방법을 알아두면 좋습니다.
- 다음 스크립트는 Kubernetes Engine 클러스터를 삭제합니다.
./delete.sh -c my-cluster-1
실습 시작 시 자체 클러스터 이름을 만든 경우 해당 이름을 사용합니다. 이 예에서는 my-cluster-1이라는 이름을 사용했습니다.
출력의 마지막 줄은 다음과 같습니다.
Deleting cluster
참고: 클러스터 삭제 명령어는 비동기식으로 실행되며 삭제하는 데 잠시 시간이 걸립니다. 원하는 경우 Cloud 콘솔 UI 또는 gcloud container clusters list 명령어를 사용하여 진행 상황을 추적합니다. 클러스터가 삭제될 때까지 기다립니다.
완료된 작업 테스트하기
내 진행 상황 확인하기를 클릭하여 실행한 작업을 확인합니다. 클러스터가 삭제되면 평가 점수가 표시됩니다.
해체(클러스터 삭제)
다음 명령어를 사용하면 남은 리소스가 삭제됩니다.
- GCR에 푸시된 컨테이너 이미지를 삭제합니다.
gcloud container images delete "${IMAGE_PATH}@${IMAGE_DIGEST}" --force-delete-tags
-
Do you want to continue (Y/n)?라는 메시지가 표시되면 Y를 입력합니다.
-
증명자를 삭제합니다.
gcloud --project="${PROJECT_ID}" \
beta container binauthz attestors delete "${ATTESTOR}"
- 컨테이너 분석 메모를 삭제합니다.
curl -X DELETE \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1beta1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
사용자 환경에서 문제 해결
- Binary Authorization 정책을 업데이트한 후 매우 빠르게 새 포드/컨테이너를 실행하려고 하면 정책이 적용되지 않을 수 있습니다. 정책 변경사항이 활성화되기까지 30초 이상 기다려야 할 수 있습니다. 다시 시도하려면
kubectl delete <podname>을 사용하여 포드를 삭제하고 포드 생성 명령어를 다시 제출하세요.
-
gcloud container clusters list 명령어를 실행하여 클러스터 상태를 확인합니다.
-
--enable-network-policy, --accelerator, --enable-tpu 또는 --enable-metadata-concealment와 같은 추가 기능을 사용 설정하는 경우 이러한 포드가 실행될 수 있도록 Binary Authorization 정책 허용 목록에 레지스트리를 추가해야 할 수 있습니다. kubectl describe pod <podname>을 사용하여 이미지 사양에서 레지스트리 경로를 찾고 gcr.io/example-registry/* 형식으로 허용 목록에 추가한 후 정책을 저장합니다.
- 할당량에 관한 오류가 표시되면 프로젝트에서 할당량을 늘리세요. 리소스 할당량 문서에서 리소스 할당량에 대해 자세히 알아보세요.
관련 자료
- Google Cloud 할당량
- Google Cloud 가입
- Google Cloud Shell
- GKE의 Binary Authorization
- 컨테이너 분석 메모
- Kubernetes 허용 컨트롤러
- 출시 단계
수고하셨습니다
이 실습에서는 Binary Authorization을 사용하여 Kubernetes Engine 클러스터를 배포하여 사용자 환경을 보호하는 방법을 알아봤습니다.
설명서 최종 업데이트: 2025년 2월 27일
실습 최종 테스트: 2025년 2월 27일
Copyright 2026 Google LLC. 이 소프트웨어는 사용 또는 목적에 대한 보증이나 진술 없이 있는 그대로 제공됩니다. 이 소프트웨어를 사용하는 경우 Google과의 계약이 적용됩니다.