Configurar o contêiner secundário do driver CSI do Cloud Storage FUSE para GKE

Neste documento, mostramos como definir as configurações de recursos para o contêiner secundário do driver CSI do Cloud Storage FUSE no Google Kubernetes Engine (GKE).

Para otimizar o desempenho e o uso de recursos do aplicativo no GKE, configure definições de recursos específicas para o contêiner secundário do driver CSI do Cloud Storage FUSE. Ao configurar esses recursos, como uma imagem particular, um buffer de gravação personalizado e um volume de cache de leitura personalizado, você tem mais controle sobre como seus aplicativos interagem com o Cloud Storage. Essas configurações podem levar a um acesso mais rápido aos dados, tempos de processamento mais rápidos e, possivelmente, reduzir o consumo geral de recursos nos seus clusters do GKE.

Este documento é destinado a desenvolvedores, administradores e arquitetos que otimizam o desempenho de aplicativos. Para saber mais sobre papéis comuns e exemplos de tarefas que mencionamos no conteúdo do Google Cloud , consulte Funções e tarefas comuns do usuário do GKE.

Antes de começar, familiarize-se com os seguintes conceitos de carga de trabalho e armazenamento:

Como o contêiner secundário funciona

O driver CSI do Cloud Storage FUSE usa um contêiner secundário para ativar buckets do Cloud Storage e torná-los acessíveis como sistemas de arquivos locais para aplicativos do Kubernetes. Esse contêiner secundário, chamado gke-gcsfuse-sidecar, é executado ao lado do contêiner de carga de trabalho no mesmo pod. Quando o driver detecta a anotação gke-gcsfuse/volumes: "true" em uma especificação de pod, ele injetará automaticamente o contêiner secundário. Essa abordagem de contêiner secundário ajuda a garantir a segurança e gerenciar os recursos de maneira eficaz.

O contêiner secundário processa as complexidades da ativação dos buckets do Cloud Storage e fornece acesso ao sistema de arquivos para os aplicativos sem exigir que você gerencie o tempo de execução do Cloud Storage FUSE diretamente. É possível configurar limites de recursos para o contêiner secundário usando anotações como gke-gcsfuse/cpu-limit e gke-gcsfuse/memory-limit. O modelo de contêiner secundário também garante que a instância do Cloud Storage FUSE esteja vinculada ao ciclo de vida da carga de trabalho, impedindo que ela consuma recursos desnecessariamente. Isso significa que o contêiner secundário é encerrado automaticamente quando os contêineres de carga de trabalho são encerrados, especialmente em cargas de trabalho de job ou pods com um RestartPolicy de Never.

Compatibilidade do Istio com OSS

O contêiner secundário do driver CSI do Cloud Storage FUSE e o Istio podem coexistir e ser executados simultaneamente no pod. No entanto, na versão 1.29 e mais recentes do GKE, podem ocorrer falhas de autenticação se o Cloud Storage FUSE tentar se conectar ao servidor de metadados antes que o proxy do Istio esteja pronto. Se você encontrar essas falhas de autenticação, adicione traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32 a metadata.annotations na especificação do pod para resolver o problema. Essa anotação configura o Istio para excluir o endereço IP do servidor de metadados do GKE do redirecionamento.

Configurar buffer de gravação personalizado

O Cloud Storage FUSE prepara gravações em um diretório local e faz upload para o Cloud Storage em operações close ou fsync.

Nesta seção, descrevemos como configurar um volume de buffer personalizado para o armazenamento em buffer de gravação do Cloud Storage FUSE. Esse cenário pode ser aplicável se você precisar substituir o volume emptyDir padrão do Cloud Storage FUSE para preparar os arquivos em operações de gravação. Isso é útil se você precisar gravar arquivos maiores que 10 GiB nos clusters do Autopilot.

É possível especificar qualquer tipo de armazenamento compatível com o driver CSI do Cloud Storage FUSE para armazenamento em cache de arquivos, como um SSD local, armazenamento baseado em Persistent Disk e disco RAM (memória). O GKE vai usar o volume especificado para armazenamento em buffer de gravação de arquivo. Para saber mais sobre essas opções, consulte Selecionar o armazenamento para fazer backup do cache de arquivos.

Para usar um volume de buffer personalizado com suporte de um Persistent Disk, especifique um fsGroup diferente de zero no securityContext do pod. Essa etapa concede as permissões de leitura ou gravação necessárias para o volume ao contêiner sidecar não raiz. Essa configuração não é necessária se o PVC montar buckets do Cloud Storage como volumes permanentes usando o driver CSI do Cloud Storage FUSE.

O exemplo a seguir mostra como usar um PersistentVolumeClaim predefinido como o volume de buffer:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"
spec:
  securityContext:
    fsGroup: FS_GROUP
  containers:
  ...
  volumes:
  - name: gke-gcsfuse-buffer
    persistentVolumeClaim:
      claimName: BUFFER_VOLUME_PVC

Substitua:

  • FS_GROUP: o ID do fsGroup.
  • BUFFER_VOLUME_PVC: o nome da PVC predefinida.

Configurar o volume de cache de leitura personalizado

Nesta seção, descrevemos como configurar um volume de cache personalizado para o armazenamento em cache de leitura do Cloud Storage FUSE.

Este cenário pode ser aplicável se você precisar substituir o volume emptyDir padrão do Cloud Storage FUSE para preparar os arquivos em operações de gravação. É possível especificar qualquer tipo de armazenamento compatível com o GKE, como um PersistentVolumeClaim, e o GKE usará o volume especificado para armazenamento em cache de arquivos. Isso é útil se você precisar armazenar em cache arquivos maiores que 10 GiB em clusters do Autopilot.

Para usar um volume de cache personalizado com suporte de um Persistent Disk, especifique um fsGroup diferente de zero no securityContext do seu pod. Essa etapa concede as permissões de leitura ou gravação necessárias para o volume ao contêiner sidecar não raiz. Essa configuração não é necessária se a PVC montar buckets do Cloud Storage como volumes permanentes usando o driver CSI do Cloud Storage FUSE.

O exemplo a seguir mostra como usar um PersistentVolumeClaim predefinido como o volume de cache:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"
spec:
  securityContext:
    fsGroup: FS_GROUP
  containers:
  ...
  volumes:
  - name: gke-gcsfuse-cache
    persistentVolumeClaim:
      claimName: CACHE_VOLUME_PVC

Substitua:

  • FS_GROUP: o ID do fsGroup.
  • CACHE_VOLUME_PVC: o nome predefinido do PersistentVolumeClaim.

Configurar uma imagem particular para o contêiner secundário

Nesta seção, descrevemos como usar a imagem do contêiner secundário quando você a hospeda em um registro de contêiner particular. Esse cenário será aplicável se você precisar usar nós particulares para fins de segurança.

Para configurar e consumir a imagem do contêiner secundário particular, siga estas etapas:

  1. Consulte esta tabela de compatibilidade do GKE para encontrar uma imagem de contêiner secundário público compatível.
  2. Extraia-a para o ambiente local e envie para o registro de contêiner particular.
  3. No manifesto, especifique um contêiner chamado gke-gcsfuse-sidecar com apenas o campo de imagem. O GKE usará a imagem do contêiner secundário especificada para se preparar para a injeção desse contêiner.

    Veja um exemplo:

    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
        gke-gcsfuse/volumes: "true"
    spec:
      containers:
      - name: gke-gcsfuse-sidecar
        image: PRIVATE_REGISTRY/gcs-fuse-csi-driver-sidecar-mounter:PRIVATE_IMAGE_TAG
      - name: main # your main workload container.
    

    Substitua:

    • PRIVATE_REGISTRY: o registro de contêiner particular. Por exemplo, us-central1-docker.pkg.dev/my-project/my-registry.
    • PRIVATE_IMAGE_TAG: a tag de imagem do contêiner secundário particular. Por exemplo, v1.17.1-gke.1.

Configurar recursos do contêiner secundário

Por padrão, o contêiner gke-gcsfuse-sidecar é configurado com as seguintes solicitações e limites de recursos para clusters Standard e Autopilot:

Solicitações:

  • 250m CPU
  • 256 MiB de memória
  • Armazenamento temporário de 5 GiB

Limites (GKE versão 1.29.1-gke.1670000 e mais recente):

  • cpu ilimitada
  • memória ilimitada
  • armazenamento temporário ilimitado

Limites (antes da versão 1.29.1-gke.1670000 do GKE):

  • 250m CPU
  • 256 MiB de memória
  • Armazenamento temporário de 5 GiB

Por padrão, o contêiner gke-gcsfuse-metadata-prefetch é configurado com as seguintes solicitações e limites de recursos para clusters Standard e Autopilot:

Solicitações:

  • 10m CPU
  • 10 MiB de memória
  • Armazenamento temporário de 10 MiB

Limites:

  • 50m CPU
  • 250 MiB de memória
  • armazenamento temporário ilimitado

Nos clusters Standard e Autopilot, é possível substituir os valores padrão. A maneira como o GKE processa recursos de contêiner depende do modo de operação do cluster:

  • Clusters padrão: se uma das solicitações ou um dos limites for definido e outro não, os limites e as solicitações de recursos dos pods serão definidos como iguais. Se a solicitação e os limites forem definidos, os pods usarão as solicitações de recurso e os limites exatos especificados. Se você não definir nenhum valor, os recursos padrão (descritos acima) serão aplicados diretamente.
  • Clusters do Autopilot: se uma das solicitações ou limites for definida e outra não, os limites e solicitações de recursos dos pods serão definidos como iguais. Consulte Como definir limites de recursos no Autopilot para entender como as substituições de recursos e os valores de recursos padrão definidos afetam o comportamento do pod.

Para substituir os valores padrão do contêiner gke-gcsfuse-sidecar, é possível especificar a anotação gke-gcsfuse/[cpu-limit|memory-limit|ephemeral-storage-limit|cpu-request|memory-request|ephemeral-storage-request], conforme mostrado no exemplo a seguir:

Para substituir os valores padrão do contêiner gke-gcsfuse-metadata-prefetch (a partir da versão 1.32.3-gke.1717000 do GKE), especifique a anotação gke-gcsfuse/[metadata-prefetch-cpu-limit|metadata-prefetch-memory-limit|metadata-prefetch-ephemeral-storage-limit|metadata-prefetch-cpu-request|metadata-prefetch-memory-request|metadata-prefetch-ephemeral-storage-request], conforme mostrado no exemplo a seguir:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"

    # gke-gcsfuse-sidecar overrides
    gke-gcsfuse/cpu-limit: "10"
    gke-gcsfuse/memory-limit: 10Gi
    gke-gcsfuse/ephemeral-storage-limit: 1Ti
    gke-gcsfuse/cpu-request: 500m
    gke-gcsfuse/memory-request: 1Gi
    gke-gcsfuse/ephemeral-storage-request: 50Gi

    # gke-gcsfuse-metadata-prefetch overrides
    gke-gcsfuse/metadata-prefetch-cpu-limit: "10"
    gke-gcsfuse/metadata-prefetch-memory-limit: 10Gi
    gke-gcsfuse/metadata-prefetch-ephemeral-storage-limit: 1Ti
    gke-gcsfuse/metadata-prefetch-cpu-request: 500m
    gke-gcsfuse/metadata-prefetch-memory-request: 1Gi
    gke-gcsfuse/metadata-prefetch-ephemeral-storage-request: 50Gi

É possível usar o valor "0" para cancelar a definição de limites ou solicitações de recursos, mas observe que o contêiner gke-gcsfuse-sidecar já tem todos os limites (cpu-limit, memory-limit e ephemeral-storage-limit) não definidos, e o contêiner gke-gcsfuse-metadata-prefetch já tem ephemeral-storage-limit não definido. Portanto, definir esses limites como "0" em um cluster com a versão 1.32.3-gke.1717000 ou posterior do GKE não seria uma operação.

Por exemplo, definir gke-gcsfuse/metadata-prefetch-memory-limit: "0" indica que você quer que o limite de memória do contêiner gke-gcsfuse-metadata-prefetch não seja definido. Isso é útil quando não é possível decidir a quantidade de recursos que o recurso de pré-busca de metadados precisa para as cargas de trabalho e você quer permitir que a pré-busca de metadados consuma todos os recursos disponíveis em um nó.

(Opcional) Analisar o desempenho usando o Cloud Profiler

Use o Cloud Profiler para ter visibilidade contínua e granular do consumo de recursos dos seus aplicativos com uso intensivo de armazenamento. Os dados granulares podem ajudar você a monitorar proativamente o uso de CPU e memória no driver CSI do Cloud Storage FUSE e no contêiner secundário dele. Os insights que você recebe dos dados do Cloud Profiler ajudam a identificar caminhos de código ineficientes, otimizar a alocação de recursos e resolver problemas complexos, como vazamentos de memória ou eventos inesperados de memória insuficiente (OOM, na sigla em inglês), antes que eles afetem a estabilidade do serviço.

O uso do Cloud Profiler é opcional e foi projetado para administradores que precisam de diagnósticos detalhados de desempenho. O Cloud Profiler é ativado por padrão para o driver de nó. Para contêineres secundários, é um recurso opcional que pode ser ativado manualmente.

Antes de ativar o Cloud Profiler

Para usar o Cloud Profiler com o driver CSI do Cloud Storage FUSE, verifique se você está usando a versão 1.36.0-gke.2403000 ou mais recente do GKE. Antes de gerar perfis, ative a API Cloud Profiler e configure as permissões de IAM adequadas para os componentes que você quer criar perfis.

Ativar a API

Ative a API Cloud Profiler

Conceder permissões ao driver do nó

Para enviar dados de criação de perfil ao Cloud Profiler, o driver de nó precisa de permissões do IAM. Como o driver do nó é executado na rede host por padrão, ele se autentica usando a conta de serviço do IAM associada ao nó do GKE, em vez de usar a Federação de Identidade da Carga de Trabalho para GKE.

Conceda o papel roles/cloudprofiler.agent à conta de serviço do nó:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --role=roles/cloudprofiler.agent \
    --member=serviceAccount:NODE_SERVICE_ACCOUNT

Substitua:

  • PROJECT_ID: o ID do projeto Google Cloud .
  • NODE_SERVICE_ACCOUNT: a conta de serviço do IAM usada pelos nós do GKE. Normalmente, essa é a conta de serviço padrão do Compute Engine, por exemplo, PROJECT_NUMBER-compute@, a menos que os nós estejam configurados para usar uma conta de serviço diferente.

Conceder permissões ao contêiner secundário

Para enviar dados de criação de perfil ao Cloud Profiler, o contêiner secundário e o processo gcsfuse exigem permissões do IAM. Esses componentes são autenticados usando a federação de identidade da carga de trabalho para GKE, que usa a conta de serviço do Kubernetes (KSA, na sigla em inglês) associada ao pod da carga de trabalho.

Conceda o papel roles/cloudprofiler.agent à KSA que o pod usa:

gcloud projects add-iam-policy-binding projects/PROJECT_ID \
    --role=roles/cloudprofiler.agent \
    --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME \
    --condition=None

Substitua:

  • PROJECT_ID: o ID do projeto Google Cloud .
  • PROJECT_NUMBER: o número do projeto Google Cloud .
  • NAMESPACE: o nome do namespace do Kubernetes.
  • KSA_NAME: o nome da sua conta de serviço do Kubernetes.

Ativar o Cloud Profiler para cargas de trabalho de sidecar

Para gerar perfis para o montador de arquivo secundário e o processo gcsfuse, defina o atributo de volume enableCloudProfilerForSidecar como "true" na especificação da carga de trabalho. Ao ativar o Cloud Profiler para o contêiner secundário, ele também é ativado automaticamente para o processo gcsfuse subjacente.

Substitua BUCKET_NAME pelo nome do bucket do Cloud Storage:

volumes:
  - name: gcs-fuse-csi-ephemeral
    csi:
      driver: gcsfuse.csi.storage.gke.io
      volumeAttributes:
        bucketName: BUCKET_NAME
        enableCloudProfilerForSidecar: "true"

Ver dados de criação de perfil

Para ver os dados de criação de perfil, acesse a página do Cloud Profiler no console do Google Cloud . Use o filtro Nome do serviço da seguinte maneira para analisar o componente que você está investigando:

Componente Filtro de nome do serviço
Driver de nó gcs-fuse-csi-driver
Sidecar Mounter gke-gcsfuse-sidecar
GCSFuse gcsfuse

O Cloud Profiler identifica cada instância usando o formato POD_NAME_POD_UID. Isso garante que cada instância seja identificada de maneira exclusiva, mesmo que um pod seja reiniciado.

(Opcional) Desativar o perfil do GCSFuse

Por padrão, ativar a criação de perfil para o contêiner secundário também cria o perfil do processo gcsfuse subjacente. Talvez você queira desativar a criação de perfil do gcsfuse para reduzir a sobrecarga de recursos ou concentrar sua análise apenas no desempenho do contêiner secundário.

Para desativar a criação de perfil gcsfuse e manter a criação de perfil sidecar ativada, adicione enable-cloud-profiler=false ao atributo mountOptions na especificação de volume.

Substitua BUCKET_NAME pelo nome do bucket do Cloud Storage:

volumes:
  - name: gcs-fuse-csi-ephemeral
    csi:
      driver: gcsfuse.csi.storage.gke.io
      volumeAttributes:
        bucketName: BUCKET_NAME
        enableCloudProfilerForSidecar: "true"
        mountOptions: "enable-cloud-profiler=false"

Configurar a verbosidade da geração de registros

Por padrão, o contêiner gke-gcsfuse-sidecar gera registros nos níveis info e error. No entanto, para depuração ou análise mais detalhada, talvez seja necessário ajustar a verbosidade do registro. Esta seção descreve como aumentar ou diminuir o nível de geração de registros.

É possível usar opções de montagem para configurar o nível de detalhe do registro ou usar a capacidade do driver CSI de traduzir valores de atributo de volume nas configurações necessárias do gcsfuse.

No manifesto do pod de destino, inclua as seguintes configurações:

      volumeAttributes:
        bucketName: BUCKET_NAME
        mountOptions: "implicit-dirs"
        gcsfuseLoggingSeverity:  LOGGING_SEVERITY

Para usar as opções de montagem, inclua a seguinte configuração no manifesto do pod de destino:

  mountOptions: "logging:severity:LOGGING_SEVERITY"

Substitua:

  • BUCKET_NAME: seu nome do bucket do Cloud Storage
  • LOGGING_SEVERITY: um dos seguintes valores, com base nos seus requisitos:
    • trace
    • debug
    • info
    • warning
    • error

Depois que o pod é implantado, o driver CSI inicia o gcsfuse com o nível de registro recém-configurado.

Use o filtro a seguir para verificar se a gravidade do registro está sendo aplicada:

resource.labels.container_name="gke-gcsfuse-sidecar"
resource.type="k8s_container"
resource.labels.pod_name="POD_NAME"
"severity:"

Resolver problemas

Para mais informações sobre como resolver problemas do driver CSI do Cloud Storage FUSE, consulte o guia de solução de problemas na documentação do projeto do GitHub.

A seguir