Google Kubernetes Engine (GKE) ComputeClasses를 사용하여 다양한 워크로드 요구사항을 충족하는 노드를 만들 수 있습니다. 포드는 ComputeClass를 사용하여 하드웨어를 만들 수 있습니다. ComputeClass에 따라 해당 하드웨어의 수요가 많거나, 사용 가능 여부가 제한적이거나, 엔터프라이즈에 상대적으로 비용이 많이 들 수 있습니다. 이 튜토리얼에서는 Kubernetes RBAC 및 ValidatingAdmissionPolicies를 사용하여 ComputeClass의 생성, 삭제, 수정, 선택을 제한하는 방법을 보여줍니다.
이러한 제한사항은 다음과 같은 상황을 방지하는 데 도움이 될 수 있습니다.
- GPU 또는 TPU와 같은 특수 하드웨어가 필요하지 않은 포드는 해당 하드웨어를 요청하는 ComputeClass를 선택합니다.
- 승인되지 않은 엔티티가 중요한 워크로드용으로 예약된 하드웨어에 액세스하기 위해 ComputeClass를 만들거나 수정합니다.
이 문서에서는 와일드카드 ComputeClass 허용 또는 허용되지 않는 특정 ComputeClass 선택과 같은 일반적인 오용 유형을 차단하는 ValidatingAdmissionPolicy의 예를 사용합니다. 특정 팀의 워크로드가 ComputeClass를 사용하지 못하도록 차단하는 등 조직에 특정한 요구사항을 충족하도록 ValidatingAdmissionPolicy를 수정할 수 있습니다.
목표
- ValidatingAdmissionPolicy를 사용하여 각 네임스페이스에서 포드가 선택할 수 있는 ComputeClass를 승인된 목록으로 제한합니다.
- 역할 기반 액세스 제어 (RBAC)를 사용하여 클러스터에서 ComputeClass를 만들거나 수정하거나 삭제할 수 있는 사용자를 제한합니다.
비용
이 문서에서는 비용이 청구될 수 있는 Google Cloud구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
- Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init -
Google Cloud 프로젝트를 만들거나 선택합니다.
프로젝트를 선택하거나 만드는 데 필요한 역할
- 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
-
프로젝트 만들기: 프로젝트를 만들려면
resourcemanager.projects.create권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
-
Google Cloud 프로젝트를 만듭니다.
gcloud projects create PROJECT_ID
PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다. -
만든 Google Cloud 프로젝트를 선택합니다.
gcloud config set project PROJECT_ID
PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.
-
이 가이드에 기존 프로젝트를 사용하는 경우 이 가이드를 완료하는 데 필요한 권한이 있는지 확인합니다. 새 프로젝트를 만든 경우에는 이미 필요한 권한이 있습니다.
Kubernetes Engine API를 사용 설정합니다.
API 사용 설정에 필요한 역할
API를 사용 설정하려면
serviceusage.services.enable권한이 포함된 서비스 사용량 관리자 IAM 역할 (roles/serviceusage.serviceUsageAdmin)이 필요합니다. 역할 부여 방법 알아보기gcloud services enable container.googleapis.com
-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init -
Google Cloud 프로젝트를 만들거나 선택합니다.
프로젝트를 선택하거나 만드는 데 필요한 역할
- 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
-
프로젝트 만들기: 프로젝트를 만들려면
resourcemanager.projects.create권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
-
Google Cloud 프로젝트를 만듭니다.
gcloud projects create PROJECT_ID
PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다. -
만든 Google Cloud 프로젝트를 선택합니다.
gcloud config set project PROJECT_ID
PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.
-
이 가이드에 기존 프로젝트를 사용하는 경우 이 가이드를 완료하는 데 필요한 권한이 있는지 확인합니다. 새 프로젝트를 만든 경우에는 이미 필요한 권한이 있습니다.
Kubernetes Engine API를 사용 설정합니다.
API 사용 설정에 필요한 역할
API를 사용 설정하려면
serviceusage.services.enable권한이 포함된 서비스 사용량 관리자 IAM 역할 (roles/serviceusage.serviceUsageAdmin)이 필요합니다. 역할 부여 방법 알아보기gcloud services enable container.googleapis.com
- 로컬 셸을 사용하는 경우
kubectl구성요소를 설치합니다.gcloud components install kubectl
- 버전 1.30 이상을 사용하는 GKE 클러스터가 있는지 확인합니다. 이 튜토리얼에서는 Autopilot 클러스터를 만들 수도 있습니다.
- RBAC용 Google 그룹스를 사용하도록 클러스터를 구성합니다.
- 도메인에서
gke-security-groups그룹을 설정합니다. - 클러스터에서 RBAC용 Google 그룹스를 사용 설정합니다.
자세한 내용은 Google 그룹 설정하기를 참고하세요.
- 도메인에서
필요한 역할
클러스터에서 RBAC 정책과 Kubernetes 객체를 만드는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 Kubernetes Engine 관리자 (role/container.admin) IAM 역할을 부여해 달라고 요청하세요.
역할 부여에 대한 상세 설명은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.
환경 준비
이 튜토리얼의 생성 및 확인 작업을 위해 클러스터를 준비하려면 다음 단계를 따르세요.
클러스터에 연결합니다.
gcloud container clusters get-credentials CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION다음을 바꿉니다.
CLUSTER_NAME: 클러스터 이름입니다.CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 리전 또는 영역(예:us-central1또는us-central1-a)
이 튜토리얼에 사용할 네임스페이스를 만듭니다. 클러스터의 기존 네임스페이스를 사용할 수도 있습니다.
kubectl create namespace computeclass-vap-tutorialValidatingAdmissionPolicies 및 ValidatingAdmissionPolicyBindings를 관리할 수 있는 액세스 권한을 부여하는 RBAC 정책을 만듭니다.
다음 매니페스트를
validatingadmissionpolicy-editor.yaml로 저장합니다.apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: validatingadmissionpolicy-editor rules: - apiGroups: ["admissionregistration.k8s.io"] resources: ["validatingadmissionpolicies","validatingadmissionpolicybindings"] verbs: ["get", "list", "create", "update", "patch", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: edit-validatingadmissionpolicies subjects: - kind: User name: USER_ACCOUNT apiGroup: rbac.authorization.k8s.io roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: validatingadmissionpolicy-editorUSER_ACCOUNT을 사용자 계정의 이메일 주소로 바꿉니다.RBAC 정책을 만듭니다.
kubectl apply -f validatingadmissionpolicy-editor.yaml
클러스터에 ComputeClass를 만듭니다. 클러스터에 ComputeClass가 이미 있는 경우 이 단계를 건너뜁니다.
다음 매니페스트를
access-computeclass.yaml로 저장합니다.apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: access-restriction-class spec: priorities: - machineFamily: e2 nodePoolAutoCreation: enabled: true whenUnsatisfiable: ScaleUpAnywayComputeClass를 만듭니다.
kubectl apply -f access-computeclass.yaml
ValidatingAdmissionPolicy 만들기
포드가 선택할 수 있는 ComputeClass를 제한하려면 ValidatingAdmissionPolicy를 만들고 특정 네임스페이스에서 적용합니다. ValidatingAdmissionPolicy 사양을 사용하여 포드가 ComputeClass를 선택하는 방법을 제어합니다. 다음 단계에서는 이 정책을 만들고 적용하는 방법을 보여줍니다.
다음 ValidatingAdmissionPolicy 매니페스트를
restrict-computeclass-usage-vap.yaml로 저장합니다.apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: restrict-computeclass-usage spec: failurePolicy: Fail # If an internal error occurs, deny the request. variables: # Check whether the admission request is for a Deployment. - name: isDeployment expression: "object.kind == 'Deployment'" # Get the Pod specification from the admission request by reading the # spec.template.spec field for Deployments or the spec field for static Pods. - name: podSpec expression: "variables.isDeployment ? object.spec.template.spec : object.spec" # Check whether a node selector or an affinity rule that explicitly requests a # disallowed ComputeClass. - name: hasForbiddenNodeSelectorOrAffinity expression: >- (has(variables.podSpec.nodeSelector) && variables.podSpec.nodeSelector['cloud.google.com/compute-class'] == 'COMPUTECLASS_NAME') || (has(variables.podSpec.affinity) && has(variables.podSpec.affinity.nodeAffinity) && has(variables.podSpec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution) && variables.podSpec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.exists(term, has(term.matchExpressions) && term.matchExpressions.exists( exp, exp.key == 'cloud.google.com/compute-class' && exp.operator == 'In' && exp.values.exists(v, v == 'COMPUTECLASS_NAME') ) )) # Check whether the Pod has a toleration for the taint that corresponds to a # disallowed ComputeClass. - name: hasForbiddenComputeClassToleration expression: >- has(variables.podSpec.tolerations) && variables.podSpec.tolerations.exists(t, t.key == 'cloud.google.com/compute-class' && (t.operator == 'Exists' || (t.operator == 'Equal' && t.value == 'COMPUTECLASS_NAME')) && has(t.effect) && t.effect == 'NoSchedule') # Check whether the Pod has a toleration that could match any taint. - name: hasWildcardToleration expression: >- has(variables.podSpec.tolerations) && variables.podSpec.tolerations.exists(t, (t.operator == 'Exists' && !(has(t.key) && t.key != '')) ) # Trigger the ValidatingAdmissionPolicy when Pods or Deployments are created or # updated. matchConstraints: resourceRules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] - apiGroups: ["apps"] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["deployments"] # Validate whether any of the expressions in the variables section evaluate to # true. validations: - expression: >- !(variables.hasForbiddenNodeSelectorOrAffinity || variables.hasForbiddenComputeClassToleration || variables.hasWildcardToleration) message: >- Pods and Deployments in this namespace cannot request ComputeClass COMPUTECLASS_NAME or use wildcard tolerations.COMPUTECLASS_NAME을 포드가 선택하지 못하도록 하려는 ComputeClass의 이름으로 바꿉니다.이 ValidatingAdmissionPolicy에는 다음과 같은 속성이 있습니다.
- 정적 포드 또는 배포의 포드 트리거
다음 중 하나를 수행하는 포드를 찾습니다.
- 노드 선택기 또는 노드 어피니티 규칙을 사용하여 허용되지 않는 특정 ComputeClass를 명시적으로 선택합니다.
- 특정 허용되지 않는 ComputeClass의 노드 taint에 해당하는 톨러레이션을 사용합니다.
- 클러스터의 모든 노드 taint와 일치하는 톨러레이션(toleration)을 사용합니다.
ValidatingAdmissionPolicy의 예는 다음과 같습니다. 표현식을 사용하여 특정 라벨이 있는 포드가 특정 ComputeClass를 선택하지 못하도록 하는 등 자체 조건을 기반으로 정책을 트리거할 수 있습니다.
ValidatingAdmissionPolicy를 만듭니다.
kubectl apply -f restrict-computeclass-usage-vap.yaml다음 ValidatingAdmissionPolicyBinding을
restrict-computeclass-usage-binding.yaml로 저장합니다.apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicyBinding metadata: name: restrict-computeclass-usage-binding spec: policyName: restrict-computeclass-usage validationActions: ["Deny","Audit"] matchResources: namespaceSelector: matchLabels: kubernetes.io/metadata.name: computeclass-vap-tutorial # Replace with the name of any namespace in the cluster.이 ValidatingAdmissionPolicyBinding은 이전 단계의 ValidatingAdmissionPolicy를
computeclass-vap-tutorial네임스페이스에서 적용합니다.validationActions필드의 값은 ValidatingAdmissionPolicy를 위반하는 포드 또는 배포를 거부하고 Kubernetes 감사 로그에 항목을 추가합니다.ValidatingAdmissionPolicyBinding을 만듭니다.
kubectl apply -f restrict-computeclass-usage-binding.yaml
RBAC 정책 구성
ValidatingAdmissionPolicy를 사용하여 워크로드가 특정 ComputeClass를 사용하지 못하도록 하는 것 외에도 RBAC를 사용하여 승인되지 않은 주 구성원이 클러스터에서 ComputeClass를 만들고 수정하지 못하도록 합니다. 다음 단계에서는 RBAC용 Google 그룹스를 사용하여 특정 사용자 그룹에 ComputeClasses에 대한 액세스 권한을 부여하는 방법을 보여줍니다.
ComputeClass 편집자 그룹을 만듭니다.
Google 관리 콘솔에서 그룹 페이지로 이동합니다.
그룹 만들기를 클릭합니다.
그룹 세부정보 페이지에서 다음을 수행합니다.
- 그룹 이름 필드에
computeclass-editors을 지정합니다. - 그룹 이메일 필드에
computeclass-editors를 지정합니다. - 보안 체크박스를 선택합니다.
- 다음을 클릭합니다.
- 그룹 이름 필드에
액세스 유형 페이지의 그룹 회원 열에서 회원을 볼 수 있는 사용자 체크박스가 선택되어 있는지 확인합니다.
그룹 만들기를 클릭합니다.
탐색 메뉴에서 디렉터리 > 그룹을 클릭합니다.
gke-security-groups 행 위로 마우스를 가져간 다음 구성원 추가를 클릭합니다.
gke-security-groups에 구성원 추가 대화상자에서
computeclass-editors을 지정하고 결과에서 해당 그룹을 선택합니다.그룹에 추가를 클릭합니다.
승인된 사용자의 이메일 주소를
computeclass-editors그룹에 추가합니다.다음 ClusterRole을
computeclass-editor-clusterrole.yaml로 저장합니다.apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: computeclass-editor rules: - apiGroups: ["cloud.google.com"] resources: ["computeclasses"] verbs: ["create","update"]ClusterRole을 만듭니다.
kubectl apply -f computeclass-editor-clusterrole.yaml다음 ClusterRoleBinding을
computeclass-editor-role-binding.yaml로 저장합니다.apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: computeclass-editor-role-binding subjects: - kind: Group name: computeclass-editors@GROUP_DOMAIN apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: computeclass-editor apiGroup: rbac.authorization.k8s.io # Required for role referencesGROUP_DOMAIN을computeclass-editors그룹의 도메인 이름으로 바꿉니다.ClusterRoleBinding을 만듭니다.
kubectl apply -f computeclass-editor-role-binding.yaml
제한사항 확인
다음 섹션에서는 이전 섹션에서 구성한 제한사항이 예상대로 작동하는지 확인하는 방법을 보여줍니다. ValidatingAdmissionPolicies 또는 RBAC 정책에서 자체 제한사항을 구성한 경우 해당 정책을 위반하는 워크로드를 만들어 제한사항을 테스트합니다.
ValidatingAdmissionPolicy 확인
다음 매니페스트 중 하나를 저장합니다. 각 매니페스트는 ValidatingAdmissionPolicy의 서로 다른 조건을 위반합니다.
노드 선택기를 사용하여 허용되지 않는 ComputeClass를 선택하는 배포:
apiVersion: apps/v1 kind: Deployment metadata: name: disallowed-computeclass-deployment namespace: computeclass-vap-tutorial spec: replicas: 1 selector: matchLabels: app: forbidden-selector-app template: metadata: labels: app: forbidden-selector-app spec: containers: - name: my-app-container image: nginx:latest # The node selector triggers the policy. nodeSelector: cloud.google.com/compute-class: COMPUTECLASS_NAME허용되지 않는 ComputeClass에 대한 톨러레이션(toleration)이 있는 배포:
apiVersion: apps/v1 kind: Deployment metadata: name: disallowed-computeclass-deployment-toleration namespace: computeclass-vap-tutorial spec: replicas: 1 selector: matchLabels: app: forbidden-selector-app template: metadata: labels: app: forbidden-selector-app spec: containers: - name: my-app-container image: nginx:latest tolerations: - key: cloud.google.com/compute-class operator: Equal value: COMPUTECLASS_NAME effect: NoSchedule허용되지 않는 ComputeClass에 대한 노드 어피니티 규칙이 있는 배포:
apiVersion: apps/v1 kind: Deployment metadata: name: disallowed-computeclass-deployment-toleration namespace: computeclass-vap-tutorial spec: replicas: 1 selector: matchLabels: app: forbidden-selector-app template: metadata: labels: app: forbidden-selector-app spec: containers: - name: my-app-container image: nginx:latest affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: cloud.google.com/compute-class operator: In values: - COMPUTECLASS_NAME클러스터의 모든 노드 테인트에 대한 톨러레이션(toleration)이 있는 포드:
apiVersion: v1 kind: Pod metadata: name: disallowed-computeclass-deployment-toleration namespace: computeclass-vap-tutorial spec: containers: - name: my-app-container image: nginx:latest tolerations: - operator: Exists effect: NoSchedule
테스트 워크로드를 만듭니다.
kubectl apply -f PATH_TO_WORKLOAD_MANIFEST출력은 다음과 비슷합니다.
Error from server (BadRequest): admission webhook "validation-policy.kubernetes.io" denied the request: Pods and Deployments in this namespace cannot request ComputeClass COMPUTECLASS_NAME or use wildcard tolerations.
RBAC 구성 확인
RBAC 구성을 확인하려면 다음 단계를 따르세요.
computeclass-editors그룹의 구성원인 사용자의 사용자 인증 정보를 사용하여 클러스터를 인증합니다.사용자가 ComputeClass를 만들 수 있는지 확인합니다.
kubectl auth can-i create computeclasses.cloud.google.com \ --as=MEMBER_USERMEMBER_USER를 그룹 구성원인 사용자의 이메일 주소로 바꿉니다.출력은
yes입니다.computeclass-editors그룹의 구성원이 아닌 사용자의 사용자 인증 정보를 사용하여 클러스터를 인증합니다.사용자가 ComputeClass를 만들 수 있는지 확인합니다.
kubectl auth can-i create computeclasses.cloud.google.com \ --as=NON_MEMBER_USERNON_MEMBER_USER을 그룹 회원이 아닌 사용자의 이메일 주소로 바꿉니다.출력은
no입니다.
그룹의 구성원이 아닌 사용자에 대해 kubectl auth can-i 명령어의 출력이 yes인 경우 다음을 확인합니다.
computeclass-editors그룹은gke-security-groups그룹의 구성원입니다.- ClusterRoleBinding의 그룹 이메일 주소는 그룹의 정확한 이메일 주소입니다(예:
computeclass-editors@example.com).
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.
이 튜토리얼의 ValidatingAdmissionPolicy 및 RBAC 정책을 프로덕션 클러스터에 배포하면 GKE에서 정책을 위반하는 수신 포드 및 API 요청을 차단합니다. 이러한 정책을 활성 상태로 유지하려면 이 섹션을 건너뛰세요. 학습 또는 테스트 환경에서 이 튜토리얼을 따른 경우 다음 섹션에서는 프로젝트 또는 개별 리소스를 삭제하는 방법을 보여줍니다.
프로젝트 삭제
Google Cloud 프로젝트를 삭제합니다.
gcloud projects delete PROJECT_ID
개별 리소스 삭제
생성한 ComputeClass를 삭제합니다.
kubectl delete computeclass access-restriction-classValidatingAdmissionPolicy 및 ValidatingAdmissionPolicyBinding을 삭제합니다.
kubectl delete validatingadmissionpolicy restrict-computeclass-usage kubectl delete validatingadmissionpolicybinding restrict-computeclass-usage-bindingClusterRole 및 ClusterRoleBinding을 삭제합니다.
kubectl delete clusterroles \ computeclass-editor validatingadmissionpolicy-editor kubectl delete clusterrolebindings \ computeclass-editor-role-binding edit-validatingadmissionpolicies예시 네임스페이스를 삭제합니다.
kubectl delete namespace computeclass-vap-tutorial
다음 단계
- 클러스터 보안 권장사항 검토하기
- Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항 살펴보기 Cloud 아키텍처 센터 살펴보기