이 튜토리얼에서는 플랫폼 관리자가 정책 컨트롤러 정책을 사용하여 구성 커넥터를 통해 Google Cloud 리소스를 만드는 방법을 관리하는 방법을 보여줍니다.
이 페이지는 감사 또는 시행 자동화를 제공하고 유지하여 클라우드 플랫폼 내에서 실행되는 모든 리소스가 조직의 규정 준수 요구사항을 충족하도록 보장하고 기본 기술 인프라의 수명 주기를 관리하는 IT 관리자와 운영자를 위해 작성되었습니다. Google Cloud 콘텐츠에서 참조하는 일반적인 역할 및 예시 작업에 대해 자세히 알아보려면 일반 GKE 기업 사용자 역할 및 태스크를 참조하세요.
이 튜토리얼의 지침은 Kubernetes 또는 Google Kubernetes Engine(GKE)에 대한 기본 지식을 갖춘 개발자를 대상으로 작성되었습니다. 이 튜토리얼에서는 Cloud Storage 버킷에 허용되는 위치를 제한하는 정책을 정의합니다.
정책 컨트롤러는 보안, 규정 또는 비즈니스 규칙과 관련된 정책을 사용하여 Kubernetes 클러스터 리소스 규정 준수를 검사, 감사, 적용합니다. 정책 컨트롤러는 OPA Gatekeeper 오픈소스 프로젝트에서 빌드됩니다.
구성 커넥터는 Kubernetes 커스텀 리소스로 Google Cloud 리소스를 설명하여 수명 주기를 만들고 관리합니다. Google Cloud 리소스를 만들려면 구성 커넥터가 관리하는 네임스페이스에 Kubernetes 리소스를 만듭니다. 다음 예시에서는 구성 커넥터를 사용하여 Cloud Storage 버킷을 설명하는 방법을 보여줍니다.
apiVersion: storage.cnrm.cloud.google.com/v1beta1 kind: StorageBucket metadata: name: my-bucket spec: location: us-east1
구성 커넥터를 사용하여 Google Cloud 리소스를 관리하면 Google Kubernetes Engine(GKE) Enterprise 버전 클러스터에서 리소스를 만들 때 정책 컨트롤러 정책을 해당 리소스에 적용할 수 있습니다. 이러한 정책을 사용하면 정책을 위반하는 방식으로 리소스를 만들거나 수정하는 작업을 방지하거나 보고할 수 있습니다. 예를 들어 Cloud Storage 버킷의 위치를 제한하는 정책을 적용할 수 있습니다.
Kubernetes 리소스 모델(KRM)을 기반으로 하는 접근 방식을 사용하면 일관된 도구 및 워크플로 모음을 사용해서 Kubernetes 및 Google Cloud 리소스를 모두 관리할 수 있습니다. 이 튜토리얼에서는 다음 작업을 완료하는 방법을 보여줍니다.
- Google Cloud 리소스를 관리하는 정책을 정의합니다.
- 개발자와 관리자가 정책을 위반하는 Google Cloud 리소스를 만들지 못하도록 하는 제어를 구현합니다.
- 구성 커넥터 외부에서 리소스를 만든 경우에도 기존 Google Cloud 리소스를 정책에 대해 감사하는 제어를 구현합니다.
- 리소스 정의를 만들고 업데이트할 때 개발자와 관리자에게 빠른 피드백을 제공합니다.
- Kubernetes 클러스터에 정의를 적용하기 전에 정책에 대한 Google Cloud 리소스 정의의 유효성을 검사합니다.
목표
- 구성 커넥터 부가기능이 포함된 Google Kubernetes Engine(GKE) Enterprise 버전을 만듭니다.
- 정책 컨트롤러를 설치합니다.
- 정책을 만들어 허용된 Cloud Storage 버킷 위치를 제한합니다.
- 정책이 허용되지 않은 위치에 Cloud Storage 버킷을 생성하지 않게 하는지 확인하기
- 개발 중에 Cloud Storage 버킷 정의의 정책 준수를 평가합니다.
- 기존 Cloud Storage 버킷의 정책 준수를 감사하기
비용
이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
시작하기 전에
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Cloud Shell에서 이 튜토리얼에 사용할 Google Cloud 프로젝트를 설정합니다.
gcloud config set project PROJECT_ID
PROJECT_ID
를 프로젝트의 Google Cloud 프로젝트 ID로 바꿉니다. 이 명령어를 실행하면 Cloud Shell에서 프로젝트 ID가 포함된GOOGLE_CLOUD_PROJECT
라고 하는 내보낸 환경 변수를 만듭니다. Cloud Shell을 사용하지 않는 경우 다음 명령어를 사용하여 환경 변수를 만들 수 있습니다.export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)
GKE API를 사용 설정합니다.
gcloud services enable container.googleapis.com
정책 컨트롤러 API를 사용 설정합니다.
gcloud services enable anthospolicycontroller.googleapis.com
이 튜토리얼용으로 만든 파일을 저장할 디렉터리를 만듭니다.
mkdir -p ~/cnrm-gatekeeper-tutorial
만든 디렉터리로 이동합니다.
cd ~/cnrm-gatekeeper-tutorial
GKE 클러스터 만들기
Cloud Shell에서 구성 커넥터 부가기능 및 GKE용 워크로드 아이덴티티 제휴를 사용하여 GKE 클러스터를 만듭니다.
gcloud container clusters create CLUSTER_NAME \ --addons ConfigConnector \ --enable-ip-alias \ --num-nodes 4 \ --release-channel regular \ --scopes cloud-platform \ --workload-pool $GOOGLE_CLOUD_PROJECT.svc.id.goog \ --zone ZONE
다음을 바꿉니다.
CLUSTER_NAME
: 이 프로젝트에 사용할 클러스터의 이름(예:cnrm-gatekeeper-tutorial
)ZONE
: 위치와 가까운 Compute Engine 영역(예:asia-southeast1-b
)
구성 커넥터 부가기능은 GKE 클러스터에 있는 Google Cloud 리소스용 커스텀 리소스 정의(CRD)를 설치합니다.
(선택사항) 고유한 환경에서 비공개 클러스터를 사용하는 경우 GKE 클러스터 제어 영역이 정책 컨트롤러 웹훅에 연결하도록 허용하는 방화벽 규칙을 추가합니다.
gcloud compute firewall-rules create allow-cluster-control-plane-tcp-8443 \ --allow tcp:8443 \ --network default \ --source-ranges CONTROL_PLANE_CIDR \ --target-tags NODE_TAG
다음을 바꿉니다.
CONTROL_PLANE_CIDR
: GKE 클러스터 제어 영역의 IP 범위(예:172.16.0.16/28
)입니다.NODE_TAG
: GKE 클러스터의 모든 노드에 적용되는 태그입니다.
이 선택적 방화벽 규칙은 클러스터가 비공개 노드를 사용할 때 정책 컨트롤러 웹훅이 작동하도록 하는 데 필요합니다.
Config Connector 설정
구성 커넥터를 설치하는 Google Cloud 프로젝트를 호스트 프로젝트라고 합니다. 구성 커넥터를 사용하여 리소스를 관리하는 프로젝트를 관리 프로젝트라고 합니다. 이 튜토리얼에서는 구성 커넥터를 사용하여 호스트 프로젝트와 관리형 프로젝트가 동일한 프로젝트가 되도록 GKE 클러스터와 동일한 프로젝트에 Google Cloud 리소스를 만듭니다.
Cloud Shell에서 구성 커넥터의 Google 서비스 계정을 만드세요.
gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \ --display-name "Config Connector Gatekeeper tutorial"
SERVICE_ACCOUNT_NAME
을 이 서비스 계정에 사용할 이름, 예를 들어cnrm-gatekeeper-tutorial
로 바꿉니다. 구성 커넥터는 이 Google 서비스 계정을 사용하여 관리형 프로젝트에 리소스를 만듭니다.Google 서비스 계정에 스토리지 관리자 역할을 부여합니다.
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \ --member "serviceAccount:SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \ --role roles/storage.admin
이 튜토리얼에서는 구성 커넥터를 사용하여 Cloud Storage 버킷을 만들기 때문에 스토리지 관리자 역할을 사용합니다. 사용자 환경에서 구성 커넥터용으로 만들려는 Google Cloud 리소스를 관리하는 데 필요한 역할을 부여합니다. 사전 정의된 역할에 대한 자세한 내용은 IAM 문서의 역할 이해를 참조하세요.
이 튜토리얼에서 만든 구성 커넥터 리소스의 Kubernetes 네임스페이스를 만듭니다.
kubectl create namespace NAMESPACE
NAMESPACE를 튜토리얼에 사용할 Kubernetes 네임스페이스로 바꿉니다(예:
tutorial
).Google Cloud 리소스(관리형 프로젝트)를 만드는 데 사용할 프로젝트 구성 커넥터를 지정하기 위해 네임스페이스에 주석을 추가합니다.
kubectl annotate namespace NAMESPACE \ cnrm.cloud.google.com/project-id=$GOOGLE_CLOUD_PROJECT
Kubernetes 네임스페이스에 대해 구성 커넥터를 사용 설정하고 만든 Google 서비스 계정과 연결하는
ConfigConnectorContext
리소스를 만듭니다.cat << EOF | kubectl apply -f - apiVersion: core.cnrm.cloud.google.com/v1beta1 kind: ConfigConnectorContext metadata: name: configconnectorcontext.core.cnrm.cloud.google.com namespace: NAMESPACE spec: googleServiceAccount: SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com EOF
네임스페이스에서 구성 커넥터 리소스를 관리하도록 하기 위해
ConfigConnectorContext
리소스를 만들 때 구성 커넥터는cnrm-system
네임스페이스에 Kubernetes 서비스 계정 및 StatefulSet를 만듭니다.네임스페이스의 구성 커넥터 컨트롤러 포드를 기다립니다.
kubectl wait --namespace cnrm-system --for=condition=Ready pod \ -l cnrm.cloud.google.com/component=cnrm-controller-manager,cnrm.cloud.google.com/scoped-namespace=NAMESPACE
포드가 준비되면 Cloud Shell 메시지가 표시됩니다.
error: no matching resources found
메시지가 표시되면 1분 동안 기다린 후 다시 시도하세요.IAM 정책 binding을 만들어 구성 커넥터 Kubernetes 서비스 계정을 Google 서비스 계정에 결합합니다.
gcloud iam service-accounts add-iam-policy-binding \ SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --member "serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[cnrm-system/cnrm-controller-manager-NAMESPACE]" \ --role roles/iam.workloadIdentityUser
이 binding을 사용하면
cnrm-system
네임스페이스의cnrm-controller-manager-NAMESPACE
Kubernetes 서비스 계정을 생성된 Google 서비스 계정으로 사용할 수 있습니다.
정책 컨트롤러 설치
설치 안내를 따라 정책 컨트롤러를 설치합니다.
감사 간격으로 60
초를 사용합니다.
구성 커넥터를 사용하여 Google Cloud 리소스 만들기
Cloud Shell에서
us-central1
리전의 Cloud Storage 버킷을 나타내는 구성 커넥터 매니페스트를 만듭니다.cat << EOF > tutorial-storagebucket-us-central1.yaml apiVersion: storage.cnrm.cloud.google.com/v1beta1 kind: StorageBucket metadata: name: tutorial-us-central1-$GOOGLE_CLOUD_PROJECT namespace: NAMESPACE spec: location: us-central1 uniformBucketLevelAccess: true EOF
Cloud Storage 버킷을 만들려면 매니페스트를 적용하세요.
kubectl apply -f tutorial-storagebucket-us-central1.yaml
구성 커넥터가 Cloud Storage 버킷을 생성했는지 확인합니다.
gcloud storage ls | grep tutorial
출력은 다음과 비슷합니다.
gs://tutorial-us-central1-PROJECT_ID/
이 출력에는 Google Cloud 프로젝트 ID인
PROJECT_ID
가 포함됩니다.이 출력이 표시되지 않으면 잠시 기다렸다가 단계를 다시 수행합니다.
정책 만들기
정책 컨트롤러의 정책은 제약조건 템플릿 및 제약조건으로 구성됩니다. 제약조건 템플릿에는 정책 로직이 포함됩니다. 제약조건은 정책이 적용되는 위치와 정책 논리에 대한 입력 매개변수를 지정합니다.
Cloud Shell에서 Cloud Storage 버킷 위치를 제한하는 제약조건 템플릿을 만듭니다.
cat << EOF > tutorial-storagebucket-location-template.yaml apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: gcpstoragelocationconstraintv1 spec: crd: spec: names: kind: GCPStorageLocationConstraintV1 validation: openAPIV3Schema: properties: locations: type: array items: type: string exemptions: type: array items: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package gcpstoragelocationconstraintv1 allowedLocation(reviewLocation) { locations := input.parameters.locations satisfied := [ good | location = locations[_] good = lower(location) == lower(reviewLocation)] any(satisfied) } exempt(reviewName) { input.parameters.exemptions[_] == reviewName } violation[{"msg": msg}] { bucketName := input.review.object.metadata.name bucketLocation := input.review.object.spec.location not allowedLocation(bucketLocation) not exempt(bucketName) msg := sprintf("Cloud Storage bucket <%v> uses a disallowed location <%v>, allowed locations are %v", [bucketName, bucketLocation, input.parameters.locations]) } violation[{"msg": msg}] { not input.parameters.locations bucketName := input.review.object.metadata.name msg := sprintf("No permitted locations provided in constraint for Cloud Storage bucket <%v>", [bucketName]) } EOF
템플릿을 적용하여 Cloud Storage 버킷을 만듭니다.
kubectl apply -f tutorial-storagebucket-location-template.yaml
싱가포르와 자카르타 리전(
asia-southeast1
및asia-southeast2
)의 버킷만 허용하는 제약 조건을 만듭니다. 이전에 만든 네임스페이스에 제약조건이 적용됩니다. Cloud Build의 기본 Cloud Storage 버킷은 제외됩니다.cat << EOF > tutorial-storagebucket-location-constraint.yaml apiVersion: constraints.gatekeeper.sh/v1beta1 kind: GCPStorageLocationConstraintV1 metadata: name: singapore-and-jakarta-only spec: enforcementAction: deny match: kinds: - apiGroups: - storage.cnrm.cloud.google.com kinds: - StorageBucket namespaces: - NAMESPACE parameters: locations: - asia-southeast1 - asia-southeast2 exemptions: - ${GOOGLE_CLOUD_PROJECT}_cloudbuild EOF
버킷이 존재할 수 있는 영역을 제한하려면 제약조건을 적용하세요.
kubectl apply -f tutorial-storagebucket-location-constraint.yaml
정책 확인
허용되지 않는 위치(
us-west1
)의 Cloud Storage 버킷을 나타내는 매니페스트를 만듭니다.cat << EOF > tutorial-storagebucket-us-west1.yaml apiVersion: storage.cnrm.cloud.google.com/v1beta1 kind: StorageBucket metadata: name: tutorial-us-west1-$GOOGLE_CLOUD_PROJECT namespace: NAMESPACE spec: location: us-west1 uniformBucketLevelAccess: true EOF
Cloud Storage 버킷을 만들려면 매니페스트를 적용하세요.
kubectl apply -f tutorial-storagebucket-us-west1.yaml
출력은 다음과 비슷합니다.
Error from server ([singapore-and-jakarta-only] Cloud Storage bucket <tutorial-us-west1-PROJECT_ID> uses a disallowed location <us-west1>, allowed locations are ["asia-southeast1", "asia-southeast2"]): error when creating "tutorial-storagebucket-us-west1.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [singapore-and-jakarta-only] Cloud Storage bucket <tutorial-us-west1-PROJECT_ID> uses a disallowed location <us-west1>, allowed locations are ["asia-southeast1", "asia-southeast2"]
(선택사항) Cloud 감사 로그에서 요청 거부를 위한 결정에 대한 기록을 확인할 수 있습니다. 다음과 같이 프로젝트의 관리자 활동 로그를 쿼리합니다.
gcloud logging read --limit=1 \ "logName=\"projects/$GOOGLE_CLOUD_PROJECT/logs/cloudaudit.googleapis.com%2Factivity\""' resource.type="k8s_cluster" resource.labels.cluster_name="CLUSTER_NAME" resource.labels.location="ZONE" protoPayload.authenticationInfo.principalEmail!~"system:serviceaccount:cnrm-system:.*" protoPayload.methodName:"com.google.cloud.cnrm." protoPayload.status.code=7'
출력은 다음과 비슷합니다.
insertId: 3c6940bb-de14-4d18-ac4d-9a6becc70828 labels: authorization.k8s.io/decision: allow authorization.k8s.io/reason: '' mutation.webhook.admission.k8s.io/round_0_index_0: '{"configuration":"mutating-webhook.cnrm.cloud.google.com","webhook":"container-annotation-handler.cnrm.cloud.google.com","mutated":true}' mutation.webhook.admission.k8s.io/round_0_index_1: '{"configuration":"mutating-webhook.cnrm.cloud.google.com","webhook":"management-conflict-annotation-defaulter.cnrm.cloud.google.com","mutated":true}' logName: projects/PROJECT_ID/logs/cloudaudit.googleapis.com%2Factivity operation: first: true id: 3c6940bb-de14-4d18-ac4d-9a6becc70828 last: true producer: k8s.io protoPayload: '@type': type.googleapis.com/google.cloud.audit.AuditLog authenticationInfo: principalEmail: user@example.com authorizationInfo: - permission: com.google.cloud.cnrm.storage.v1beta1.storagebuckets.create resource: storage.cnrm.cloud.google.com/v1beta1/namespaces/NAMESPACE/storagebuckets/tutorial-us-west1-PROJECT_ID methodName: com.google.cloud.cnrm.storage.v1beta1.storagebuckets.create requestMetadata: callerIp: 203.0.113.1 callerSuppliedUserAgent: kubectl/v1.21.1 (linux/amd64) kubernetes/5e58841 resourceName: storage.cnrm.cloud.google.com/v1beta1/namespaces/NAMESPACE/storagebuckets/tutorial-us-west1-PROJECT_ID serviceName: k8s.io status: code: 7 message: Forbidden receiveTimestamp: '2021-05-21T06:56:24.940264678Z' resource: labels: cluster_name: CLUSTER_NAME location: CLUSTER_ZONE project_id: PROJECT_ID type: k8s_cluster timestamp: '2021-05-21T06:56:09.060635Z'
methodName
필드는 시도된 작업을 나타내고resourceName
은 구성 커넥터 리소스의 전체 이름을 표시하며status
섹션은 요청이 실패했음을 나타냅니다(오류 코드7
및Forbidden
메시지).허용된 위치(
asia-southeast1
)의 Cloud Storage 버킷을 나타내는 매니페스트를 만듭니다.cat << EOF > tutorial-storagebucket-asia-southeast1.yaml apiVersion: storage.cnrm.cloud.google.com/v1beta1 kind: StorageBucket metadata: name: tutorial-asia-southeast1-$GOOGLE_CLOUD_PROJECT namespace: NAMESPACE spec: location: asia-southeast1 uniformBucketLevelAccess: true EOF
Cloud Storage 버킷을 만들려면 매니페스트를 적용하세요.
kubectl apply -f tutorial-storagebucket-asia-southeast1.yaml
출력은 다음과 비슷합니다.
storagebucket.storage.cnrm.cloud.google.com/tutorial-asia-southeast1-PROJECT_ID created
이 출력에는 Google Cloud 프로젝트 ID인
PROJECT_ID
가 포함됩니다.구성 커넥터가 Cloud Storage 버킷을 생성했는지 확인합니다.
gcloud storage ls | grep tutorial
출력은 다음과 비슷합니다.
gs://tutorial-asia-southeast1-PROJECT_ID/ gs://tutorial-us-central1-PROJECT_ID/
이 출력이 표시되지 않으면 잠시 기다렸다가 이 단계를 다시 수행합니다.
감사 제약조건
정책 컨트롤러의 감사 컨트롤러는 정기적으로 제약조건을 기준으로 리소스를 평가합니다. 컨트롤러는 제약조건 이전에 생성된 리소스와 구성 커넥터 외부에서 생성된 리소스의 정책 위반을 감지합니다.
Cloud Shell에서
GCPStorageLocationConstraintV1
제약조건 템플릿을 사용하는 모든 제약조건에 대한 위반을 확인합니다.kubectl get gcpstoragelocationconstraintv1 -o json \ | jq '.items[].status.violations'
출력은 다음과 비슷합니다.
[ { "enforcementAction": "deny", "kind": "StorageBucket", "message": "Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are \"asia-southeast1\", \"asia-southeast2\"", "name": "tutorial-us-central1-PROJECT_ID", "namespace": "NAMESPACE" } ]
제약조건을 만들기 전에
us-central1
에서 만든 Cloud Storage 버킷을 확인합니다.
개발 중 리소스 검증
개발 및 지속적 통합 빌드 중에 GKE 클러스터에 해당 리소스를 적용하기 전에 제약조건을 기준으로 리소스의 유효성을 검사하는 것이 좋습니다. 유효성 검사는 빠른 피드백을 제공하며 리소스 및 제약조건 관련 문제를 조기에 발견할 수 있도록 합니다. 이 단계에서는 kpt를 사용하여 리소스를 검증하는 방법을 보여줍니다. kpt 명령줄 도구를 사용하면 Kubernetes 리소스 매니페스트를 관리하고 적용할 수 있습니다.
Cloud Shell에서 kpt를 사용하여
gatekeeper
KRM 함수를 실행합니다.kpt fn eval . --image=gcr.io/kpt-fn/gatekeeper:v0.2 --truncate-output=false
KRM 함수는 로컬 파일 시스템에 YAML 파일로 저장된 Kubernetes 리소스를 변형 또는 검사할 수 있는 프로그램입니다.
gatekeeper
KRM 함수는 Gatekeeper 정책에 대해 구성 커넥터 Cloud Storage 버킷 리소스를 검사합니다.gatekeeper
KRM 함수는 Artifact Registry에서 사용할 수 있는 컨테이너 이미지로 패키징됩니다.이 함수는
us-central1
및us-west1
리전에 있는 Cloud Storage 버킷의 매니페스트 파일의 제약조건 위반을 보고합니다.출력은 다음과 비슷합니다.
[RUNNING] "gcr.io/kpt-fn/gatekeeper:v0.2" [FAIL] "gcr.io/kpt-fn/gatekeeper:v0.2" Results: [ERROR] Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are ["asia-southeast1", "asia-southeast2"] violatedConstraint: singapore-and-jakarta-only in object "storage.cnrm.cloud.google.com/v1beta1/StorageBucket/tutorial/tutorial-us-central1-GOOGLE_CLOUD_PROJECT" in file "tutorial-storagebucket-us-central1.yaml" [ERROR] Cloud Storage bucket <tutorial-us-west1-PROJECT_ID> uses a disallowed location <us-west1>, allowed locations are ["asia-southeast1", "asia-southeast2"] violatedConstraint: singapore-and-jakarta-only in object "storage.cnrm.cloud.google.com/v1beta1/StorageBucket/tutorial/tutorial-us-west1-GOOGLE_CLOUD_PROJECT" in file "tutorial-storagebucket-us-west1.yaml" Stderr: "[error] storage.cnrm.cloud.google.com/v1beta1/StorageBucket/test/tutorial-us-central1-PROJECT_ID : Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are [\"asia-southeast1\", \"asia-southeast2\"]" "violatedConstraint: singapore-and-jakarta-only" "" "[error] storage.cnrm.cloud.google.com/v1beta1/StorageBucket/test/tutorial-us-west1-PROJECT_IDT : Cloud Storage bucket <tutorial-us-west1-PROJECT_IDgt; uses a disallowed location <us-west1>, allowed locations are [\"asia-southeast1\", \"asia-southeast2\"]" "violatedConstraint: singapore-and-jakarta-only" "" Exit code: 1
구성 커넥터 외부에서 생성된 리소스 검증
리소스를 내보내 구성 커넥터 외부에서 생성된 Google Cloud 리소스의 유효성을 확인할 수 있습니다. 리소스를 내보낸 후 다음 옵션 중 하나를 사용하여 내보낸 리소스에 대해 정책 컨트롤러 정책을 평가합니다.
gatekeeper
KRM 함수를 사용하여 리소스 검사리소스를 구성 커넥터로 가져옵니다.
리소스를 내보내려면 Cloud 애셋 인벤토리를 사용합니다.
Cloud Shell에서 Cloud Asset API를 사용 설정합니다.
gcloud services enable cloudasset.googleapis.com
us-central1
및us-west1
에서 Cloud Storage 버킷에 대해 Kubernetes 리소스 매니페스트 파일을 삭제합니다.rm tutorial-storagebucket-us-*.yaml
현재 프로젝트의 모든 Cloud Storage 리소스를 내보내고 출력을
export.yaml
이라는 파일에 저장합니다.gcloud beta resource-config bulk-export \ --project $GOOGLE_CLOUD_PROJECT \ --resource-format krm \ --resource-types StorageBucket > export.yaml
출력은 다음과 비슷합니다.
Exporting resource configurations to stdout... Export complete.
KRM 함수를 함께 연결하여 kpt 파이프라인을 만듭니다. 이 파이프라인은 현재 디렉터리의 리소스를 Cloud Storage 버킷 위치 정책에 대해 검사합니다.
kpt fn source . \ | kpt fn eval - --image=gcr.io/kpt-fn/set-namespace:v0.1 -- namespace=NAMESPACE \ | kpt fn eval - --image=gcr.io/kpt-fn/gatekeeper:v0.2 --truncate-output=false
내보낸 리소스에는
namespace
메타데이터 속성 값이 없습니다. 이 파이프라인은set-namespace
라는 KRM 함수를 사용하여 모든 리소스의namespace
값을 설정합니다.출력은 다음과 비슷하며 내보낸 리소스에 대한 위반사항을 보여줍니다.
[RUNNING] "gcr.io/kpt-fn/set-namespace:v0.1" [PASS] "gcr.io/kpt-fn/set-namespace:v0.1" [RUNNING] "gcr.io/kpt-fn/gatekeeper:v0.2" [FAIL] "gcr.io/kpt-fn/gatekeeper:v0.2" Results: [ERROR] Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are ["asia-southeast1", "asia-southeast2"] violatedConstraint: singapore-and-jakarta-only in object "storage.cnrm.cloud.google.com/v1beta1/StorageBucket/tutorial/tutorial-us-central1-GOOGLE_CLOUD_PROJECT" in file "export.yaml" Stderr: "[error] storage.cnrm.cloud.google.com/v1beta1/StorageBucket/test/tutorial-us-central1-PROJECT_ID : Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are [\"asia-southeast1\", \"asia-southeast2\"]" "violatedConstraint: singapore-and-jakarta-only" "" Exit code: 1
이 튜토리얼을 수행하기 전에 만든 Cloud Storage 버킷이 Google Cloud 프로젝트에 포함되어 있고 해당 위치가 제약조건을 위반하면 이전에 만든 버킷이 출력에 표시됩니다.
수고하셨습니다. Cloud Storage 버킷의 허용 위치를 관리하는 정책을 성공적으로 설정했습니다. 튜토리얼이 완료되었습니다. 이제 다른 Google Cloud 리소스에 대해 고유한 정책을 계속 추가할 수 있습니다.
문제 해결
구성 커넥터가 예상 Google Cloud 리소스를 만들지 않는 경우 Cloud Shell에서 다음 명령어를 사용하여 구성 커넥터 컨트롤러 관리자의 로그를 확인하세요.
kubectl logs --namespace cnrm-system --container manager \
--selector cnrm.cloud.google.com/component=cnrm-controller-manager,cnrm.cloud.google.com/scoped-namespace=NAMESPACE
정책 컨트롤러가 정책을 올바르게 적용하지 않는 경우 다음 명령어를 사용하여 컨트롤러 관리자 로그를 확인하세요.
kubectl logs deployment/gatekeeper-controller-manager \
--namespace gatekeeper-system
정책 컨트롤러가 제약조건 객체의 status
필드에서 위반을 보고하지 않으면 다음 명령어를 사용하여 감사 컨트롤러의 로그를 확인하세요.
kubectl logs deployment/gatekeeper-audit --namespace gatekeeper-system
이 튜토리얼에서 문제가 발생하면 다음 문서를 검토하세요.
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.
프로젝트 삭제
- In the Google Cloud console, go to the Manage resources page.
- If the project that you plan to delete is attached to an organization, expand the Organization list in the Name column.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
리소스 삭제
이 튜토리얼에서 사용된 Google Cloud 프로젝트를 유지하려면 개별 리소스를 삭제합니다.
Cloud Shell에서 Cloud Storage 버킷 위치 제약조건을 삭제합니다.
kubectl delete -f tutorial-storagebucket-location-constraint.yaml
구성 커넥터에서 관리하는 네임스페이스의 모든
storagebucket
리소스에 문자열 값이true
인cnrm.cloud.google.com/force-destroy
주석을 추가합니다.kubectl annotate storagebucket --all --namespace NAMESPACE \ cnrm.cloud.google.com/force-destroy=true
이 주석은 GKE 클러스터에서 해당
storagebucket
리소스를 삭제할 때 버킷에 객체가 포함되어 있더라도 구성 커넥터가 Cloud Storage 버킷을 삭제할 수 있도록 하는 directive입니다.Cloud Storage 버킷을 나타내는 구성 커넥터 리소스를 삭제하세요.
kubectl delete --namespace NAMESPACE storagebucket --all
GKE 클러스터를 삭제합니다.
gcloud container clusters delete CLUSTER_NAME \ --zone ZONE --async --quiet
IAM에서 워크로드 아이덴티티 정책 binding을 삭제합니다.
gcloud iam service-accounts remove-iam-policy-binding \ SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --member "serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[cnrm-system/cnrm-controller-manager-NAMESPACE]" \ --role roles/iam.workloadIdentityUser
Google 서비스 계정의 Cloud Storage 관리자 역할 결합을 삭제합니다.
gcloud projects remove-iam-policy-binding $GOOGLE_CLOUD_PROJECT \ --member "serviceAccount:SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \ --role roles/storage.admin
구성 커넥터용으로 만든 Google 서비스 계정을 삭제합니다.
gcloud iam service-accounts delete --quiet \ SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com