Como usar cotas de recursos hierárquicos

As cotas de recursos do Kubernetes são uma ferramenta para que os administradores garantam uma parcela razoável de recursos entre usuários diferentes. Uma cota de recursos, definida por um objeto ResourceQuota, fornece restrições que limitam o consumo de recursos agregados em um único namespace.

O Controlador de hierarquia estende o conceito de cotas de recursos por namespace para compatibilidade com namespaces hierárquicos. Um objeto HierarchicalResourceQuota limita o consumo de recursos agregados em todos os namespaces em uma subárvore, permitindo que os administradores limitem o consumo de recursos em vários namespaces relacionados.

Quando as cotas de recursos hierárquicos são ativadas, o controlador de hierarquia instala dois recursos de validadores de admissão, um para aplicar os limites de consumo e outro para validar as cotas de recursos hierárquicos.

Como ativar cotas de recursos hierárquicos

As cotas de recursos hierárquicos são fornecidas pelo controlador de hierarquia. Para ativar as cotas de recursos hierárquicos, siga estas etapas:

  1. Instale o Controlador de hierarquia usando o Config Sync 1.6.2 ou posterior.

  2. No arquivo de configuração do operador do Config Sync, no objeto spec.hierarchyController, defina o valor de enableHierarchicalResourceQuota como true:

    # config-management.yaml
    
    apiVersion: configmanagement.gke.io/v1
    kind: ConfigManagement
    metadata:
      name: config-management
    spec:
      hierarchyController:
        enabled: true
        # Set to true to enable hierarchical resource quotas:
        enableHierarchicalResourceQuota: true
      # ...other fields...
    
  3. Aplique a configuração:

    kubectl apply -f config-management.yaml
    

    Após cerca de um minuto, o Controlador de hierarquia e as cotas de recursos hierárquicos podem ser usadas no cluster.

Para verificar se as cotas de recursos hierárquicos estão ativadas, siga estas etapas:

  1. Crie um objeto HierarchicalResourceQuota em qualquer namespace, como o seguinte:

    cat > example-hrq.yaml <<EOF
    apiVersion: hierarchycontroller.configmanagement.gke.io/v1alpha1
    kind: HierarchicalResourceQuota
    metadata:
      name: example-hrq
    spec:
      hard:
        configmaps: "1"
    EOF
    
    kubectl apply -f example-hrq.yaml -n default
    
  2. Verifique se um novo objeto ResourceQuota chamado gke-hc-hrq foi criado no namespace com o mesmo spec.hard de 1 configmap, por exemplo:

    kubectl describe resourcequota gke-hc-hrq -n default
    

    Saída:

    Name:           gke-hc-hrq
    Namespace:      default
    Resource        Used    Hard
    --------        ----    ----
    configmaps      0       1
    
  3. Limpar:

    kubectl delete hrq -n default example-hrq
    

    Verifique se o objeto criado automaticamente foi removido:

    kubectl get resourcequota gke-hc-hrq -n default
    

    Saída:

    Error from server (NotFound): resourcequotas "gke-hc-hrq" not found
    

Como usar cotas de recursos hierárquicos

Como definir cotas

Definir um HierarchicalResourceQuota é o mesmo que definir um ResourceQuota normal, mas com um apiVersion e um kind diferentes; Portanto, é possível definir limites em recursos no campo spec.hard como em ResourceQuota.

Considere uma equipe chamada team-a que tem um serviço chamado service-a e tem uma subequipe chamada team-b. Todas elas são representadas por namespaces hierárquicos da seguinte maneira:

kubectl hns tree team-a

Saída:

team-a
├── service-a
└── team-b

Se você quiser limitar o número de configmaps em team-a, mas sem limitar o número em quaisquer descendentes, crie uma ResourceQuota regular da seguinte forma:

cat > team-a-rq.yaml <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-a-rq
  namespace: team-a
spec:
  hard:
    configmaps: "1"
EOF

kubectl apply -f team-a-rq.yaml

No entanto, para limitar o número total de configmaps em team-a e seus descendentes combinados, substitua apiVersion e kind no exemplo anterior:

cat > team-a-hrq.yaml <<EOF
# Modify the following two lines:
apiVersion: hierarchycontroller.configmanagement.gke.io/v1alpha1
kind: HierarchicalResourceQuota
# Everything below this line remains the same
metadata:
  name: team-a-hrq
  namespace: team-a
spec:
  hard:
    configmaps: "1"

EOF

kubectl apply -f team-a-hrq.yaml

A primeira tentativa de criar um configmap em qualquer um desses três namespaces será bem-sucedida. Por exemplo, podemos optar por criar o configmap em um dos namespaces filhos:

kubectl create configmap config-1 --from-literal key=value -n team-b

Saída:

confimap/config-1 created

No entanto, qualquer nova tentativa de criar novos configmaps em qualquer um dos três namespaces falhará, incluindo nos namespaces irmãos ou pai:

kubectl create configmap config-2 --from-literal key=value -n service-a
kubectl create configmap config-2 --from-literal key=value -n team-a

Saída para ambos:

Error from server (Forbidden): admission webhook "resourcesquotasstatus.hierarchycontroller.configmanagement.gke.io" denied the request: exceeded hierarchical quota in namespace "team-a": "team-a-hrq", requested: configmaps=1, used: configmaps=1, limited: configmaps=1

Como inspecionar cotas

Para ver os limites atuais e o uso de HierarchicalResourceQuota, use o comando kubectl describe para visualizar uma cota de recursos regular:

kubectl describe hrq team-a-hrq -n team-a

Saída:

# ...other fields...
Spec:
  Hard:
    Configmaps:  1
Status:
  Hard:
    Configmaps:  1
  Used:
    Configmaps:  1

Como atualizar a hierarquia de namespace

Um namespace sempre está sujeito a qualquer HierarchicalResourceQuota nos ancestrais. Modificar a hierarquia de namespace aciona um novo cálculo dos usos de qualquer cota.

Como remover um namespace de uma subárvore com cotas hierárquicas

Quando um namespace é removido de uma subárvore com cotas hierárquicas nos ancestrais, ele não está mais sujeito a essas cotas e os recursos dele são removidos dos usos das cotas.

Por exemplo, se team-b for removido da subárvore anterior, não haverá limites no consumo de configmap em team-b. O uso da cota hierárquica é redefinido para 0, o que significa que team-a e service-a agora podem consumir mais configmap no total.

Como adicionar um namespace a uma subárvore com cotas hierárquicas

Quando um namespace é adicionado a uma subárvore com cotas hierárquicas, ele está sujeito às cotas hierárquicas e os usos de recursos são adicionados aos usos das cotas.

Por exemplo, se outro namespace for adicionado à subárvore anterior, nenhum outro consumo de configmap será permitido no namespace recém-adicionado. Da mesma forma, qualquer uso configmap existente no namespace recém-adicionado será adicionado ao uso da cota hierárquica.

As cotas hierárquicas não impedem que você mova um novo namespace para uma subárvore, mesmo que o uso do novo namespace exceda o limite nas cotas hierárquicas. No entanto, se um limite for excedido, o uso adicional de recursos será banido até que o uso fique abaixo do limite ou até que o limite seja aumentado. Isso é semelhante ao comportamento do Kubernetes ResourceQuota quando um limite é imposto abaixo do uso atual no namespace.

Regras gerais

As cotas de recursos hierárquicos se comportam de maneira semelhante às cotas de recursos do Kubernetes em casos extremos. Exemplo:

  • Se várias cotas de recursos hierárquicos se aplicarem ao mesmo namespace, os limites de recurso mais restritivos serão respeitados.
  • Se você criar um limite inferior à quantidade de recursos já consumidos, os recursos atuais não serão excluídos. No entanto, qualquer consumo futuro de recursos será proibido até que o uso fique abaixo do limite ou o limite seja aumentado.

Solução de problemas

InternalError ao consumir recursos

Quando você consome recursos, por exemplo, ao criar um configmap, sua solicitação pode parar de responder por 10 segundos, e você receberá a seguinte mensagem de erro:

Error from server (InternalError): Internal error occurred: resource quota evaluates timeout

Você não verá essa mensagem de erro a menos que o pod gke-hc-controller-manager esteja em mau estado.

Para corrigir o problema, os administradores com permissão podem excluir o pod usando o prefixo gke-hc-controller-manager- diretamente no namespace hnc-system. O pod é reiniciado automaticamente. Antes que o pod esteja pronto, esteja ciente do seguinte:

Se isso não corrigir o problema, envie-o para análise, preferencialmente com registros que você pode conseguir usando o seguinte:

kubectl logs -n hnc-system deployment/gke-hc-controller-manager -c manager

A seguir