Usar discos de inicialização secundários para pré-carregar dados ou imagens de contêiner


Neste documento, mostramos como melhorar a latência de inicialização da carga de trabalho usando discos de inicialização secundários no Google Kubernetes Engine (GKE) para pré-carregar dados ou imagens de contêiner em novos nós. Isso permite que as cargas de trabalho realizem uma inicialização a frio rápida e melhorem a utilização geral dos recursos provisionados.

Antes de ler este documento, certifique-se de estar familiarizado com o Google Cloud, Kubernetes, contêineres, YAML, tempo de execução do containerd e a CLI do Google Cloud.

Visão geral

A partir da versão 1.28.3-gke.1067000 do GKE nos clusters padrão e na versão 1.30.1-gke.1329000 do GKE, em clusters do Autopilot do GKE, será possível configurar o pool de nós com uma inicialização secundária. Peça ao GKE para provisionar os nós e pré-carregá-los com dados, como um modelo de machine learning ou uma imagem de contêiner. Como usar imagens de contêiner ou dados pré-carregados em um disco secundário que tem os seguintes benefícios para as cargas de trabalho:

  • Latência reduzida ao extrair imagens de contêiner grandes ou fazer o download de dados
  • Escalonamento automático mais rápido
  • Recuperação mais rápida de interrupções, como eventos de manutenção e erros do sistema

As seções a seguir descrevem como configurar o disco de inicialização secundário nos clusters do GKE Autopilot e Standard.

Como funcionam os discos de inicialização secundários

Sua carga de trabalho pode começar mais rapidamente usando dados ou imagem de contêiner pré-carregadas em discos de inicialização secundários. Os discos de inicialização secundários têm as seguintes características:

  • Os discos de inicialização secundários são Discos permanentes que têm o suporte do armazenamento em blocos distribuído. Se a imagem de disco já estiver em uso na zona, o tempo de criação de todos os discos subsequentes da mesma imagem de disco será menor.
  • O tipo de disco de inicialização secundário é igual ao disco de inicialização de nós.
  • O tamanho do disco de inicialização secundário é decidido pelo tamanho da imagem do disco.

Adicionar discos de inicialização secundários aos pools de nós não aumenta o tempo de provisionamento do nó. O GKE provisiona discos de inicialização secundários de uma imagem de disco em paralelo com o processo de provisionamento de nós.

Para oferecer suporte a imagens de contêiner pré-carregadas, o GKE amplia o ambiente de execução do containerd com plug-ins que leem as imagens de contêiner dos discos de inicialização secundários. As imagens de contêiner são reutilizadas pelas camadas de base. Recomendamos que você pré-carregue as grandes camadas de base no disco de inicialização secundário, enquanto as pequenas camadas superiores podem ser extraídas do Container Registry.

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 gcloud components update.

Requisitos

Os requisitos a seguir se aplicam ao uso do disco de inicialização secundário:

  1. Seus clusters estão executando a versão do GKE 1.28.3-gke.1067000 no GKE Standard ou a versão 1.30.1-gke.1329000 no Autopilot do GKE.
  2. Ao modificar a imagem do disco, crie um novo pool de nós. Não é possível atualizar a imagem do disco em nós atuais.
  3. Configure o streaming de imagens para usar o recurso de disco de inicialização secundário.
  4. Usar o Container-Optimized OS com uma imagem de nó do containerd. Os nós do Autopilot usam essa imagem por padrão.
  5. Preparar a imagem de disco com dados prontos durante o tempo de build ou com imagens de contêiner pré-carregadas. Verifique se o cluster tem acesso à imagem do disco para carregar nos nós. Recomendamos automatizar a imagem do disco em um pipeline de CI/CD.

Preparar o disco de inicialização secundário

Para preparar o disco de inicialização secundário, selecione a guia Imagens para pré-carregar imagens de contêiner ou selecione a guia Dados para pré-carregar dados e, em seguida, siga as seguintes instruções:

Imagens

O GKE tem uma ferramenta chamada gke-disk-image-builder para criar uma máquina virtual (VM) e extrair as imagens de contêiner em um disco e criar uma imagemdesse disco.

Para criar uma imagem de disco com várias imagens de contêiner pré-carregadas, siga as seguintes etapas:

  1. Crie um bucket do Cloud Storage para armazenar os registros de execução de gke-disk-image-builder.
  2. Crie uma imagem de disco com gke-disk-image-builder.
go run ./cli \
    --project-name=PROJECT_ID \
    --image-name=DISK_IMAGE_NAME \
    --zone=LOCATION \
    --gcs-path=gs://LOG_BUCKET_NAME \
    --disk-size-gb=10 \
    --container-image=docker.io/library/python:latest \
    --container-image=docker.io/library/nginx:latest

Substitua:

  • PROJECT_ID: o nome do seu projeto do Google Cloud.
  • DISK_IMAGE_NAME: o nome da imagem do disco. Por exemplo, nginx-python-image.
  • LOCATION: o local do cluster.
  • LOG_BUCKET_NAME: o nome do bucket do Cloud Storage para armazenar os registros de execução. Por exemplo, gke-secondary-disk-image-logs/.

Quando você cria uma imagem de disco com gke-disk-image-builder o Google Cloud cria vários recursos para concluir o processo (por exemplo, uma instância de VM, um disco temporário e um disco permanente). Após a execução, o criador de imagens limpa todos os recursos, exceto a imagem do disco que você criou.

Dados

Crie uma imagem de disco personalizada como a fonte de dados ao realizar as seguintes etapas:

  1. Crie uma VM com um disco em branco.
  2. Use o SSH para se conectar à VM.
    1. Monte o disco em branco.
    2. Faça o download dos dados no disco em branco.
  3. Crie uma imagem personalizada a partir do disco.

Configurar o disco de inicialização secundário

É possível configurar o disco de inicialização secundário em um cluster do GKE Autopilot ou Standard. Recomendamos que você use um cluster do Autopilot para ter uma experiência totalmente gerenciada do Kubernetes. Para escolher o modo de operação do GKE mais adequado para suas cargas de trabalho, consulte Escolher um modo de operação do GKE.

Usar o Autopilot do GKE

Nesta seção, você vai criar uma lista de permissões de imagens de disco para permitir a imagem de disco em um cluster do GKE Autopilot. Em seguida, você vai modificar o seletor de nós do pod para usar um disco de inicialização secundário.

Permitir as imagens de disco no projeto

Nesta seção, você criará um GCPResourceAllowlist para permitir que o GKE crie nós com discos de inicialização secundários usando imagens de disco no seu projeto do Google Cloud.

  1. Salve o seguinte manifesto como allowlist-disk.yaml:

    apiVersion: "node.gke.io/v1"
    kind: GCPResourceAllowlist
    metadata:
      name: gke-secondary-boot-disk-allowlist
    spec:
      allowedResourcePatterns:
      - "projects/PROJECT_ID/global/images/.*"
    

    Substitua o PROJECT_ID pelo ID do projeto para hospedar a imagem do disco.

  2. Aplique o manifesto:

    kubectl apply -f allowlist-disk.yaml
    

    O GKE cria nós com discos de inicialização secundários de todas as imagens de disco do projeto.

Atualizar o seletor de nós do pod para usar um disco de inicialização secundário

Nesta seção, você vai modificar a especificação do pod para que o GKE crie os nós com o disco de inicialização secundário.

  1. Adicione um nodeSelector ao seu modelo de pod:

    nodeSelector:
        cloud.google.com.node-restriction.kubernetes.io/gke-secondary-boot-disk-DISK_IMAGE_NAME=CONTAINER_IMAGE_CACHE.PROJECT_ID
    

    Substitua:

    • DISK_IMAGE_NAME: o nome da imagem do disco.
    • PROJECT_ID: o ID do projeto para hospedar a imagem do disco.
  2. Use o comando kubectl apply para aplicar a especificação do Kubernetes com o modelo do pod.

  3. Confirme se o cache do disco de inicialização secundário está em uso:

    kubectl get events --all-namespaces
    

    O resultado será assim:

    75s         Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm   Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  4. Verifique a latência de extração da imagem:

    kubectl describe pod POD_NAME
    

    Substitua POD_NAME pelo nome do pod.

    A saída será assim:

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

A latência esperada de extração da imagem do contêiner em cache deve ser significativamente reduzida, independentemente do tamanho da imagem.

Usar o GKE Standard

Para criar um cluster do GKE Standard e um pool de nós, siga as instruções a seguir, escolhendo a guia Imagens ou Dados caso você queira pré-carregar imagens de contêiner ou pré-carregar dados no disco de inicialização secundário:

Imagens

É possível configurar um disco de inicialização secundário usando a CLI do Google Cloud ou o Terraform:

gcloud

  1. Crie um cluster do GKE Standard com o streaming de imagens ativado:

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-image-streaming
    

    Substitua:

    • CLUSTER_NAME: o nome do cluster.
    • LOCATION: o local do cluster.
    • VERSION: a versão do GKE a ser usada. A versão precisa ser 1.28.3-gke.1067000 ou posterior.
  2. Crie um pool de nós com um disco de inicialização secundário no mesmo projeto:

    gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location LOCATION \
    --enable-image-streaming \
    --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE
    

    Substitua:

    • NODE_POOL_NAME: o nome do pool de nós.
    • CLUSTER_NAME: o nome do cluster existente.
    • LOCATION: as zonas do Compute separadas por vírgula do cluster.
    • DISK_IMAGE_NAME: o nome da imagem do disco.

    Para criar um pool de nós com um disco de inicialização secundário usando a imagem do disco em um projeto diferente, siga as etapas em Usar um disco de inicialização secundário em um projeto diferente.

  3. Adicione um nodeSelector ao seu modelo de pod:

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  4. Confirme se o cache do disco de inicialização secundário está em uso:

    kubectl get events --all-namespaces
    

    O resultado será assim:

    75s       Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  5. Verifique a latência de extração de imagem executando o seguinte comando:

    kubectl describe pod POD_NAME
    

    Substitua POD_NAME pelo nome do pod.

    A saída será assim:

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

A latência de extração esperada da imagem do contêiner em cache não deve ser maior do que alguns segundos, independentemente do tamanho da imagem.

Terraform

  1. Para criar um cluster com o pool de nós padrão usando o Terraform, consulte o exemplo a seguir:

    resource "google_container_cluster" "default" {
      name               = "default"
      location           = "us-central1-a"
      initial_node_count = 1
      # Set `min_master_version` because secondary_boot_disks require GKE 1.28.3-gke.106700 or later.
      min_master_version = "1.28"
      # Setting `deletion_protection` to `true` would prevent
      # accidental deletion of this instance using Terraform.
      deletion_protection = false
    }
  2. Crie um pool de nós com um disco de inicialização secundário no mesmo projeto:

    resource "google_container_node_pool" "secondary-boot-disk-container" {
      name               = "secondary-boot-disk-container"
      location           = "us-central1-a"
      cluster            = google_container_cluster.default.name
      initial_node_count = 1
    
      node_config {
        machine_type = "e2-medium"
        image_type   = "COS_CONTAINERD"
        gcfs_config {
          enabled = true
        }
        secondary_boot_disks {
          disk_image = ""
          mode       = "CONTAINER_IMAGE_CACHE"
        }
      }
    }

    Para saber mais como usar o Terraform, consulte o Suporte do Terraform para GKE.

  3. Adicione um nodeSelector ao seu modelo de pod:

    nodeSelector:
        cloud.google.com/gke-nodepool: NODE_POOL_NAME
    
  4. Confirme se o cache do disco de inicialização secundário está em uso:

    kubectl get events --all-namespaces
    

    O resultado será assim:

    75s       Normal      SecondaryDiskCachin
    node/gke-pd-cache-demo-default-pool-75e78709-zjfm Image
    gcr.io/k8s-staging-jobsejt/pytorch-mnist:latest is backed by secondary disk cache
    
  5. Verifique a latência de extração de imagem executando o seguinte comando:

    kubectl describe pod POD_NAME
    

    Substitua POD_NAME pelo nome do pod.

    A saída será assim:

    …
      Normal  Pulled     15m   kubelet            Successfully pulled image "docker.io/library/nginx:latest" in 0.879149587s
    …
    

A latência de extração esperada da imagem do contêiner em cache não deve ser maior do que alguns segundos, independentemente do tamanho da imagem.

Para saber mais como usar o Terraform, consulte o Suporte do Terraform para GKE.

Dados

É possível configurar um disco de inicialização secundário e pré-carregar dados usando a CLI do Google Cloud ou o Terraform:

gcloud

  1. Crie um cluster do GKE Standard com o streaming de imagens ativado:

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=VERSION \
        --enable-image-streaming
    

    Substitua:

    • CLUSTER_NAME: o nome do cluster.
    • LOCATION: o local do cluster.
    • VERSION: a versão do GKE a ser usada. A versão do GKE precisa ser a 1.28.3-gke.1067000 ou posterior.
  2. Crie um pool de nós com um disco de inicialização secundário usando a sinalização --secondary-boot-disk:

    gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location LOCATION \
    --enable-image-streaming \
    --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME
    

    Substitua:

    • NODE_POOL_NAME: o nome do pool de nós.
    • CLUSTER_NAME: o nome do cluster existente.
    • LOCATION: as zonas do Compute separadas por vírgula do cluster.
    • DISK_IMAGE_NAME: o nome da imagem do disco.

    Para criar um pool de nós com um disco de inicialização secundário usando a imagem do disco em um projeto diferente, siga as etapas em Usar um disco de inicialização secundário em um projeto diferente.

    O GKE cria um pool de nós em que cada nó tem um disco secundário com dados pré-carregados. O GKE anexa e monta o disco de inicialização secundário no nó.

  3. Outra opção é montar a imagem do disco secundário nos contêineres do pod usando uma montagem de volume hostPath. Use o manifesto a seguir para definir os recursos do pod e use uma montagem de volume hostPath para pré-carregar o disco de dados nos contêineres:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-name
    spec:
      containers:
      ...
      volumeMounts:
      - mountPath: /usr/local/data_path_sbd
        name: data_path_sbd
    ...
    volumes:
      - name: data_path_sbd
        hostPath:
            path: /mnt/disks/gke-secondary-disks/gke-DISK_IMAGE_NAME-disk
    

    Substitua DISK_IMAGE_NAME pelo nome da imagem do disco.

Terraform

  1. Para criar um cluster com o pool de nós padrão usando o Terraform, consulte o exemplo a seguir:

    resource "google_container_cluster" "default" {
      name               = "default"
      location           = "us-central1-a"
      initial_node_count = 1
      # Set `min_master_version` because secondary_boot_disks require GKE 1.28.3-gke.106700 or later.
      min_master_version = "1.28"
      # Setting `deletion_protection` to `true` would prevent
      # accidental deletion of this instance using Terraform.
      deletion_protection = false
    }
  2. Crie um pool de nós com um disco de inicialização secundário no mesmo projeto:

    resource "google_container_node_pool" "secondary-boot-disk-data" {
      name               = "secondary-boot-disk-data"
      location           = "us-central1-a"
      cluster            = google_container_cluster.default.name
      initial_node_count = 1
    
      node_config {
        machine_type = "e2-medium"
        image_type   = "COS_CONTAINERD"
        gcfs_config {
          enabled = true
        }
        secondary_boot_disks {
          disk_image = ""
        }
      }
    }

    Para saber mais como usar o Terraform, consulte o Suporte do Terraform para GKE.

  3. Outra opção é montar a imagem do disco secundário nos contêineres do pod usando uma montagem de volume hostPath. Use o manifesto a seguir para definir os recursos do pod e use uma montagem de volume hostPath para pré-carregar o disco de dados nos contêineres:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-name
    spec:
      containers:
      ...
      volumeMounts:
      - mountPath: /usr/local/data_path_sbd
        name: data_path_sbd
    ...
    volumes:
      - name: data_path_sbd
        hostPath:
            path: /mnt/disks/gke-secondary-disks/gke-DISK_IMAGE_NAME-disk
    

    Substitua DISK_IMAGE_NAME pelo nome da imagem do disco.

Escalonamento automático de clusters com discos secundários de inicialização

É possível criar um pool de nós e configurar o escalonamento automático de clusters em um disco de inicialização secundário usando a CLI do Google Cloud.

  gcloud container node-pools create NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --location LOCATION \
      --enable-image-streaming \
      --secondary-boot-disk=disk-image=global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE \
      --enable-autoscaling \
      --num-nodes NUM_NODES \
      --min-nodes MIN_NODES \
      --max-nodes MAX_NODES

Substitua:

  • NODE_POOL_NAME: o nome do pool de nós.
  • CLUSTER_NAME: o nome do cluster existente.
  • LOCATION: as zonas do Compute separadas por vírgula do cluster.
  • DISK_IMAGE_NAME: o nome da imagem do disco.
  • MIN_NODES: o número mínimo de nós a ser escalonado automaticamente para o pool de nós especificado por zona. Para especificar o número mínimo de nós para todo o pool de nós no GKE versões 1.24 e posteriores, use --total-min-nodes. As sinalizações --total-min-nodes e --total-max-nodes são mutuamente exclusivas com as sinalizações --min-nodes e --max-nodes.
  • MAX_NODES: o número máximo de nós a ser escalonado automaticamente para o pool de nós especificado por zona. Para especificar o número máximo de nós para todo o pool de nós no GKE versões 1.24 e posteriores, use --total-max-nodes. As sinalizações --total-min-nodes e --total-max-nodes são mutuamente exclusivas com as sinalizações --min-nodes e --max-nodes.

Provisionamento automático de nós com discos de inicialização secundários

No GKE 1.30.1-gke.1329000 e versões posteriores, configure o provisionamento automático de nós para criar e excluir automaticamente pools de nós para atender às demandas de recursos das suas cargas de trabalho.

  1. Criar um recurso personalizado da lista de permissões de imagens de disco para o disco de inicialização secundário para provisionamento automático de nós do GKE semelhante ao mostrado a seguir:

    apiVersion: "node.gke.io/v1"
    kind: GCPResourceAllowlist
    metadata:
      name: gke-secondary-boot-disk-allowlist
    spec:
      allowedResourcePatterns:
      - "projects/<PROJECT_ID>/global/images/.*"
    

    Substitua o PROJECT_ID pelo ID do projeto para hospedar a imagem do disco.

  2. Implante o recurso personalizado da lista de permissões no cluster e execute o seguinte comando:

    kubectl apply -f ALLOWLIST_FILE
    

    Substitua ALLOWLIST_FILE pelo nome do arquivo do manifesto.

  3. Atualizar o seletor de nós do pod para usar um disco de inicialização secundário

    nodeSelector:
        cloud.google.com.node-restriction.kubernetes.io/gke-secondary-boot-disk-DISK_IMAGE_NAME=CONTAINER_IMAGE_CACHE.PROJECT_ID
    

    Substitua:

    • DISK_IMAGE_NAME: o nome da imagem do disco.
    • PROJECT_ID: o ID do projeto para hospedar a imagem do disco.

Usar um disco de inicialização secundário em um projeto diferente

Ao criar um pool de nós com um disco de inicialização secundário, é possível dizer ao GKE para usar a imagem do disco em um um projeto diferente usando a sinalização --secondary-boot-disk.

  1. Criar um pool de nós com um disco de inicialização secundário a partir da imagem do disco em um projeto diferente usando a flag --secondary-boot-disk. Exemplo:

    gcloud beta container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location LOCATION \
        --enable-image-streaming \
        --secondary-boot-disk=disk-image=projects/IMAGE_PROJECT_ID/global/images/DISK_IMAGE_NAME,mode=CONTAINER_IMAGE_CACHE
    

    Substitua:

    • DISK_IMAGE_NAME: o nome da imagem do disco.
    • IMAGE_PROJECT_ID: o nome do projeto que a imagem do disco pertence.

    O GKE cria um pool de nós em que cada nó tem um disco secundário com dados pré-carregados. Isso anexa e monta o disco de inicialização secundário no nó.

  2. Conceda acesso a imagens de disco pertencentes a um projeto diferente adicionando "Usuário de imagens do Compute" para as contas de serviço do cluster:

    • Conta de serviço padrão do Compute: CLUSTER_PROJECT_NUMBER@cloudservices.gserviceaccount.com
    • Conta de serviço do GKE: service-CLUSTER_PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
    gcloud projects add-iam-policy-binding IMAGE_PROJECT_ID \
        --member serviceAccount:CLUSTER_PROJECT_NUMBER@cloudservices.gserviceaccount.com \
        --role roles/compute.imageUser
    
    gcloud projects add-iam-policy-binding IMAGE_PROJECT_ID \
        --member serviceAccount:service-CLUSTER_PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com \
        --role roles/compute.imageUser
    

A seguir