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/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 do Linux acesso somente leitura à API cgroups ativando o sistema de arquivos /sys/fs/cgroup em cada contêiner. Opcionalmente, é possível permitir que o GKE ative esse sistema de arquivos no modo de leitura/gravação em pods específicos para permitir que os processos raiz gerenciem e restrinjam recursos para processos filhos.

Esses cgroups graváveis ajudam a melhorar a confiabilidade em aplicativos como Ray que executam 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 Google Cloud CLI para essa tarefa, instale e, em seguida, inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da CLI gcloud não sejam compatíveis com a execução dos comandos neste documento.

Ativar cgroups graváveis para 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 nos 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 cgroups graváveis para o cluster ou pools de nós, configure as cargas de trabalho para atender a todos os requisitos a seguir:

  • Selecione um nó que tenha 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 init.

Para configurar esses requisitos, siga estas etapas:

  1. Para selecionar nós que têm cgroups graváveis ativados, adicione o node.gke.io/enable-writable-cgroups: "true" rótulo ao spec.nodeSelector campo 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:

    • Ativar 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 de QoS garantida para o pod, especifique solicitações e limites de CPU e memória iguais para cada contêiner no pod ou para todo o pod, 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 cada contêiner, mesmo que você ative cgroups graváveis apenas para um dos contêineres no pod.

A especificação final do pod precisa 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 é gravável

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. É possível usar um dos pods de amostra 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 ativado:

    mount | grep cgroup
    

    O resultado será assim:

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

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

A seguir