Provisionar e usar armazenamento em blocos brutos com suporte de SSD local


Nesta página, explicamos como provisionar o armazenamento SSD local nos clusters do Google Kubernetes Engine (GKE) e como configurar cargas de trabalho para consumir dados do armazenamento em blocos brutos com suporte de SSD local anexado aos nós no cluster.

O uso dessa opção de SSD local oferece mais controle sobre o armazenamento subjacente e permite criar seu próprio cache no nível do nó para que os pods ofereçam melhor desempenho para seus aplicativos. Também é possível personalizar essa opção instalando um sistema de arquivos em discos SSD locais e executando um DaemonSet para configurar o RAID e formatar os discos conforme necessário.

Para saber mais sobre o suporte ao SSD local para acesso a blocos brutos no GKE, consulte Sobre SSDs locais.

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.

Criar um cluster ou pool de nós com armazenamento em blocos brutos com suporte de SSD local

Use a gcloud CLI com a opção --local-nvme-ssd-block para criar um cluster com armazenamento em blocos brutos com suporte de SSD local.

O comando da gcloud CLI executado para criar o cluster ou o pool de nós depende de qual geração de séries de máquinas o tipo de máquina que você está usando pertence. Por exemplo, os tipos de máquina N1 e N2 pertencem a uma série de máquinas de primeira e segunda geração, respectivamente, enquanto os tipos de máquina C3 pertencem a uma série de máquinas de terceira geração.

Criar um cluster com SSD local

1ª ou 2ª geração

Se você usar um tipo de máquina de uma série de máquinas de primeira ou segunda geração, crie seu cluster especificando a opção --local-nvme-ssd-block count=NUMBER_OF_DISKS. A opção especifica o número de discos SSD locais a serem anexados a cada nó. O número máximo varia por tipo de máquina e região.

Para criar um cluster:

gcloud container clusters create CLUSTER_NAME \
    --local-nvme-ssd-block count=NUMBER_OF_DISKS \
    --machine-type=MACHINE_TYPE \
    --release-channel CHANNEL_NAME

Substitua:

  • CLUSTER_NAME: o nome do cluster.
  • NUMBER_OF_DISKS: o número dos discos SSD locais a serem provisionados em cada nó. O número máximo de discos varia de acordo com o tipo de máquina e região.
  • MACHINE_TYPE: o tipo de máquina de primeira ou segunda geração a ser usado. É necessário especificar esse campo porque não é possível usar SSDs locais com o tipo e2-medium padrão.
  • CHANNEL_NAME: um canal de lançamento que inclui versões do GKE posteriores à 1.25.3-gke.1800.

3ª geração

Se você usar um tipo de máquina de uma série de máquinas de terceira geração, use a opção --local-nvme-ssd-block, sem um campo de contagem, para criar um cluster. O GKE provisiona automaticamente a capacidade do SSD local para o cluster com base no formato da VM. O número máximo varia por tipo de máquina e região.

gcloud container clusters create CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --cluster-version CLUSTER_VERSION \
    --local-nvme-ssd-block

Substitua:

  • CLUSTER_NAME: o nome do cluster.
  • MACHINE_TYPE: o tipo de máquina a ser usado com uma série de terceira geração.
  • CLUSTER_VERSION: uma versão do cluster do GKE que permite SSD local em tipos de máquina com uma série de terceira geração.

Criar um pool de nós com SSD local

1ª ou 2ª geração

Para criar um pool de nós que use discos SSD locais para acesso a blocos brutos, execute o seguinte comando:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --local-nvme-ssd-block count=NUMBER_OF_DISKS

Substitua:

  • POOL_NAME: o nome do novo pool de nós.
  • CLUSTER_NAME: o nome do cluster.
  • MACHINE_TYPE: o tipo de máquina de primeira ou segunda geração a ser usado. A especificação desse campo é obrigatória, já que o SSD local não pode ser usado com o tipo e2-medium padrão.
  • NUMBER_OF_DISKS: o número dos discos SSD locais a serem provisionados em cada nó. O número máximo de discos varia de acordo com o tipo de máquina e região.

3ª geração

Se você usar um tipo de máquina de uma série de máquinas de terceira geração, use a opção --local-nvme-ssd-block, sem um campo de contagem, para criar um cluster:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --node-version NODE_VERSION \
    --local-nvme-ssd-block

Substitua:

  • POOL_NAME: o nome do novo pool de nós.
  • CLUSTER_NAME: o nome do cluster.
  • MACHINE_TYPE: o tipo de máquina a ser usado em um tipo de máquina de terceira geração.
  • NODE_VERSION: uma versão do pool de nós do GKE que oferece suporte ao SSD local em tipos de máquina de uma série de máquinas de terceira geração.

Os nós no pool de nós são criados com um rótulo cloud.google.com/gke-local-nvme-ssd=true. Você pode verificar os rótulos executando o seguinte comando:

kubectl describe node NODE_NAME

Para cada SSD local anexado ao pool de nós, o SO host cria um link simbólico para acessar o disco em uma pasta ordinal e um link simbólico com um identificador universal exclusivo (UUID, na sigla em inglês). Por exemplo, se você criar um pool de nós com três SSDs locais usando a opção --local-nvme-ssd-block, o SO host criará os links simbólicos a seguir para os discos:

  • /dev/disk/by-id/google-local-ssd-block0
  • /dev/disk/by-id/google-local-ssd-block1
  • /dev/disk/by-id/google-local-ssd-block2

O sistema operacional do host também cria estes links simbólicos com UUIDs para os discos:

  • /dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID1
  • /dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID2
  • /dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID3

Isso garante que os discos possam ser acessados usando um identificador exclusivo.

Acessar volumes SSD locais

O exemplo a seguir mostra como acessar o armazenamento em blocos brutos com suporte de SSD local.

PersistentVolumes locais

Os volumes SSD locais podem ser montados como pods usando PersistentVolumes.

Crie PersistentVolumes a partir de SSDs locais fazendo manualmente um PersistentVolume ou executando o provisionador estático do volume local.

Limitações dos PersistentVolumes locais

  • No momento, o escalonamento automático de clusters e o provisionamento dinâmico não são compatíveis com PersistentVolumes locais.

  • O upgrade de um cluster do GKE ou a reparação de nós exclui as instâncias do Compute Engine, que também exclui todos os dados nos discos SSDs locais.

  • Não ative upgrades automáticos ou reparos automáticos de nós em clusters ou pools de nós que usam SSD local para dados permanentes. Primeiro, faça backup dos dados do aplicativo e, só então, restaure os dados para um novo cluster ou pool de nós.

  • Os objetos do PersistentVolume local não são limpos automaticamente quando um nó é excluído, atualizado, reparado ou reduzido. Recomendamos que você verifique e exclua periodicamente objetos obsoletos do PersistentVolume local associados a nós excluídos.

Criar o PersistentVolume manualmente

Crie manualmente um PersistentVolume para cada SSD local em cada nó no cluster.

Use o campo nodeAffinity em um objeto PersistentVolume para se referir a um SSD local em um nó específico. O exemplo a seguir mostra a especificação do PersistentVolume para SSD local em nós que executam o Linux:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: "example-local-pv"
spec:
  capacity:
    storage: 375Gi
  accessModes:
  - "ReadWriteOnce"
  persistentVolumeReclaimPolicy: "Retain"
  storageClassName: "local-storage"
  local:
    path: "/mnt/disks/ssd0"
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: "kubernetes.io/hostname"
          operator: "In"
          values:
          - "gke-test-cluster-default-pool-926ddf80-f166"

Neste exemplo, os discos SSD locais são configurados manualmente para RAID e formatados e montados em /mnt/disks/ssd0 no nó gke-test-cluster-default-pool-926ddf80-f166. O campo nodeAffinity é usado para ajudar a atribuir cargas de trabalho a nós com SSDs locais configurados manualmente para RAID. Se você tiver apenas um nó no cluster ou se tiver configurado a RAID para todos os nós, o campo nodeAffinity não será necessário.

A especificação PersistenVolumeClaim correspondente tem esta aparência:

  kind: PersistentVolumeClaim
  apiVersion: v1
  metadata:
    name: ssd-local-claim
  spec:
    accessModes:
    - ReadWriteOnce
    storageClassName: local-storage
    resources:
      requests:
        storage: 37Gi

Se você excluir o PersistentVolume, vai precisar apagar manualmente os dados do disco.

Executar o provisionador estático do volume local

Crie PersistentVolumes para SSDs locais automaticamente usando o provisionador estático do volume local. O provisionador é um DaemonSet que gerencia os discos SSDs locais em cada nó, cria e exclui os PersistentVolumes deles e limpa os dados nos discos SSDs locais quando o PersistentVolume é liberado.

Para executar o provisionador estático do volume local:

  1. Use um DaemonSet para configurar a RAID e formatar os discos:

    1. Faça o download da especificação gke-daemonset-raid-disks.yaml.
    2. Implante o DaemonSet de discos RAID. O DaemonSet define uma matriz RAID 0 em todos os discos SSD locais e formata o dispositivo em um sistema de arquivos ext4.

      kubectl create -f gke-daemonset-raid-disks.yaml
      
  2. Faça o download da especificação do gke-nvme-ssd-block-raid.yaml e modifique os campos de namespace da especificação, conforme necessário.

    A especificação inclui estes recursos:

    • a ServiceAccount do provisionador
    • ClusterRole e ClusterRoleBindings para permissões para:
      • criar e excluir objetos PersistentVolume
      • receber objetos Get Node
    • ConfigMap com configurações do provisionador para o GKE
    • DaemonSet para executar o provisionador
  3. Implante o provisionador:

    kubectl create -f gke-nvme-ssd-block-raid.yaml
    

    Depois que o provisionador estiver em execução, ele criará um objeto PersistentVolume para o dispositivo SSD local RAID no cluster.

  4. Salve o seguinte manifesto PersistentVolumeClaim: provisioner-pvc-example.yaml:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: PVC_NAME
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 50Gi
      storageClassName: nvme-ssd-block
    

    Substitua PVC_NAME pelo nome do PersistentVolumeClaim.

  5. Crie o PersistentVolumeClaim:

    kubectl create -f provisioner-pvc-example.yaml
    
  6. Salve o seguinte manifesto de pod como provisioner-pod-example.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: POD_NAME
    spec:
      containers:
      - name: "shell"
        image: "ubuntu:14.04"
        command: ["/bin/sh", "-c"]
        args: ["echo 'hello world' > /cache/test.txt && sleep 1 && cat /cache/test.txt && sleep 3600"]
        volumeMounts:
        - mountPath: /cache
          name: local-ssd-storage
      volumes:
      - name: local-ssd-storage
        persistentVolumeClaim:
          claimName: PVC_NAME
    

    Substitua POD_NAME pelo nome do pod.

  7. Crie o pod:

    kubectl create -f provisioner-pod-example.yaml
    

Ativar a vinculação de volume atrasada

Para melhorar a programação, recomendamos que você também crie um StorageClass com volumeBindingMode: WaitForFirstConsumer. Isso atrasa a vinculação do PersistentVolumeClaim até a programação do pod. Assim, um SSD local será escolhido em um nó apropriado que possa executar o pod. Esse comportamento de programação aprimorado significa que as solicitações de CPU e memória do pod, afinidade do nó, afinidade e antiafinidade do pod e várias solicitações de PersistentVolumeClaim são consideradas com os nós que têm SSDs locais disponíveis, ao selecionar um nó para um pod executável.

Neste exemplo, é usado o modo de vinculação de volume atrasada:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: "local-nvme"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"

Para criar um StorageClass com vinculação atrasada, salve o manifesto YAML em um arquivo local e aplique-o ao cluster usando o seguinte comando:

kubectl apply -f filename

Solução de problemas

Para instruções sobre solução de problemas, consulte Como resolver problemas de armazenamento no GKE.

A seguir