Os buffers de capacidade melhoram a capacidade de resposta e a confiabilidade de cargas de trabalho críticas, gerenciando de forma proativa a capacidade de cluster reserva e os estados suspensos de capacidade pré-provisionada e pré-configurada usando uma CustomResourceDefinition (CRD) do CapacityBuffer do Kubernetes. O uso de buffers de capacidade permite definir explicitamente uma quantidade específica de capacidade de nó não utilizada no cluster. Essa capacidade reservada ajuda a reduzir o tempo de programação do pod.
Quando uma carga de trabalho de alta prioridade precisa escalonar verticalmente rapidamente, a nova carga de trabalho pode usar a capacidade vazia imediatamente sem aguardar o provisionamento do nó. Essa abordagem minimiza a latência e evita a contenção de recursos durante picos repentinos na demanda.
Esta página fornece métodos para configurar buffers de capacidade: um buffer de réplicas fixas, um buffer de limites de recursos e um buffer baseado em porcentagem.
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 o comando
gcloud components update. Talvez as versões anteriores da CLI gcloud não sejam compatíveis com a execução dos comandos neste documento.
- Crie ou tenha acesso a um cluster do GKE na versão 1.35.2-gke.1842000 para buffers ativos e na versão 1.36.0-gke.2253000 ou mais recente para buffers de espera.
- Ative o provisionamento automático de nós nos clusters padrão. Nos clusters do Autopilot, o provisionamento automático de nós já está ativado. O provisionamento automático de nós é opcional, mas recomendado para buffers ativos e obrigatório para buffers de espera.
Criar objetos do Kubernetes de pré-requisito
Para configurar um CapacityBuffer, você precisa de um namespace que contenha todos os objetos necessários (o CapacityBuffer em si e outros recursos, como um PodTemplate ou uma carga de trabalho). O PodTemplate e o CapacityBuffer precisam estar no mesmo namespace. É possível criar um namespace ou usar um namespace atual, incluindo o namespace default.
Dependendo do tipo de CapacityBuffer que você está configurando, também é necessário um dos seguintes:
- PodTemplate: define os requisitos de recursos para uma única unidade de capacidade de buffer. A configuração especificada no objeto CapacityBuffer faz referência ao modelo de pod.
Carga de trabalho: uma carga de trabalho atual que você referencia no objeto CapacityBuffer. Este guia usa um objeto de implantação como um exemplo de carga de trabalho, mas os buffers de capacidade oferecem suporte a qualquer um dos seguintes tipos de recursos:
- Implantação
- ReplicaSet
- StatefulSet
- ReplicationController
- Job
CustomResourceDefinitions (CRDs) que implementam o sub-recurso
scale.
Esta seção fornece exemplos desses objetos. Se você já tiver uma carga de trabalho que quer configurar com um buffer de capacidade, acesse Aplicar um buffer de capacidade.
Para criar um exemplo de carga de trabalho do Kubernetes, siga estas etapas:
Salve o seguinte manifesto como
namespace.yaml:apiVersion: v1 kind: Namespace metadata: name: capacity-buffer-example labels: name: capacity-buffer-exampleEsse manifesto cria um namespace chamado
capacity-buffer-example.Opcional: para usar buffers de capacidade com uma ComputeClass personalizada, salve o seguinte manifesto como
custom-compute-class.yaml:apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: ccc-example namespace: capacity-buffer-example spec: # Buffers are also created according to these priorities priorities: - machineFamily: n4 - machineFamily: n4d - machineFamily: c4 - machineFamily: c4d nodePoolAutoCreation: enabled: trueEsse manifesto cria uma
ComputeClasspersonalizada que define e controla as prioridades de computação para os nós provisionados pelo GKE. Para saber mais, consulte ComputeClasses personalizadas.Salve o seguinte manifesto como
buffer-pod-template.yaml:apiVersion: v1 kind: PodTemplate metadata: name: buffer-unit-template namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer template: spec: terminationGracePeriodSeconds: 0 containers: - name: buffer-container image: registry.k8s.io/pause:3.9 resources: requests: cpu: "1" memory: "1Gi" limits: cpu: "1" memory: "1Gi" # Optional: Using buffers with a custom ComputeClass / # controls the properties of the provisioned nodes. nodeSelector: cloud.google.com/compute-class: ccc-exampleEsse manifesto cria um
PodTemplateque define os requisitos de recursos para uma única unidade de capacidade de buffer (1CPU e1Gide memória). Essa configuração especifica o tamanho das unidades de capacidade que o GKE provisiona para o buffer. Por exemplo, com esse PodTemplate, o GKE não considera nós com menos de 1 CPU e 1Gi de recursos disponíveis como parte do buffer, se o cluster for escalonado.Salve o seguinte manifesto como
sample-workload-deployment.yaml:apiVersion: apps/v1 kind: Deployment metadata: name: critical-workload-ref namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer spec: replicas: 10 selector: matchLabels: app: critical-workload template: metadata: labels: app: critical-workload spec: containers: - name: busybox image: busybox command: ["sleep", "3600"] resources: requests: cpu: 100m # Optional: Using buffers with a custom ComputeClass / # controls the properties of the provisioned nodes. nodeSelector: cloud.google.com/compute-class: ccc-exampleEsse manifesto cria um exemplo de implantação com 10 réplicas, que é o objeto de referência para o exemplo de buffer baseado em porcentagem na próxima seção.
Aplique os manifestos ao cluster:
kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yamlVerifique se o GKE criou os objetos:
kubectl get podtemplate -n capacity-buffer-example kubectl get deployment critical-workload-ref -n capacity-buffer-exampleO resultado será assim:
NAME AGE buffer-unit-template 1m NAME READY UP-TO-DATE AVAILABLE AGE critical-workload-ref 10/10 10 10 1m
Aplicar um buffer de capacidade
Esta seção fornece exemplos dos diferentes tipos de buffers de capacidade que podem ser aplicados às cargas de trabalho.
Configurar um buffer de réplicas fixas
A configuração de um CapacityBuffer com réplicas fixas especifica o número exato de unidades de buffer que você quer com base em um PodTemplate.
Para criar um buffer com réplicas fixas, siga estas etapas:
Salve o seguinte manifesto como
cb-fixed-replicas.yaml:apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: fixed-replica-buffer namespace: NAMESPACE spec: podTemplateRef: name: POD_TEMPLATE replicas: 3 provisioningStrategy: "STRATEGY"Substitua:
NAMESPACE: o nome do namespace, por exemplo,capacity-buffer-example.POD_TEMPLATE: o PodTemplate que define os requisitos de recursos, por exemplo,buffer-unit-template.STRATEGY: a estratégia de provisionamento,"buffer.x-k8s.io/active-capacity"(padrão) ou"buffer.gke.io/standby-capacity".
Esse manifesto cria um recurso CapacityBuffer que faz referência a um PodTemplate para solicitar um número específico de unidades de buffer.
Aplique o manifesto:
kubectl apply -f cb-fixed-replicas.yamlConfirme se o GKE aplicou o buffer de capacidade:
kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACEO campo
replicasno status deve mostrar3, que reflete o número de réplicas definidas no manifesto. O campoSTATUSprecisa mostrarReadyForProvisioning.
Configurar um buffer de limites de recursos
É possível usar o campo limits para definir uma quantidade máxima de recursos que o buffer deve consumir, calculada com base no tamanho do PodTemplate.
Para criar um buffer de limites de recursos, siga estas etapas:
Salve o seguinte manifesto como
cb-resource-limits.yaml:apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: resource-limit-buffer namespace: NAMESPACE spec: podTemplateRef: name: POD_TEMPLATE limits: cpu: "5" memory: "5Gi" provisioningStrategy: "STRATEGY"Substitua:
NAMESPACE: o nome do namespace, por exemplo,capacity-buffer-example.POD_TEMPLATE: o PodTemplate que define os requisitos de recursos, por exemplo,buffer-unit-template.STRATEGY: a estratégia de provisionamento,"buffer.x-k8s.io/active-capacity"(padrão) ou"buffer.gke.io/standby-capacity".
Esse manifesto cria um recurso CapacityBuffer com um limite total de 5 CPUs e 5 GiB de memória. Se você estiver usando o exemplo de PodTemplate da etapa anterior, defina cada unidade como
1CPU e1Gide memória, o que deve resultar em 5 unidades de buffer.Aplique o manifesto:
kubectl apply -f cb-resource-limits.yamlConfirme se o GKE aplicou o buffer de capacidade:
kubectl get capacitybuffer resource-limit-buffer -n NAMESPACEVerifique o status do CapacityBuffer. O campo
replicasprecisa mostrar um valor derivado dos limites definidos. Se você estiver usando o exemplo de PodTemplate da seção anterior, verá5unidades de buffer, porque esse é o número máximo de unidades que se encaixam nos limites definidos.
Configurar um buffer baseado em porcentagem
A configuração de um buffer baseado em porcentagem dimensiona dinamicamente o buffer com base em uma porcentagem de uma carga de trabalho escalonável atual. Os buffers de capacidade baseados em porcentagem
são compatíveis apenas com objetos escalonáveis do Kubernetes que implementam o
sub-recurso de escalonamento, como implantações, StatefulSets, ReplicaSets ou jobs. Não é possível definir um buffer baseado em porcentagem para modelos de pod porque eles não têm um campo replicas.
Geralmente, recomendamos começar com réplicas fixas ou estratégias de limite de recursos, em vez de buffers baseados em porcentagem. Os buffers baseados em porcentagem são menos responsivos a escalonamentos repentinos se a carga de trabalho for escalonada para números baixos ou zero, porque a margem de segurança é escalonada em proporção aos pods ativos. Eles são úteis principalmente para implantações grandes que nunca são escalonadas para contagens de réplicas muito baixas.
Para criar um buffer baseado em porcentagem, siga estas etapas:
Salve o seguinte manifesto como
cb-percentage-based.yaml:apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: percentage-buffer namespace: NAMESPACE spec: scalableRef: apiGroup: apps kind: Deployment name: SCALABLE_RESOURCE_NAME percentage: 20 provisioningStrategy: "STRATEGY"Substitua:
NAMESPACE: o nome do namespace.SCALABLE_RESOURCE_NAME: o nome do recurso escalonável, por exemplo,critical-workload-ref.STRATEGY: a estratégia de provisionamento,"buffer.x-k8s.io/active-capacity"(padrão) ou"buffer.gke.io/standby-capacity".
Esse manifesto cria um recurso CapacityBuffer que solicita um tamanho de buffer equivalente a 20% das réplicas do recurso referenciado. Se você estiver usando o exemplo de implantação da seção anterior, o valor da réplica será definido como
10.Aplique o manifesto:
kubectl apply -f cb-percentage-based.yamlConfirme se o GKE aplicou o buffer de capacidade:
kubectl get capacitybuffer percentage-buffer -n NAMESPACEVerifique o status do CapacityBuffer. O campo
replicasprecisa mostrar um valor do cálculo de porcentagem. Se você estiver usando o exemplo de implantação da seção anterior, verá2unidades de buffer, que é 20% das 10 réplicas definidas na implantação.Teste o escalonamento dinâmico escalonando manualmente a implantação para 20 réplicas:
kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20O controlador CapacityBuffer reage e escalona automaticamente o buffer para 4 réplicas.
Personalizar o comportamento do buffer de espera
É possível usar anotações para personalizar como os buffers de espera são iniciados e atualizados.
Adicione essas anotações ao campo metadata.annotations do recurso CapacityBuffer:
buffer.gke.io/standby-capacity-init-time: o período de tempo em que um nó permanece ativo após a criação antes de ser suspenso. O formato é uma string de duração (por exemplo,5mou1h). O padrão é5m.buffer.gke.io/standby-capacity-refresh-frequency: a frequência com que os nós suspensos são atualizados. O padrão é24h.
O exemplo a seguir mostra um manifesto com esses campos opcionais para personalizar o comportamento dos buffers de espera:
apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
name: customized-standby-buffer
namespace: my-namespace
annotations:
buffer.gke.io/standby-capacity-init-time: "15m"
buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
podTemplateRef:
name: buffer-unit-template
replicas: 3
provisioningStrategy: "buffer.gke.io/standby-capacity"
Pré-carregar imagens em buffers de espera
Para acelerar os tempos de inicialização da carga de trabalho quando um nó de espera é retomado, é possível pré-carregar imagens de contêiner usando um DaemonSet. O DaemonSet é executado durante o período de inicialização antes que o nó seja suspenso.
Para pré-carregar imagens usando o DaemonSet, siga estas etapas:
Salve o seguinte manifesto como
image-puller-daemonset.yaml:apiVersion: apps/v1 kind: DaemonSet metadata: name: image-prefetch-daemonset namespace: NAMESPACE spec: selector: matchLabels: name: image-prefetch template: metadata: labels: name: image-prefetch spec: tolerations: - key: "buffer.gke.io/standby-node-suspended" operator: "Exists" initContainers: - name: image-puller image: IMAGE_NAME command: ["sh", "-c", "true"] containers: - name: pause image: registry.k8s.io/pause:3.9Substitua:
NAMESPACE: o namespace do DaemonSet, por exemplo,capacity-buffer-example.IMAGE_NAME: o nome da imagem a ser pré-carregada, por exemplo,your-app-image:latest.
Aplique o manifesto do DaemonSet ao cluster:
kubectl apply -f image-puller-daemonset.yamlVerifique se o DaemonSet foi criado:
kubectl get daemonset image-prefetch-daemonset -n NAMESPACEVerifique se o buffer de capacidade foi criado e está pronto para provisionamento:
kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACEVerifique o status. O campo
STATUSprecisa mostrarReadyForProvisioning.
Monitorar o status e a performance do buffer de capacidade
É possível monitorar o status e a integridade dos buffers de capacidade usando comandos kubectl e métricas do Cloud Monitoring.
Verificar o status do recurso CapacityBuffer
Para verificar a integridade dos buffers de capacidade e confirmar se eles estão prontos para receber cargas de trabalho, siga estas etapas:
Confira o status de todos os buffers de capacidade no cluster:
kubectl get capacitybuffer -AInspecione o status detalhado, as condições e os registros de eventos de um buffer específico:
kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
Identificar nós de buffer de espera suspensos
As VMs de buffer de espera são pré-provisionadas, mas mantidas em um estado suspenso para ajudar a reduzir custos. É possível reconhecer esses nós suspensos porque eles têm uma condição personalizada. Para auditar instâncias de nós suspensos, execute o seguinte comando:
kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'
Um status de True indica que uma VM de espera está suspensa. Um status de False ou
<none> indica um nó ativo em execução.
Monitorar a performance com o Cloud Monitoring
Para ajudar a monitorar a performance dos buffers de capacidade, monitore os seguintes recursos no Cloud Monitoring:
- Latência de reação (
cluster_autoscaler/reaction_time_milliseconds) : rastreia a duração para que o escalonador automático de cluster tome uma decisão de escalonamento com base na demanda pendente do CapacityBuffer. - Registros do escalonador automático de cluster: procure entradas de registro como
"Capacity pod processor injecting ..."para observar eventos de substituição de pods de buffer ativos.
Remover buffers de capacidade
Se você não precisar mais de um buffer de capacidade para suas cargas de trabalho, exclua o objeto CapacityBuffer. Isso remove os pods de marcador de posição e permite que o escalonador automático de cluster reduza os nós.
kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
Substitua CAPACITY_BUFFER_NAME pelo nome do CapacityBuffer que você quer excluir.
Solução de problemas
A seção a seguir contém informações sobre como resolver problemas comuns com buffers de capacidade.
Buffer de capacidade não está pronto devido ao modelo de faturamento
Se você criar um CapacityBuffer para uma carga de trabalho que usa o modelo de faturamento baseado em pod (pagamento por pod), o buffer de capacidade não estará pronto para provisionamento.
Para identificar esse problema, verifique o status do CapacityBuffer:
kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE
Procure uma condição do tipo ReadyForProvisioning com um status de False.
Para resolver esse problema, verifique se o CapacityBuffer faz referência a uma carga de trabalho ou PodTemplate compatível com o faturamento baseado em nós.
Erros de permissão para recursos escalonáveis personalizados
Se você configurar um CapacityBuffer para trabalhar com objetos escalonáveis personalizados (usando o campo scalableRef), o escalonador automático de cluster poderá falhar ao escalonar o buffer se não tiver as permissões necessárias. Esse problema ocorre apenas em
versões do GKE anteriores a 1.36.0-gke.2459000.
Para resolver esse problema, conceda manualmente as permissões necessárias por
criar um ClusterRole e ClusterRoleBinding, como no
exemplo a seguir:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: custom-scale-getter
rules:
- apiGroups: ["api.example.com"]
resources: ["customreplicatedresources/scale"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ca-custom-scale-getter
subjects:
- kind: User
name: "system:cluster-autoscaler"
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: custom-scale-getter
Para mais informações sobre como configurar o RBAC, consulte a documentação do RBAC do Kubernetes.
A seguir
- Saiba mais sobre buffers de capacidade.
- Consulte a documentação da CRD CapacityBuffer.