ComputeClass の変更と選択に対するアクセスを制限する

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 ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

  1. アカウントにログインします。 Google Cloud を初めて使用する場合は、 アカウントを作成して、 実際のシナリオでプロダクトがどのように機能するかを評価してください。 Google Cloud新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud CLI をインストールします。

  3. 外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。

  4. gcloud CLI を初期化するには、次のコマンドを実行します:

    gcloud init
  5. プロジェクトを作成または選択します Google Cloud

    プロジェクトを選択または作成するために必要なロール

    • プロジェクトを選択する: プロジェクトの選択に特定の 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 プロジェクトの名前に置き換えます。

  6. このガイドで既存のプロジェクトを使用する場合は、 このガイドを完了するために必要な権限があることを 確認します。新しいプロジェクトを作成した場合は、 必要な権限がすでに付与されています。

  7. プロジェクトで課金が有効になっていることを確認します Google Cloud 。

  8. Kubernetes Engine API を有効にします。

    API を有効にするために必要なロール

    API を有効にするには、 権限を含む Service Usage 管理者 IAM ロール(roles/serviceusage.serviceUsageAdmin)が必要です。serviceusage.services.enable詳しくは、ロールを付与する方法をご覧ください。

    gcloud services enable container.googleapis.com
  9. Google Cloud CLI をインストールします。

  10. 外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。

  11. gcloud CLI を初期化するには、次のコマンドを実行します:

    gcloud init
  12. プロジェクトを作成または選択します Google Cloud

    プロジェクトを選択または作成するために必要なロール

    • プロジェクトを選択する: プロジェクトの選択に特定の 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 プロジェクトの名前に置き換えます。

  13. このガイドで既存のプロジェクトを使用する場合は、 このガイドを完了するために必要な権限があることを 確認します。新しいプロジェクトを作成した場合は、 必要な権限がすでに付与されています。

  14. プロジェクトで課金が有効になっていることを確認します Google Cloud 。

  15. Kubernetes Engine API を有効にします。

    API を有効にするために必要なロール

    API を有効にするには、 権限を含む Service Usage 管理者 IAM ロール(roles/serviceusage.serviceUsageAdmin)が必要です。serviceusage.services.enable詳しくは、ロールを付与する方法をご覧ください。

    gcloud services enable container.googleapis.com
  16. ローカルシェルを使用する場合は、kubectl コンポーネントをインストールします。
    gcloud components install kubectl
  17. バージョン 1.30 以降を使用する GKE クラスタがあることを確認します。このチュートリアルでは、 Autopilot クラスタ を作成することもできます。
  18. RBAC 向け Google グループを使用するようにクラスタを構成します。
    1. ドメインに gke-security-groups グループを設定します。
    2. クラスタで RBAC 向け Google グループを有効にします。

    詳細については、 Google グループを設定するをご覧ください。

必要なロール

クラスタで RBAC ポリシーと Kubernetes オブジェクトを作成するために必要な権限を取得するには、プロジェクトに対する Kubernetes Engine 管理者(role/container.admin)IAM ロールを付与するよう管理者に依頼してください。ロールの付与については、プロジェクト、フォルダ、組織へのアクセスを管理するをご覧ください。

必要な権限は、カスタム ロールや他の事前定義 ロールから取得することもできます。

環境を準備する

このチュートリアルの作成タスクと検証タスクのためにクラスタを準備する手順は次のとおりです。

  1. クラスタに接続します。

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • CONTROL_PLANE_LOCATION: クラスタ コントロール プレーンのリージョンまたは ゾーン(例: us-central1us-central1-a)。
  2. このチュートリアルで使用する Namespace を作成します。クラスタ内の既存の Namespace を使用することもできます。

    kubectl create namespace computeclass-vap-tutorial
    
  3. ValidatingAdmissionPolicies と ValidatingAdmissionPolicyBindings の管理アクセス権を付与する RBAC ポリシーを作成します。

    1. 次のマニフェストを 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 は、ユーザー アカウントのメールアドレスに置き換えます。

    2. RBAC ポリシーを作成します。

      kubectl apply -f validatingadmissionpolicy-editor.yaml
      
  4. クラスタに ComputeClass を作成します。クラスタに ComputeClass がすでに存在する場合は、この手順をスキップします。

    1. 次のマニフェストを access-computeclass.yaml として保存します。

      apiVersion: cloud.google.com/v1
      kind: ComputeClass
      metadata:
        name: access-restriction-class
      spec:
        priorities:
        - machineFamily: e2
        nodePoolAutoCreation:
          enabled: true
        whenUnsatisfiable: ScaleUpAnyway
      
    2. ComputeClass を作成します。

      kubectl apply -f access-computeclass.yaml
      

ValidatingAdmissionPolicy を作成する

Pod が選択できる ComputeClass を制限するには、ValidatingAdmissionPolicy を作成して、特定の Namespace に適用します。ValidatingAdmissionPolicy 仕様を使用して、Pod が ComputeClass を選択する方法を制御します。このポリシーを作成して適用する手順は次のとおりです。

  1. 次の 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 のノードテイントに対応する 許容 を使用する 。
      • クラスタ内のすべてのノードテイントに一致する許容を使用する。

    この ValidatingAdmissionPolicy は一例です。式を使用すると、特定のラベルを持つ Pod が特定の ComputeClass を選択できないようにするなど、独自の条件に基づいてポリシーをトリガーできます。

  2. ValidatingAdmissionPolicy を作成します。

    kubectl apply -f restrict-computeclass-usage-vap.yaml
    
  3. 次の 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 Namespace に適用します。validationActions フィールドの値は、ValidatingAdmissionPolicy に違反する Pod または Deployment を拒否し、Kubernetes 監査ログにエントリを追加します。

  4. ValidatingAdmissionPolicyBinding を作成します。

    kubectl apply -f restrict-computeclass-usage-binding.yaml
    

RBAC ポリシーを構成する

ValidatingAdmissionPolicy を使用してワークロードが特定の ComputeClass を使用できないようにするだけでなく、RBAC を使用して、許可されていないプリンシパルがクラスタ内の ComputeClass を作成および変更できないようにします。次の手順では、RBAC 向け Google グループを使用して、特定のユーザー グループに ComputeClass へのアクセス権を付与する方法について説明します。

  1. ComputeClass エディタのグループを作成します。

    1. Google 管理コンソールで、[グループ] ページに移動します。

      グループに移動

    2. [グループを作成] をクリックします。

    3. [グループの詳細] ページで、次の操作を行います。

      1. [グループ名] フィールドに「computeclass-editors」と入力します。
      2. [グループのメールアドレス] フィールドに「computeclass-editors」と入力します。
      3. [セキュリティ] チェックボックスをオンにします。
      4. [次へ] をクリックします。
    4. [アクセスタイプ] ページの [グループ メンバー] 列で、[メンバーを閲覧できるユーザー] チェックボックスがオンになっていることを確認します。

    5. [グループを作成] をクリックします。

    6. ナビゲーション メニューで、[ディレクトリ] [>] [グループ] をクリックします。

    7. [gke-security-groups] 行にカーソルを合わせ、[メンバーを追加] をクリックします。

    8. [gke-security-groups にメンバーを追加] ダイアログで、「computeclass-editors」と入力し、結果からそのグループを選択します。

    9. [グループに追加] をクリックします。

  2. 承認されたユーザーのメールアドレスを computeclass-editors グループに追加します。

  3. 次の 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"]
    
  4. ClusterRole を作成します。

    kubectl apply -f computeclass-editor-clusterrole.yaml
    
  5. 次の 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 グループのドメイン名に置き換えます。

  6. ClusterRoleBinding を作成します。

    kubectl apply -f computeclass-editor-role-binding.yaml
    

制限を確認する

以降のセクションでは、前のセクションで構成した制限が想定どおりに機能することを確認する方法について説明します。ValidatingAdmissionPolicies または RBAC ポリシーで独自の制限を構成する場合は、これらのポリシーに違反するワークロードを作成して制限をテストします。

ValidatingAdmissionPolicy を確認する

  1. 次のいずれかのマニフェストを保存します。各マニフェストは、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
      
  2. テスト ワークロードを作成します。

    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 構成を確認する手順は次のとおりです。

  1. computeclass-editors グループのメンバーであるユーザーの認証情報を使用して、クラスタに対して認証を行います。

  2. ユーザーが ComputeClass を作成できるかどうかを確認します。

    kubectl auth can-i create computeclasses.cloud.google.com \
        --as=MEMBER_USER
    

    MEMBER_USER は、グループのメンバーであるユーザーのメールアドレスに置き換えます。

    出力は yes です。

  3. computeclass-editors グループのメンバーではないユーザーの認証情報を使用して、クラスタに対して認証を行います。

  4. ユーザーが 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

リソースを個別に削除する

  1. 作成した ComputeClass を削除します。

    kubectl delete computeclass access-restriction-class
    
  2. ValidatingAdmissionPolicy と ValidatingAdmissionPolicyBinding を削除します。

    kubectl delete validatingadmissionpolicy restrict-computeclass-usage
    kubectl delete validatingadmissionpolicybinding restrict-computeclass-usage-binding
    
  3. ClusterRole と ClusterRoleBinding を削除します。

    kubectl delete clusterroles \
        computeclass-editor validatingadmissionpolicy-editor
    kubectl delete clusterrolebindings \
        computeclass-editor-role-binding edit-validatingadmissionpolicies
    
  4. サンプル Namespace を削除します。

    kubectl delete namespace computeclass-vap-tutorial
    

次のステップ