您可以使用 Google Kubernetes Engine (GKE) ComputeClasses 建立節點,滿足各種工作負載需求。Pod 可以使用 ComputeClass 建立硬體。視 ComputeClass 而定,該硬體可能供不應求、供應量有限,或對貴公司而言相對昂貴。本教學課程說明如何使用 Kubernetes RBAC 和ValidatingAdmissionPolicies,限制 ComputeClass 的建立、刪除、修改和選取作業。
這些限制有助於避免下列情況:
- 不需要 GPU 或 TPU 等專用硬體的 Pod 會選取要求該硬體的 ComputeClass。
- 未經授權的實體建立或修改 ComputeClass,以存取為重要工作負載保留的硬體。
本文使用 ValidatingAdmissionPolicy 範例,封鎖常見的濫用類型,例如萬用字元 ComputeClass 容許度,或選取特定禁止的 ComputeClass。您可以修改 ValidatingAdmissionPolicy,以符合貴機構的特定需求,例如禁止特定團隊的工作負載使用 ComputeClass。
目標
- 使用 ValidatingAdmissionPolicy,將每個命名空間中 Pod 可選取的 ComputeClass 限制在核准清單內。
- 使用角色型存取控管 (RBAC),限制叢集中可建立、修改或刪除 ComputeClass 的使用者。
費用
在本文件中,您會使用下列 Google Cloud的計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」。
事前準備
- 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自評估產品在實際工作環境中的成效。新客戶還能獲得價值 $300 美元的免費抵免額,可用於執行、測試及部署工作負載。
-
安裝 Google Cloud CLI。
-
若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI。
-
執行下列指令,初始化 gcloud CLI:
gcloud init -
選取或建立專案所需的角色
- 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
-
建立專案:如要建立專案,您需要「專案建立者」角色 (
roles/resourcemanager.projectCreator),其中包含resourcemanager.projects.create權限。瞭解如何授予角色。
-
建立 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,您需要具備服務使用情形管理員 IAM 角色 (
roles/serviceusage.serviceUsageAdmin),其中包含serviceusage.services.enable權限。瞭解如何授予角色。gcloud services enable container.googleapis.com
-
安裝 Google Cloud CLI。
-
若您採用的是外部識別資訊提供者 (IdP),請先使用聯合身分登入 gcloud CLI。
-
執行下列指令,初始化 gcloud CLI:
gcloud init -
選取或建立專案所需的角色
- 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
-
建立專案:如要建立專案,您需要「專案建立者」角色 (
roles/resourcemanager.projectCreator),其中包含resourcemanager.projects.create權限。瞭解如何授予角色。
-
建立 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,您需要具備服務使用情形管理員 IAM 角色 (
roles/serviceusage.serviceUsageAdmin),其中包含serviceusage.services.enable權限。瞭解如何授予角色。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-tutorial建立 RBAC 政策,授予管理 ValidatingAdmissionPolicies 和 ValidatingAdmissionPolicyBindings 的存取權:
將下列資訊清單儲存為
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-editor將
USER_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: ScaleUpAnyway建立 ComputeClass:
kubectl apply -f access-computeclass.yaml
建立 ValidatingAdmissionPolicy
如要限制 Pod 可選取的 ComputeClass,請建立 ValidatingAdmissionPolicy,並在特定命名空間中強制執行。您可以使用 ValidatingAdmissionPolicy 規格,控管 Pod 選取 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替換為要禁止 Pod 選取的 ComputeClass 名稱。這個 ValidatingAdmissionPolicy 具有下列屬性:
- 靜態 Pod 或 Deployment 中的 Pod 觸發條件。
找出執行下列任一動作的 Pod:
- 使用節點選取器或節點相依性規則,明確選取特定不允許的 ComputeClass。
- 使用與特定不允許的 ComputeClass 節點 taint 相對應的容許條件。
- 使用與叢集中所有節點汙染相符的容許條件。
這個 ValidatingAdmissionPolicy 是範例。您可以根據自己的條件使用運算式觸發政策,例如防止具有特定標籤的 Pod 選取特定 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 會在
computeclass-vap-tutorial命名空間中,強制執行上一個步驟的 ValidatingAdmissionPolicy。validationActions欄位中的值會拒絕違反 ValidatingAdmissionPolicy 的 Pod 或部署項目,並在 Kubernetes 稽核記錄中新增項目。建立 ValidatingAdmissionPolicyBinding:
kubectl apply -f restrict-computeclass-usage-binding.yaml
設定 RBAC 政策
除了使用 ValidatingAdmissionPolicy 防止工作負載使用特定 ComputeClass 外,您也可以使用 RBAC,防止未經授權的主體在叢集中建立及修改 ComputeClass。下列步驟說明如何使用 Google 網路論壇進行 RBAC,將 ComputeClasses 的存取權授予特定使用者群組:
為 ComputeClass 編輯者建立群組:
前往 Google 管理控制台的「群組」頁面。
按一下 [建立群組]。
在「群組詳細資料」頁面中,執行下列操作:
- 在「Group name」(群組名稱) 欄位中,指定
computeclass-editors。 - 在「群組電子郵件」欄位中,指定
computeclass-editors。 - 選取「安全性」核取方塊。
- 點選「下一步」。
- 在「Group name」(群組名稱) 欄位中,指定
在「存取類型」頁面的「群組成員」欄中,確認已選取「可以檢視成員的使用者」核取方塊。
按一下 [建立群組]。
在導覽選單中,依序點選「目錄」>「群組」。
將游標懸停在「gke-security-groups」列上,然後按一下「新增成員」。
在「Add members to 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 references將
GROUP_DOMAIN替換為computeclass-editors群組的網域名稱。建立 ClusterRoleBinding:
kubectl apply -f computeclass-editor-role-binding.yaml
確認限制
以下各節說明如何確認您在上述各節中設定的限制是否正常運作。如果您在 ValidatingAdmissionPolicies 或 RBAC 政策中設定自己的限制,請建立違反這些政策的工作負載,測試這些限制。
驗證 ValidatingAdmissionPolicy
儲存下列任一資訊清單,這些資訊清單各自違反 ValidatingAdmissionPolicy 的不同條件:
Deployment 使用節點選取器選取不允許的 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:
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_NAMEPod 容許叢集中的任何節點 taint:
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_USER將
MEMBER_USER替換為群組成員的電子郵件地址。輸出內容為
yes。使用不屬於
computeclass-editors群組的使用者憑證,向叢集進行驗證。檢查使用者是否可以建立 ComputeClass:
kubectl auth can-i create computeclasses.cloud.google.com \ --as=NON_MEMBER_USER將
NON_MEMBER_USER替換為非群組成員的使用者電子郵件地址。輸出內容為
no。
如果 kubectl auth can-i 指令的輸出內容是 yes,但使用者不是群組成員,請確認下列事項:
computeclass-editors群組是gke-security-groups群組的成員。- ClusterRoleBinding 中的群組電子郵件地址必須是群組的確切電子郵件地址,例如
computeclass-editors@example.com。
清除所用資源
為避免因為本教學課程所用資源,導致系統向 Google Cloud 帳戶收取費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。
如果您在本教學課程中,將 ValidatingAdmissionPolicy 和 RBAC 政策部署至正式版叢集,GKE 會封鎖違反政策的傳入 Pod 和 API 要求。如要維持這些政策的效力,請略過本節。如果您是在學習或測試環境中完成本教學課程,請參閱下列各節,瞭解如何刪除專案或個別資源。
刪除專案
刪除 Google Cloud 專案:
gcloud projects delete PROJECT_ID
刪除個別資源
刪除您建立的 ComputeClass:
kubectl delete computeclass access-restriction-class刪除 ValidatingAdmissionPolicy 和 ValidatingAdmissionPolicyBinding:
kubectl delete validatingadmissionpolicy restrict-computeclass-usage kubectl delete validatingadmissionpolicybinding restrict-computeclass-usage-binding刪除 ClusterRole 和 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 Architecture Center。