Google Kubernetes Engine(GKE)の ComputeClasses を使用すると、さまざまなワークロード要件を満たすノードを作成できます。Pod は ComputeClass を使用してハードウェアを作成できます。ComputeClass によって、そのハードウェアは需要が高い、可用性が低い、または企業にとって比較的コストが高い場合があります。このチュートリアルでは、Kubernetes RBAC と ValidatingAdmissionPolicies を使用して、ComputeClass の作成、削除、変更、選択を制限する方法について説明します。
これらの制限により、次のような状況を防ぐことができます。
- GPU や TPU などの専用ハードウェアを必要としない Pod は、そのハードウェアをリクエストする ComputeClass を選択します。
- 未承認のエンティティが ComputeClass を作成または変更して、重要なワークロード用に予約されているハードウェアにアクセスします。
このドキュメントでは、ワイルドカード ComputeClass 許容や特定の許可されていない ComputeClass の選択など、一般的なタイプの不正使用をブロックする ValidatingAdmissionPolicy の例を使用します。ValidatingAdmissionPolicy を変更して、特定のチームのワークロードが ComputeClass を使用できないようにするなど、組織固有の要件を満たすことができます。
目標
- ValidatingAdmissionPolicy を使用して、各 Namespace で Pod が選択できる 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権限が必要です。プロジェクトを作成した場合は、オーナーロール(roles/owner)を介してこの権限がすでに付与されている可能性があります。それ以外の場合は、Service Usage 管理者ロール(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権限が必要です。プロジェクトを作成した場合は、オーナーロール(roles/owner)を介してこの権限がすでに付与されている可能性があります。それ以外の場合は、Service Usage 管理者ロール(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など)。
このチュートリアルで使用する Namespace を作成します。クラスタ内の既存の Namespace を使用することもできます。
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 を作成する
Pod が選択できる ComputeClass を制限するには、ValidatingAdmissionPolicy を作成して、特定の Namespace で適用します。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 に対応する toleration を使用します。
- クラスタ内のすべてのノード taint と一致する toleration を使用します。
この 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 は、前の手順の ValidatingAdmissionPolicy を
computeclass-vap-tutorialNamespace で適用します。validationActionsフィールドの値は、ValidatingAdmissionPolicy に違反する Pod または Deployment を拒否し、Kubernetes 監査ログにエントリを追加します。ValidatingAdmissionPolicyBinding を作成します。
kubectl apply -f restrict-computeclass-usage-binding.yaml
RBAC ポリシーを構成する
ValidatingAdmissionPolicy を使用してワークロードが特定の ComputeClass を使用できないようにするだけでなく、RBAC を使用して、承認されていないプリンシパルがクラスタ内の ComputeClass を作成および変更できないようにします。次の手順では、RBAC 向け Google グループを使用して、特定のユーザー グループに ComputeClass へのアクセス権を付与する方法について説明します。
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 を選択する Deployment:
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 の容認がある Deployment:
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 のノード アフィニティ ルールがある Deployment:
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クラスタ内の任意のノード テイントの容認能力を持つ Pod:
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 はポリシーに違反する受信 Pod と 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サンプル Namespace を削除します。
kubectl delete namespace computeclass-vap-tutorial
次のステップ
- ComputeClass のベスト プラクティスを確認する
- クラスタ セキュリティのベスト プラクティスを確認する
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud アーキテクチャ センターをご覧ください。