Restreindre l'accès à la modification et à la sélection des ComputeClasses

Vous pouvez utiliser les ComputeClasses de Google Kubernetes Engine (GKE) pour créer des nœuds qui répondent à diverses exigences de charge de travail. Les pods peuvent utiliser des ComputeClasses pour créer du matériel. En fonction de la ComputeClass, ce matériel peut être très demandé, limité en disponibilité ou relativement coûteux pour votre entreprise. Ce tutoriel vous explique comment utiliser le RBAC Kubernetes et les ValidatingAdmissionPolicies pour restreindre la création, la suppression, la modification et la sélection des ComputeClasses.

Ces restrictions peuvent vous aider à éviter les situations suivantes :

  • Les pods qui n'ont pas besoin de matériel spécialisé comme des GPU ou des TPU sélectionnent les ComputeClasses qui demandent ce matériel.
  • Une entité non autorisée crée ou modifie des ComputeClasses pour accéder au matériel réservé aux charges de travail critiques.

Ce document utilise un exemple de ValidatingAdmissionPolicy qui bloque les types courants d'utilisation abusive, tels que les tolérances ComputeClass génériques ou la sélection de ComputeClass spécifiques non autorisées. Vous pouvez modifier la ValidatingAdmissionPolicy pour répondre aux exigences spécifiques de votre organisation, par exemple en empêchant les charges de travail de certaines équipes d'utiliser des ComputeClasses.

Objectifs

  • Utilisez une ValidatingAdmissionPolicy pour limiter les ComputeClasses que les pods peuvent sélectionner dans chaque espace de noms à une liste approuvée.
  • Utilisez le contrôle des accès basé sur les rôles (RBAC) pour limiter les utilisateurs autorisés à créer, modifier ou supprimer des ComputeClasses dans vos clusters.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Pour obtenir une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai sans frais.

Une fois que vous avez terminé les tâches décrites dans ce document, supprimez les ressources que vous avez créées pour éviter que des frais vous soient facturés. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits sans frais pour exécuter, tester et déployer des charges de travail.
  2. Installez la Google Cloud CLI.

  3. Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.

  4. Pour initialiser la gcloud CLI, exécutez la commande suivante :

    gcloud init
  5. Créez ou sélectionnez un projet Google Cloud .

    Rôles requis pour sélectionner ou créer un projet

    • Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
    • Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.
    • Créez un projet Google Cloud  :

      gcloud projects create PROJECT_ID

      Remplacez PROJECT_ID par le nom du projet Google Cloud que vous créez.

    • Sélectionnez le projet Google Cloud que vous avez créé :

      gcloud config set project PROJECT_ID

      Remplacez PROJECT_ID par le nom de votre projet Google Cloud .

  6. Si vous utilisez un projet existant pour ce guide, vérifiez que vous disposez des autorisations nécessaires pour suivre les instructions. Si vous avez créé un projet, vous disposez déjà des autorisations requises.

  7. Vérifiez que la facturation est activée pour votre projet Google Cloud .

  8. Activez l'API Kubernetes Engine :

    Rôles requis pour activer les API

    Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin), qui contient l'autorisation serviceusage.services.enable. Découvrez comment attribuer des rôles.

    gcloud services enable container.googleapis.com
  9. Installez la Google Cloud CLI.

  10. Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.

  11. Pour initialiser la gcloud CLI, exécutez la commande suivante :

    gcloud init
  12. Créez ou sélectionnez un projet Google Cloud .

    Rôles requis pour sélectionner ou créer un projet

    • Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
    • Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.
    • Créez un projet Google Cloud  :

      gcloud projects create PROJECT_ID

      Remplacez PROJECT_ID par le nom du projet Google Cloud que vous créez.

    • Sélectionnez le projet Google Cloud que vous avez créé :

      gcloud config set project PROJECT_ID

      Remplacez PROJECT_ID par le nom de votre projet Google Cloud .

  13. Si vous utilisez un projet existant pour ce guide, vérifiez que vous disposez des autorisations nécessaires pour suivre les instructions. Si vous avez créé un projet, vous disposez déjà des autorisations requises.

  14. Vérifiez que la facturation est activée pour votre projet Google Cloud .

  15. Activez l'API Kubernetes Engine :

    Rôles requis pour activer les API

    Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin), qui contient l'autorisation serviceusage.services.enable. Découvrez comment attribuer des rôles.

    gcloud services enable container.googleapis.com
  16. Si vous utilisez une interface système locale, installez le composant kubectl :
    gcloud components install kubectl
  17. Assurez-vous de disposer d'un cluster GKE qui utilise la version 1.30 ou ultérieure. Vous pouvez également créer un cluster Autopilot pour ce tutoriel.
  18. Configurez votre cluster pour Google Groupes pour RBAC :
    1. Configurez le groupe gke-security-groups dans votre domaine.
    2. Activez Google Groupes pour RBAC dans votre cluster.

    Pour en savoir plus, consultez Configurer vos groupes Google.

Rôles requis

Pour obtenir les autorisations nécessaires pour créer des règles RBAC et des objets Kubernetes dans votre cluster, demandez à votre administrateur de vous accorder le rôle IAM Administrateur Kubernetes Engine (role/container.admin) sur votre projet. Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Préparer l'environnement

Pour préparer votre cluster aux tâches de création et de validation de ce tutoriel, procédez comme suit :

  1. Connectez-vous à votre cluster :

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

    Remplacez les éléments suivants :

    • CLUSTER_NAME : nom du cluster
    • CONTROL_PLANE_LOCATION : région ou zone du plan de contrôle du cluster, par exemple us-central1 ou us-central1-a.
  2. Créez un espace de noms à utiliser pour ce tutoriel. Vous pouvez également utiliser n'importe quel espace de noms existant dans le cluster.

    kubectl create namespace computeclass-vap-tutorial
    
  3. Créez une règle RBAC qui accorde l'accès à la gestion des ValidatingAdmissionPolicies et des ValidatingAdmissionPolicyBindings :

    1. Enregistrez le manifeste suivant sous le nom 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
      

      Remplacez USER_ACCOUNT par l'adresse e-mail de votre compte utilisateur.

    2. Créez la règle RBAC :

      kubectl apply -f validatingadmissionpolicy-editor.yaml
      
  4. Créez une ComputeClass dans votre cluster. Si le cluster dispose déjà d'une ComputeClass, ignorez cette étape.

    1. Enregistrez le manifeste suivant sous le nom 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. Créez la ComputeClass :

      kubectl apply -f access-computeclass.yaml
      

Créer une ValidatingAdmissionPolicy

Pour limiter les ComputeClasses que les pods peuvent sélectionner, vous devez créer une ValidatingAdmissionPolicy et l'appliquer dans un espace de noms spécifique. Vous utilisez la spécification ValidatingAdmissionPolicy pour contrôler la façon dont les pods peuvent sélectionner des ComputeClasses. Les étapes suivantes vous expliquent comment créer et appliquer cette règle :

  1. Enregistrez le fichier manifeste ValidatingAdmissionPolicy suivant sous le nom 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.
    

    Remplacez COMPUTECLASS_NAME par le nom d'une ComputeClass que vous souhaitez empêcher les pods de sélectionner.

    Cette ValidatingAdmissionPolicy possède les propriétés suivantes :

    • Déclencheurs pour les pods statiques ou les pods dans les déploiements.
    • Recherche les pods qui effectuent l'une des actions suivantes :

      • Utilisez un sélecteur de nœud ou une règle d'affinité de nœud pour sélectionner explicitement une ComputeClass spécifique non autorisée.
      • Utilisez une tolérance qui correspond à un taint de nœud pour une ComputeClass spécifique non autorisée.
      • Utilisez une tolérance qui correspond à tous les rejets de nœuds du cluster.

    Cette ValidatingAdmissionPolicy est un exemple. Vous pouvez utiliser des expressions pour déclencher la règle en fonction de vos propres conditions, par exemple pour empêcher les pods ayant des libellés spécifiques de sélectionner certaines ComputeClasses.

  2. Créez la ValidatingAdmissionPolicy :

    kubectl apply -f restrict-computeclass-usage-vap.yaml
    
  3. Enregistrez la ValidatingAdmissionPolicyBinding suivante sous le nom 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.
    

    Cette liaison ValidatingAdmissionPolicyBinding applique la ValidatingAdmissionPolicy de l'étape précédente dans l'espace de noms computeclass-vap-tutorial. Les valeurs du champ validationActions rejettent les pods ou les déploiements qui ne respectent pas la stratégie ValidatingAdmissionPolicy et ajoutent une entrée au journal d'audit Kubernetes.

  4. Créez ValidatingAdmissionPolicyBinding :

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

Configurer des règles RBAC

En plus d'utiliser une ValidatingAdmissionPolicy pour empêcher les charges de travail d'utiliser certaines ComputeClasses, utilisez RBAC pour empêcher les principaux non autorisés de créer et de modifier les ComputeClasses dans votre cluster. La procédure suivante vous montre comment accorder l'accès aux ComputeClasses à un groupe d'utilisateurs spécifique à l'aide de Google Groupes pour RBAC :

  1. Créez un groupe pour les éditeurs ComputeClass :

    1. Dans la console d'administration Google, accédez à la page Groupes.

      Accéder à Google Groupes

    2. Cliquez sur Créer un groupe.

    3. Sur la page Détails du groupe, procédez comme suit :

      1. Dans le champ Nom du groupe, spécifiez computeclass-editors.
      2. Dans le champ Adresse e-mail du groupe, spécifiez computeclass-editors.
      3. Cochez la case Sécurité.
      4. Cliquez sur Suivant.
    4. Sur la page Type d'accès, dans la colonne Membres du groupe, vérifiez que la case Qui peut voir les membres est cochée.

    5. Cliquez sur Créer un groupe.

    6. Dans le menu de navigation, cliquez sur Annuaire > Groupes.

    7. Pointez sur la ligne gke-security-groups, puis cliquez sur Ajouter des membres.

    8. Dans la boîte de dialogue Ajouter des membres à gke-security-groups, spécifiez computeclass-editors et sélectionnez ce groupe dans les résultats.

    9. Cliquez sur Ajouter au groupe.

  2. Ajoutez les adresses e-mail des utilisateurs autorisés au groupe computeclass-editors.

  3. Enregistrez le ClusterRole suivant sous le nom 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. Créez le ClusterRole :

    kubectl apply -f computeclass-editor-clusterrole.yaml
    
  5. Enregistrez le ClusterRoleBinding suivant sous le nom 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
    

    Remplacez GROUP_DOMAIN par le nom de domaine du groupe computeclass-editors.

  6. Créez l'objet ClusterRoleBinding :

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

Vérifier vos restrictions

Les sections suivantes vous expliquent comment vérifier que les restrictions que vous avez configurées dans les sections précédentes fonctionnent comme prévu. Si vous configurez vos propres restrictions dans ValidatingAdmissionPolicies ou des règles RBAC, testez-les en créant une charge de travail qui ne les respecte pas.

Valider la ValidatingAdmissionPolicy

  1. Enregistrez l'un des fichiers manifestes suivants, qui enfreignent chacun une condition différente de ValidatingAdmissionPolicy :

    • Déploiement qui utilise un sélecteur de nœud pour sélectionner une classe ComputeClass non autorisée :

      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
      
    • Déploiement avec une tolérance pour une ComputeClass non autorisée :

      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
      
    • Déploiement comportant une règle d'affinité de nœud pour une ComputeClass non autorisée :

      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 ayant une tolérance pour tout rejet de nœud dans le cluster :

      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. Créez la charge de travail de test :

    kubectl apply -f PATH_TO_WORKLOAD_MANIFEST
    

    Le résultat ressemble à ce qui suit :

    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.
    

Vérifier la configuration RBAC

Pour vérifier votre configuration RBAC, procédez comme suit :

  1. Authentifiez-vous auprès du cluster à l'aide des identifiants d'un utilisateur membre du groupe computeclass-editors.

  2. Vérifiez si l'utilisateur peut créer une ComputeClass :

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

    Remplacez MEMBER_USER par l'adresse e-mail d'un utilisateur membre du groupe.

    Le résultat est yes.

  3. Authentifiez-vous auprès du cluster en utilisant les identifiants d'un utilisateur qui n'est pas membre du groupe computeclass-editors.

  4. Vérifiez si l'utilisateur peut créer une ComputeClass :

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

    Remplacez NON_MEMBER_USER par l'adresse e-mail d'un utilisateur qui n'est pas membre du groupe.

    Le résultat est no.

Si le résultat de la commande kubectl auth can-i est yes pour un utilisateur qui n'est pas membre du groupe, vérifiez les points suivants :

  • Le groupe computeclass-editors est membre du groupe gke-security-groups.
  • L'adresse e-mail du groupe dans votre ClusterRoleBinding est l'adresse e-mail exacte du groupe, par exemple computeclass-editors@example.com.

Effectuer un nettoyage

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Si vous déployez les stratégies ValidatingAdmissionPolicy et RBAC de ce tutoriel dans un cluster de production, GKE bloque les pods et les requêtes API entrants qui ne respectent pas les stratégies. Pour que ces règles restent actives, ignorez cette section. Les sections suivantes vous expliquent comment supprimer le projet ou les ressources individuelles si vous avez suivi ce tutoriel dans un environnement d'apprentissage ou de test.

Supprimer le projet

    Supprimer un projet Google Cloud  :

    gcloud projects delete PROJECT_ID

Supprimer des ressources individuelles

  1. Supprimez la classe de calcul que vous avez créée :

    kubectl delete computeclass access-restriction-class
    
  2. Supprimez la ValidatingAdmissionPolicy et la ValidatingAdmissionPolicyBinding :

    kubectl delete validatingadmissionpolicy restrict-computeclass-usage
    kubectl delete validatingadmissionpolicybinding restrict-computeclass-usage-binding
    
  3. Supprimez les objets ClusterRole et ClusterRoleBinding :

    kubectl delete clusterroles \
        computeclass-editor validatingadmissionpolicy-editor
    kubectl delete clusterrolebindings \
        computeclass-editor-role-binding edit-validatingadmissionpolicies
    
  4. Supprimez l'espace de noms de l'exemple :

    kubectl delete namespace computeclass-vap-tutorial
    

Étapes suivantes