Restringir o acesso para modificar e selecionar ComputeClasses

É possível usar as ComputeClasses do Google Kubernetes Engine (GKE) para criar nós que atendam a vários requisitos de carga de trabalho. Os pods podem usar ComputeClasses para criar hardware. Dependendo da ComputeClass, esse hardware pode estar em demanda, ter disponibilidade limitada ou ser relativamente caro para sua empresa. Este tutorial mostra como usar o RBAC do Kubernetes e ValidatingAdmissionPolicies para restringir a criação, exclusão, modificação e seleção de ComputeClasses.

Essas restrições podem ajudar a evitar situações como as seguintes:

  • Os pods que não precisam de hardware especializado, como GPUs ou TPUs, selecionam ComputeClasses que solicitam esse hardware.
  • Uma entidade não autorizada cria ou modifica ComputeClasses para ter acesso a hardware reservado para cargas de trabalho críticas.

Este documento usa um exemplo de ValidatingAdmissionPolicy que bloqueia tipos comuns de uso indevido, como tolerâncias de ComputeClass curinga ou a seleção de ComputeClasses específicas não permitidas. É possível modificar a ValidatingAdmissionPolicy para atender a requisitos específicos da sua organização, como bloquear workloads de determinadas equipes para que não usem ComputeClasses.

Objetivos

  • Use uma ValidatingAdmissionPolicy para limitar as ComputeClasses que os pods podem selecionar em cada namespace a uma lista aprovada.
  • Use o controle de acesso baseado em papéis (RBAC) para restringir quem pode criar, modificar ou excluir ComputeClasses nos seus clusters.

Custos

Neste documento, você vai usar os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.

Novos usuários do Google Cloud podem estar qualificados para um teste sem custo financeiro.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Para mais informações, consulte Limpeza.

Antes de começar

  1. Faça login na sua conta do Google Cloud . Se você começou a usar o Google Cloud, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. Instale a CLI do Google Cloud.

  3. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na CLI gcloud com sua identidade federada.

  4. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  5. Crie ou selecione um Google Cloud projeto.

    Funções necessárias para selecionar ou criar um projeto

    • Selecionar um projeto: não é necessário um papel específico do IAM para selecionar um projeto. Você pode escolher qualquer projeto em que tenha recebido um papel.
    • Criar um projeto: para criar um projeto, é necessário ter o papel de Criador de projetos (roles/resourcemanager.projectCreator), que contém a permissão resourcemanager.projects.create. Saiba como conceder papéis.
    • Crie um projeto do Google Cloud :

      gcloud projects create PROJECT_ID

      Substitua PROJECT_ID por um nome para o projeto Google Cloud que você está criando.

    • Selecione o projeto Google Cloud que você criou:

      gcloud config set project PROJECT_ID

      Substitua PROJECT_ID pelo nome do projeto do Google Cloud .

  6. Se este guia estiver usando um projeto atual, verifique se você tem as permissões necessárias para concluir o guia. Se você criou um projeto, já tem as permissões necessárias.

  7. Verifique se o faturamento está ativado para o projeto do Google Cloud .

  8. Ative a API Kubernetes Engine.

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter o papel do IAM de administrador de uso do serviço (roles/serviceusage.serviceUsageAdmin), que contém a permissão serviceusage.services.enable. Saiba como conceder papéis.

    gcloud services enable container.googleapis.com
  9. Instale a CLI do Google Cloud.

  10. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na CLI gcloud com sua identidade federada.

  11. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  12. Crie ou selecione um Google Cloud projeto.

    Funções necessárias para selecionar ou criar um projeto

    • Selecionar um projeto: não é necessário um papel específico do IAM para selecionar um projeto. Você pode escolher qualquer projeto em que tenha recebido um papel.
    • Criar um projeto: para criar um projeto, é necessário ter o papel de Criador de projetos (roles/resourcemanager.projectCreator), que contém a permissão resourcemanager.projects.create. Saiba como conceder papéis.
    • Crie um projeto do Google Cloud :

      gcloud projects create PROJECT_ID

      Substitua PROJECT_ID por um nome para o projeto Google Cloud que você está criando.

    • Selecione o projeto Google Cloud que você criou:

      gcloud config set project PROJECT_ID

      Substitua PROJECT_ID pelo nome do projeto do Google Cloud .

  13. Se este guia estiver usando um projeto atual, verifique se você tem as permissões necessárias para concluir o guia. Se você criou um projeto, já tem as permissões necessárias.

  14. Verifique se o faturamento está ativado para o projeto do Google Cloud .

  15. Ative a API Kubernetes Engine.

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter o papel do IAM de administrador de uso do serviço (roles/serviceusage.serviceUsageAdmin), que contém a permissão serviceusage.services.enable. Saiba como conceder papéis.

    gcloud services enable container.googleapis.com
  16. Se você usa um shell local, instale o componente kubectl:
    gcloud components install kubectl
  17. Verifique se você tem um cluster do GKE que usa a versão 1.30 ou mais recente. Você também pode criar um cluster do Autopilot para este tutorial.
  18. Configure o cluster para os Grupos do Google para RBAC:
    1. Configure o grupo gke-security-groups no seu domínio.
    2. Ative os Grupos do Google para RBAC no cluster.

    Para mais informações, consulte Configurar o Google Grupos.

Funções exigidas

Para receber as permissões necessárias para criar políticas de RBAC e objetos do Kubernetes no seu cluster, peça ao administrador para conceder a você o papel do IAM de administrador do Kubernetes Engine (role/container.admin) no seu projeto. Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias usando papéis personalizados ou outros papéis predefinidos.

Prepare o ambiente

Para preparar o cluster para as tarefas de criação e verificação deste tutorial, siga estas etapas:

  1. Conecte-se ao cluster:

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

    Substitua:

    • CLUSTER_NAME: o nome do cluster.
    • CONTROL_PLANE_LOCATION: a região ou zona do plano de controle do cluster, como us-central1 ou us-central1-a.
  2. Crie um namespace para usar neste tutorial. Também é possível usar qualquer namespace existente no cluster.

    kubectl create namespace computeclass-vap-tutorial
    
  3. Crie uma política de RBAC que conceda acesso para gerenciar ValidatingAdmissionPolicies e ValidatingAdmissionPolicyBindings:

    1. Salve o seguinte manifesto como 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
      

      Substitua USER_ACCOUNT pelo endereço de e-mail da sua conta de usuário.

    2. Crie a política de RBAC:

      kubectl apply -f validatingadmissionpolicy-editor.yaml
      
  4. Crie uma ComputeClass no cluster. Se o cluster já tiver uma ComputeClass, pule esta etapa.

    1. Salve o seguinte manifesto como 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. Crie a ComputeClass:

      kubectl apply -f access-computeclass.yaml
      

Criar uma ValidatingAdmissionPolicy

Para restringir as ComputeClasses que os pods podem selecionar, crie uma ValidatingAdmissionPolicy e aplique-a em um namespace específico. Você usa a especificação ValidatingAdmissionPolicy para controlar como os pods podem selecionar ComputeClasses. As etapas a seguir mostram como criar e aplicar essa política:

  1. Salve o seguinte manifesto ValidatingAdmissionPolicy como 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.
    

    Substitua COMPUTECLASS_NAME pelo nome de uma ComputeClass que você quer impedir que os pods selecionem.

    Essa ValidatingAdmissionPolicy tem as seguintes propriedades:

    • Gatilhos para pods estáticos ou pods em implantações.
    • Encontra pods que fazem o seguinte:

      • Use um seletor de nós ou uma regra de afinidade de nós para selecionar explicitamente uma ComputeClass específica não permitida.
      • Use uma tolerância que corresponda a uma taint de nó para uma ComputeClass específica não permitida.
      • Use uma tolerância que corresponda a todas as taints de nós no cluster.

    Esta ValidatingAdmissionPolicy é um exemplo. É possível usar expressões para acionar a política com base nas suas próprias condições, como impedir que pods com rótulos específicos selecionem determinadas ComputeClasses.

  2. Crie a ValidatingAdmissionPolicy:

    kubectl apply -f restrict-computeclass-usage-vap.yaml
    
  3. Salve o seguinte ValidatingAdmissionPolicyBinding como 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.
    

    Essa ValidatingAdmissionPolicyBinding aplica a ValidatingAdmissionPolicy da etapa anterior no namespace computeclass-vap-tutorial. Os valores no campo validationActions rejeitam pods ou implantações que violam o ValidatingAdmissionPolicy e adicionam uma entrada ao registro de auditoria do Kubernetes.

  4. Crie o ValidatingAdmissionPolicyBinding:

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

Configurar políticas de RBAC

Além de usar um ValidatingAdmissionPolicy para impedir que as cargas de trabalho usem determinadas ComputeClasses, use o RBAC para impedir que principais não autorizados criem e modifiquem as ComputeClasses no cluster. As etapas a seguir mostram como conceder acesso a ComputeClasses a um grupo específico de usuários usando os Grupos do Google para RBAC:

  1. Crie um grupo para editores de ComputeClass:

    1. No Google Admin Console, acesse a página Grupos.

      Acessar o Grupos do Google

    2. Clique em Criar grupo.

    3. Na página Detalhes do grupo, faça o seguinte:

      1. No campo Nome do grupo, especifique computeclass-editors.
      2. No campo E-mail do grupo, especifique computeclass-editors.
      3. Marque a caixa de seleção Segurança.
      4. Clique em Próxima.
    4. Na página Tipo de acesso, na coluna Participantes do grupo, verifique se a caixa de seleção Quem pode ver os participantes está marcada.

    5. Clique em Criar grupo.

    6. No menu de navegação, clique em Diretório > Grupos.

    7. Passe o cursor sobre a linha gke-security-groups e clique em Adicionar participantes.

    8. Na caixa de diálogo Adicionar membros a gke-security-groups, especifique computeclass-editors e selecione esse grupo nos resultados.

    9. Clique em Adicionar ao grupo.

  2. Adicione os endereços de e-mail dos usuários autorizados ao grupo computeclass-editors.

  3. Salve o seguinte ClusterRole como 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. Crie o ClusterRole:

    kubectl apply -f computeclass-editor-clusterrole.yaml
    
  5. Salve o seguinte ClusterRoleBinding como 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
    

    Substitua GROUP_DOMAIN pelo nome de domínio do grupo computeclass-editors.

  6. Crie o ClusterRoleBinding:

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

Verificar suas restrições

As seções a seguir mostram como verificar se as restrições configuradas nas seções anteriores funcionam conforme o esperado. Se você configurar suas próprias restrições em ValidatingAdmissionPolicies ou políticas de RBAC, teste as restrições criando uma carga de trabalho que viole essas políticas.

Verificar a ValidatingAdmissionPolicy

  1. Salve um dos seguintes manifestos, cada um dos quais viola uma condição diferente da ValidatingAdmissionPolicy:

    • Implantação que usa um seletor de nós para selecionar uma ComputeClass não permitida:

      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
      
    • Implantação com uma tolerância para uma ComputeClass não permitida:

      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
      
    • Implantação com uma regra de afinidade de nó para uma ComputeClass não permitida:

      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 que tem uma tolerância para qualquer taint de nó no 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. Crie a carga de trabalho de teste:

    kubectl apply -f PATH_TO_WORKLOAD_MANIFEST
    

    O resultado será o seguinte:

    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.
    

Verificar a configuração do RBAC

Para verificar sua configuração de RBAC, siga estas etapas:

  1. Autentique-se no cluster usando as credenciais de um usuário que seja membro do grupo computeclass-editors.

  2. Verifique se o usuário pode criar uma ComputeClass:

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

    Substitua MEMBER_USER pelo endereço de e-mail de um usuário que é membro do grupo.

    A resposta é yes.

  3. Autentique-se no cluster usando as credenciais de um usuário que não é membro do grupo computeclass-editors.

  4. Verifique se o usuário pode criar uma ComputeClass:

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

    Substitua NON_MEMBER_USER pelo endereço de e-mail de um usuário que não é participante do grupo.

    A resposta é no.

Se a saída do comando kubectl auth can-i for yes para um usuário que não é membro do grupo, verifique o seguinte:

  • O grupo computeclass-editors é membro do grupo gke-security-groups.
  • O endereço de e-mail do grupo no ClusterRoleBinding é o endereço exato do grupo, como computeclass-editors@example.com.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Se você implantar as políticas ValidatingAdmissionPolicy e RBAC neste tutorial em um cluster de produção, o GKE vai bloquear os pods e as solicitações de API recebidos que violarem as políticas. Para manter essas políticas ativas, pule esta seção. As seções a seguir mostram como excluir o projeto ou recursos individuais se você seguiu este tutorial em um ambiente de aprendizado ou teste.

Excluir o projeto

    Excluir um projeto do Google Cloud :

    gcloud projects delete PROJECT_ID

Excluir recursos individuais

  1. Exclua a ComputeClass que você criou:

    kubectl delete computeclass access-restriction-class
    
  2. Exclua o ValidatingAdmissionPolicy e o ValidatingAdmissionPolicyBinding:

    kubectl delete validatingadmissionpolicy restrict-computeclass-usage
    kubectl delete validatingadmissionpolicybinding restrict-computeclass-usage-binding
    
  3. Exclua os ClusterRoles e os ClusterRoleBindings:

    kubectl delete clusterroles \
        computeclass-editor validatingadmissionpolicy-editor
    kubectl delete clusterrolebindings \
        computeclass-editor-role-binding edit-validatingadmissionpolicies
    
  4. Exclua o namespace de exemplo:

    kubectl delete namespace computeclass-vap-tutorial
    

A seguir