Configurar cgroups graváveis para contêineres

É possível permitir que as cargas de trabalho do Google Kubernetes Engine (GKE) gerenciem recursos, como CPU e memória, para processos filhos usando a API cgroups do Linux. Este documento mostra como fornecer aos contêineres acesso de leitura e gravação à API cgroups sem executar esses contêineres no modo privilegiado.

Quando usar cgroups graváveis

Por padrão, o Kubernetes fornece a todos os contêineres Linux acesso somente leitura à API cgroups montando o sistema de arquivos /sys/fs/cgroup em cada contêiner. Se quiser, deixe o GKE montar esse sistema de arquivos no modo de leitura e gravação em pods específicos para permitir que processos raiz gerenciem e restrinjam recursos para processos filhos.

Esses cgroups graváveis ajudam a melhorar a confiabilidade em aplicativos como o Ray, que executa processos do sistema e código do usuário no mesmo contêiner. Ao gravar no sistema de arquivos /sys/fs/cgroup, o Ray pode reservar partes dos recursos de um contêiner para processos críticos. É possível usar cgroups graváveis para melhorar a confiabilidade nesses aplicativos sem o risco de segurança de usar o modo privilegiado para os contêineres.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a CLI do Google Cloud para essa tarefa, instale e inicialize a gcloud CLI. Se você instalou a gcloud CLI anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da gcloud CLI não sejam compatíveis com a execução dos comandos neste documento.

Ativar cgroups graváveis para os nós

Ative cgroups graváveis nos pools de nós personalizando a configuração do containerd. É possível aplicar essa configuração a todo o cluster ou a pools de nós específicos em clusters Standard.

No arquivo de configuração do containerd, adicione uma seção writableCgroups e defina o campo enabled como true. Para mais informações, consulte Personalizar a configuração do containerd em nós do GKE.

writableCgroups:
  enabled: true

Especifique o arquivo de configuração atualizado ao criar ou atualizar um cluster ou um pool de nós.

Usar cgroups graváveis em cargas de trabalho

Depois de ativar os cgroups graváveis para o cluster ou os pools de nós, configure as cargas de trabalho para atender a todos os requisitos a seguir:

  • Selecione um nó com cgroups graváveis ativados.
  • Ative cgroups graváveis para um ou mais contêineres no pod.
  • Use a classe de qualidade de serviço (QoS) garantida atendendo a uma das seguintes condições:

    • Para cargas de trabalho que especificam recursos no nível do pod, defina valores iguais para resources.requests e resources.limits na especificação do pod.
    • Para cargas de trabalho que especificam recursos para cada contêiner, defina valores iguais para resources.requests e resources.limits na especificação de cada contêiner no pod, incluindo contêineres de inicialização.

Para configurar esses requisitos, siga estas etapas:

  1. Para selecionar nós com cgroups graváveis ativados, adicione o rótulo node.gke.io/enable-writable-cgroups: "true" ao campo spec.nodeSelector na especificação do pod:

    node.gke.io/enable-writable-cgroups: "true"
    
  2. Para ativar cgroups graváveis para sua carga de trabalho, adicione um dos seguintes rótulos ao campo metadata.annotations na especificação do pod:

    • Ative para todo o pod:

      node.gke.io/enable-writable-cgroups: "true"
      
    • Ativar para um contêiner específico no pod:

      node.gke.io/enable-writable-cgroups.CONTAINER_NAME: "true"
      

      Substitua CONTAINER_NAME pelo nome do contêiner.

  3. Para configurar a classe QoS garantida para seu pod, especifique solicitações e limites iguais de CPU e memória para cada contêiner no pod ou para o pod inteiro, como no exemplo a seguir:

    resources:
      requests:
        cpu: "100m"
        memory: "100Mi"
      limits:
        cpu: "100m"
        memory: "100Mi"
    

    É necessário especificar solicitações e limites iguais para todos os contêineres, mesmo que você ative cgroups graváveis apenas para um dos contêineres no pod.

A especificação final do pod será semelhante aos exemplos a seguir.

  • Este exemplo ativa cgroups graváveis para todos os contêineres no pod:

    apiVersion: v1
    kind: Pod
    metadata:
      name: writable-cgroups-pod
      annotations:
        node.gke.io/enable-writable-cgroups: "true"
    spec:
      nodeSelector:
        node.gke.io/enable-writable-cgroups: "true"
      containers:
      - name: container
        image: busybox:stable
        command: ["/bin/sh", "-c"]
        args:
        -   |
          trap 'echo "Caught SIGTERM, exiting..."; exit 0' TERM
          echo "Waiting for termination signal..."
          while true; do sleep 1; done
      resources:
        requests:
          cpu: "100m"
          memory: "100Mi"
        limits:
          cpu: "100m"
          memory: "100Mi"
    
  • Este exemplo ativa cgroups graváveis para um contêiner específico em um pod de vários contêineres:

    apiVersion: v1
    kind: Pod
    metadata:
      name: writable-cgroups-per-container
      annotations:
        node.gke.io/enable-writable-cgroups.busybox-container: "true"
    spec:
      nodeSelector:
        node.gke.io/enable-writable-cgroups: "true"
      containers:
      - name: busybox-container
        image: busybox:stable
        command: ["/bin/sh", "-c"]
        args:
        -   |
          trap 'echo "Caught SIGTERM, exiting..."; exit 0' TERM
          echo "Waiting for termination signal..."
          while true; do sleep 1; done
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
          limits:
            cpu: "100m"
            memory: "100Mi"
      - name: container-disabled
        image: busybox:stable
        command: ["/bin/sh", "-c"]
        args:
        -   |
          trap 'echo "Caught SIGTERM, exiting..."; exit 0' TERM
          echo "Waiting for termination signal..."
          while true; do sleep 1; done
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
          limits:
            cpu: "100m"
            memory: "100Mi"
    

Verificar se o sistema de arquivos cgroup pode ser gravado

Para verificar as permissões no sistema de arquivos /sys/fs/cgroup de um pod ou contêiner, siga estas etapas:

  1. Identifique um pod que você quer verificar. Você pode usar um dos pods de exemplo da seção Usar cgroups graváveis em cargas de trabalho.
  2. Crie uma sessão do shell no pod:

    kubectl exec -it POD_NAME -- /bin/sh
    

    Substitua POD_NAME pelo nome do pod.

  3. Descreva o sistema de arquivos cgroup montado:

    mount | grep cgroup
    

    O resultado será o seguinte:

    cgroup on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)
    

    Nessa saída, rw indica que o sistema de arquivos pode ser gravado. Se você vir ro na saída, o sistema de arquivos será somente leitura.

A seguir