Criar cargas de trabalho com estado

Nesta página, explicamos como criar e gerenciar cargas de trabalho com estado em um cluster do Kubernetes isolado do Google Distributed Cloud (GDC). Com as cargas de trabalho com estado, é possível escalonar a implantação de aplicativos com armazenamento permanente. O armazenamento permanente fornece ao aplicativo identidades consistentes e nomes de host estáveis, independente de onde as cargas de trabalho estão programadas.

Esta página é destinada a desenvolvedores do grupo de operadores de aplicativos, que são responsáveis por criar cargas de trabalho de aplicativos para a organização. Para mais informações, consulte Públicos-alvo para documentação isolada do GDC.

Antes de começar

Para executar comandos em um cluster do Kubernetes, verifique se você tem os seguintes recursos:

  1. Localize o nome do cluster do Kubernetes ou pergunte ao administrador da plataforma.

  2. Faça login e gere o arquivo kubeconfig para o cluster do Kubernetes se você não tiver um.

  3. Use o caminho kubeconfig do cluster do Kubernetes para substituir KUBERNETES_CLUSTER_KUBECONFIG nestas instruções.

Para receber as permissões necessárias para criar cargas de trabalho com estado, peça ao administrador do IAM da organização para conceder a você o papel de administrador do namespace (namespace-admin) no namespace do projeto.

Criar um recurso StatefulSet

Crie um objeto StatefulSet escrevendo um manifesto StatefulSet e executando kubectl apply para criar o recurso. Para oferecer uma forma estável para os clientes enviarem solicitações aos pods do recurso StatefulSet, também é necessário criar um objeto Service.

O comando kubectl apply usa arquivos de manifesto para criar, atualizar e excluir recursos no cluster do Kubernetes. Esse é um método declarativo de configuração de objetos. Esse método retém gravações feitas em objetos ativos sem mesclar as mudanças nos arquivos de configuração do objeto.

Para criar um recurso StatefulSet e Service, execute:

kubectl --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG -n NAMESPACE \
    apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: SERVICE_NAME
  labels:
    app: APP_NAME
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: APP_NAME
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: STATEFULSET_NAME
spec:
  selector:
    matchLabels:
      app: APP_LABEL_NAME
  serviceName: "SERVICE_NAME"
  replicas: NUMBER_OF_REPLICAS
  template:
    metadata:
      labels:
        app: APP_LABEL_NAME
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: CONTAINER_NAME
        image: CONTAINER_IMAGE
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: CONTAINER_STORAGE_VOLUME_PATH
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
EOF

Substitua:

  • KUBERNETES_CLUSTER_KUBECONFIG: o arquivo kubeconfig do cluster em que você está implantando cargas de trabalho de contêiner.

  • NAMESPACE: o namespace do projeto em que as cargas de trabalho de contêiner serão implantadas.

  • SERVICE_NAME: o nome do objeto Service. Verifique se o objeto StatefulSet também define o objeto Service no serviceName.

  • APP_NAME: o nome do aplicativo a ser executado na implantação.

  • APP_LABEL_NAME: o seletor de rótulo que determina quais pods pertencem ao objeto StatefulSet.

  • STATEFULSET_NAME: o nome do objeto StatefulSet.

  • NUMBER_OF_REPLICAS: o número de objetos Pod replicados que a implantação gerencia.

  • CONTAINER_NAME: o nome do contêiner.

  • CONTAINER_IMAGE: o nome da imagem do contêiner. Inclua o caminho do registro de contêiner e a versão da imagem, como REGISTRY_PATH/nginx:1.23.

  • CONTAINER_STORAGE_VOLUME_PATH: o caminho dentro do contêiner em que um volume de armazenamento é ativado.

Por exemplo, o objeto StatefulSet a seguir e o objeto Service correspondente criam cargas de trabalho de contêiner com estado:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: REGISTRY_PATH/nginx:1.23
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

Neste exemplo:

  • Um objeto Service chamado nginx é criado, indicado pelo campo metadata: name. O objeto Service aponta um app chamado nginx, indicado por labels.app: nginx e selector.app: nginx. O objeto Service expõe a porta 80 e a nomeia como web. Esse objeto Service controla o domínio de rede e encaminha o tráfego da Internet para o aplicativo em contêiner implantado pelo objeto StatefulSet.
  • Um StatefulSet chamado web é criado com três objetos Pod replicados, conforme definido pelo campo replicas: 3.
  • O modelo Pod, definido pela seção .spec.template, indica que os objetos Pod estão marcados como app: nginx.
  • A especificação Pod, definida pela seção .template.spec, indica que os pods do StatefulSet executam um contêiner, nginx, que executa a imagem nginx na versão 1.23.
  • A especificação Pod usa a porta da Web aberta pelo objeto Service.
  • A seção .template.spec.volumeMounts especifica um campo mountPath, que é chamado de www. O mountPath é o caminho no contêiner em que um volume de armazenamento é montado.
  • O StatefulSet provisiona três objetos PersistentVolumeClaim, chamados web-www-0, web-www-1 e web-www-2, com 1 GB de armazenamento provisionado cada um.

Depois de criado, o StatefulSet garante que o número desejado de objetos Pod esteja em execução e disponível a qualquer momento. O StatefulSet substitui automaticamente os objetos Pod que falham ou são expulsos dos respectivos nós e associa novos objetos Pod aos recursos de armazenamento, solicitações e limites de recursos e outras configurações definidas na especificação Pod do objeto StatefulSet.

Solicitar armazenamento permanente em um recurso StatefulSet

O armazenamento permanente pode ser provisionado dinamicamente para que os volumes subjacentes sejam criados sob demanda. Os aplicativos podem solicitar armazenamento permanente com um objeto PersistentVolumeClaim.

Normalmente, além de criar o objeto Pod, é necessário criar objetos PersistentVolumeClaim. No entanto, os objetos StatefulSet incluem uma matriz volumeClaimTemplates que gera os objetos PersistentVolumeClaim. Cada réplica de StatefulSet recebe o próprio objeto PersistentVolumeClaim.

Para mais informações, consulte Configurar o armazenamento de contêineres.