StatefulSet

Nesta página, você vê a descrição dos objetos StatefulSet do Kubernetes e do uso deles no Google Kubernetes Engine.

O que é um StatefulSet?

Os StatefulSets representam um conjunto de pods com identidades únicas permanentes e nomes de host estáveis que o GKE mantém, seja qual for o local em que estão programados. As informações de estado e outros dados resilientes de qualquer pod do StatefulSet são mantidos em um armazenamento de disco permanente associado ao StatefulSet.

StatefulSets usam um índice ordinal para a identidade e a ordenação dos pods. Por padrão, os pods do StatefulSet são implantados em ordem sequencial e encerrados em ordem ordinal inversa. Por exemplo, um StatefulSet chamado web tem os pods denominados web-0, web-1 e web-2. Quando a especificação do web é alterada, os pods são interrompidos e recriados de forma otimizada em uma ordem. Neste exemplo, web-2 é encerrado primeiro, depois web-1 e assim por diante. Se preferir, é possível especificar o campo podManagementPolicy: Parallel (em inglês) para iniciar o StatefulSet ou encerrar todos os pods dele em paralelo. Assim, você não precisa esperar que os pods tenham o estado Em execução e prontos ou sejam encerrados antes do lançamento ou do encerramento de outro pod.

Os StatefulSets usam um modelo de pod, que contém uma especificação para os pods (em inglês). Ela determina como será cada pod: quais aplicativos são executados dentro dos contêineres, quais volumes ele ativa, os rótulos e seletores dele e muito mais.

Padrões de uso

Os StatefulSets são projetados para implantar aplicativos com estado e em cluster que salvam dados em um armazenamento permanente, como os discos permanentes do Google Compute Engine. Os StatefulSets são adequados para implantar o Kafka, MySQL, Redis, ZooKeeper e outros aplicativos que precisam de identidades únicas e permanentes e nomes de host estáveis. Nos aplicativos sem estado, use os Deployments.

Como criar StatefulSets

É possível criar um StatefulSet usando kubectl apply (em inglês).

Depois de criado, o StatefulSet garante que o número pretendido de pods esteja disponível e em execução sempre. O StatefulSet substitui automaticamente os pods que falham ou são expulsos dos respectivos nós. Além disso, ele associa automaticamente novos pods a recursos de armazenamento, solicitações e limites de recursos e outras configurações definidas na especificação do pod.

Veja a seguir um exemplo de arquivo de manifesto de Service e StatefulSet:

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 # Label selector that determines which Pods belong to the StatefulSet
                     # Must match spec: template: metadata: labels
      serviceName: "nginx"
      replicas: 3
      template:
        metadata:
          labels:
            app: nginx # Pod template's label selector
        spec:
          terminationGracePeriodSeconds: 10
          containers:
          - name: nginx
            image: gcr.io/google_containers/nginx-slim:0.8
            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 de Service denominado nginx é criado, de acordo com o indicado pelo campo metadata: name. O Service aponta um app denominado nginx, indicado por labels: app: nginx e selector: app: nginx. Ele expõe a porta 80 e a nomeia como web. Esse Service controla o domínio de rede e encaminha o tráfego da Internet ao aplicativo em contêiner implantado pelo StatefulSet;
  • um StatefulSet denominado web é criado com três pods replicados (replicas: 3);
  • o modelo (spec: template) indica que os pods estão rotulados como app: nginx;
  • a especificação (template: spec) indica que os pods do StatefulSet executam um contêiner nginx, que executa a imagem nginx-slim na versão 0.8. A imagem do contêiner é hospedada pelo Container Registry.
  • A especificação do pod usa a porta web aberta pelo Service.
  • template: spec: volumeMounts especifica um mountPath, que é denominado www. O mountPath é o caminho dentro do contêiner em que um volume de armazenamento é ativado;
  • O StatefulSet provisiona um PersistentVolumeClaim www com 1 GB de armazenamento provisionado.

Em suma, a especificação do pod contém as seguintes instruções:

  • Rotule cada pod como app: nginx.
  • Em cada pod, execute um contêiner chamado nginx.
  • Execute a imagem nginx-slim na versão 0.8.
  • Faça com que os pods usem a porta 80.
  • Salve os dados no caminho de ativação.

Para mais informações sobre configurações de StatefulSet, consulte a referência da API do StatefulSet (em inglês).

Como atualizar StatefulSets

Para atualizar um StatefulSet, faça alterações na respectiva especificação de pod, que inclui imagens e volumes de contêiner. Também é possível atualizar as solicitações de recurso e limites, rótulos e anotações do objeto. Para atualizar um StatefulSet, use a kubectl, a API do Kubernetes ou o menu Cargas de trabalho do GKE no Console do Google Cloud.

Para decidir como lidar com as atualizações, os StatefulSets usam uma estratégia de atualização definida em spec: updateStrategy. Há duas estratégias, OnDelete e RollingUpdate:

  • OnDelete não exclui e recria automaticamente os pods quando a configuração do objeto é alterada. Na verdade, você precisa excluir manualmente os pods antigos para que o controlador crie os atualizados.
  • RollingUpdate exclui e recria automaticamente os pods quando a configuração do objeto é alterada. Os novos pods precisam estar no estado Em execução e prontos antes que os antigos sejam excluídos. Com essa estratégia, alterar a especificação do pod aciona automaticamente um lançamento. Essa é a estratégia de atualização padrão dos StatefulSets.

StatefulSets atualizam pods em ordem ordinal inversa. Execute o comando a seguir para monitorar os lançamentos de atualização:

kubectl rollout status statefulset [STATEFULSET_NAME]

Como particionar atualizações graduais

É possível particionar atualizações graduais. O particionamento é útil se você quer organizar uma atualização, lançar um canário ou executar um lançamento gradual.

Com o particionamento de uma atualização, todos os pods com um ordinal maior ou igual ao valor da partição são atualizados quando você modifica a especificação de pod do StatefulSet. Os pods com um ordinal menor que o valor da partição não são atualizados e, mesmo se forem excluídos, são recriados usando a versão anterior da especificação. Se o valor da partição for maior que o número de réplicas, as atualizações não serão propagadas para os pods.

A seguir