Neste tutorial, usamos o Kueue para mostrar como implementar um sistema de enfileiramento de jobs, configurar o recurso de carga de trabalho e o compartilhamento de cota entre diferentes namespaces no Google Kubernetes Engine (GKE) e maximizar a utilização do cluster.
Contexto
Como engenheiro de infraestrutura ou administrador de cluster, maximizar a utilização entre namespaces é muito importante. Um lote de jobs em um namespace pode não utilizar totalmente a cota completa atribuída ao namespace, enquanto outro namespace pode ter vários jobs pendentes. Para usar com eficiência os recursos do cluster entre jobs em namespaces diferentes e aumentar a flexibilidade do gerenciamento de cotas, configure coortes no Kueue. Uma coorte é um grupo de ClusterQueues que podem pedir emprestados cotas não utilizadas uns dos outros. Um ClusterQueue controla um conjunto de recursos, como aceleradores de hardware, memória e CPU.
Você pode encontrar uma definição mais detalhada de todos esses conceitos na documentação do Kueue
Objetivos
Este tutorial é para engenheiros de infraestrutura ou administradores de cluster que querem implementar um sistema de enfileiramento de jobs no Kubernetes usando o Kueue com compartilhamento de cota.Este tutorial imitará duas equipes em dois namespaces diferentes, em que cada uma tem recursos dedicados, mas pode usar as outras. Um terceiro conjunto de recursos pode ser usado como sobrecarga quando os jobs se acumulam.
Use o operador Prometheus para monitorar jobs e alocação de recursos em namespaces diferentes.
Este tutorial aborda as seguintes etapas necessárias:
- Criar um cluster do GKE
- Crie os ResourceFlavors.
- Para cada equipe, crie um ClusterQueue e um LocalQueue
- Criar Jobs e observar as cargas de trabalho admitidas
- Pedir emprestado a cota não utilizada com coortes
- Adicionar um spilover ClusterQueue que rege as VMs spot
Custos
Neste tutorial, usamos os seguintes componentes faturáveis do Google Cloud:Use a calculadora de preços para gerar uma estimativa de custo com base no uso previsto.
Ao concluir este tutorial, exclua os recursos criados para evitar o faturamento contínuo. Para mais informações, consulte Limpeza.
Antes de começar
Criar o projeto
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
No Google Cloud console, inicie uma instância do Cloud Shell:
Abrir o Cloud ShellFaça o download do código-fonte para este app de amostra:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Defina as variáveis de ambiente padrão:
gcloud config set project PROJECT_ID gcloud config set compute/region COMPUTE_REGION
Substitua os seguintes valores:
- PROJECT_ID: o ID do projeto do Google Cloud .
- COMPUTE_REGION: a região do Compute Engine.
Crie um Cluster do GKE chamado
kueue-cohort
:Você vai criar um cluster com seis nós (dois por zona) no pool padrão e sem escalonamento automático. Esses serão todos os recursos disponíveis para as equipes no início, então elas precisarão competir por elas.
Você verá como o Kueue gerencia as cargas de trabalho que as duas equipes enviarão às respectivas filas.
gcloud container clusters create kueue-cohort --region COMPUTE_REGION \ --release-channel rapid --machine-type e2-standard-4 --num-nodes 2
Após a criação do cluster, o resultado será semelhante a este:
kubeconfig entry generated for kueue-cohort. NAME: kueue-cohort LOCATION: us-central1 MASTER_VERSION: 1.26.2-gke.1000 MASTER_IP: 35.224.108.58 MACHINE_TYPE: e2-medium NODE_VERSION: 1.26.2-gke.1000 NUM_NODES: 6 STATUS: RUNNING
Em que a
STATUS
éRUNNING
para akueue-cluster
.Crie um pool de nós chamado
spot
.Este pool de nós usa a VM do Spot, e o escalonamento automático está ativado. Ele começa com 0 nós, mas depois você o disponibilizará para as equipes para uso como capacidade de sobrecarga.
gcloud container node-pools create spot --cluster=kueue-cohort --region COMPUTE_REGION \ --spot --enable-autoscaling --max-nodes 20 --num-nodes 0 \ --machine-type e2-standard-4
Instale a versão de lançamento do Kueue no cluster:
VERSION=VERSION kubectl apply -f \ https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
Substitua VERSION pela letra v após a versão mais recente do Kueue, por exemplo,
v0.4.0
. Para conferir mais informações sobre as versões do Kueue, consulte as Versões do Kueue.Aguarde até que o controlador do Kueue esteja pronto:
watch kubectl -n kueue-system get pods
A saída será semelhante a esta antes de continuar:
NAME READY STATUS RESTARTS AGE kueue-controller-manager-6cfcbb5dc5-rsf8k 2/2 Running 0 3m
Crie dois novos namespaces chamados
team-a
eteam-b
:kubectl create namespace team-a kubectl create namespace team-b
Os jobs serão gerados em cada namespace.
Definir padrões para a Google Cloud CLI
Criar um cluster do GKE
Criar o ResourceFlavors
Um ResourceFlavor representa variações de recursos nos nós do cluster, como VMs diferentes (por exemplo, spot versus sob demanda), arquiteturas (por exemplo, CPUs x86 x ARM), marcas e modelos (por exemplo, Nvidia A100 versus GPUs T4).
Os ResourceFlavors usam rótulos e taints de nós para fazer a correspondência com um conjunto de nós no cluster.
Nesse manifesto:
- O ResourceFlavor
on-demand
tem o rótulo definido comocloud.google.com/gke-provisioning: standard
. - O ResourceFlavor
spot
tem o rótulo definido comocloud.google.com/gke-provisioning: spot
.
Quando uma carga de trabalho é atribuída a um ResourceFlavor, o Kueue atribui os pods da carga aos nós que correspondem aos rótulos de nós definidos para o ResourceFlavor.
Implantar o ResourceFlavor:
kubectl apply -f flavors.yaml
Criar o ClusterQueue e a LocalQueue
Crie duas ClusterQueues cq-team-a
e cq-team-b
e as LocalQueues lq-team-a
e lq-team-b
correspondentes com os namespaces team-a
e team-b
, respectivamente.
ClusterQueues são objetos com escopo de cluster que controlam um pool de recursos, como aceleradores de hardware, memória e CPU. Os administradores em lote podem restringir a visibilidade desses objetos a usuários em lote.
LocalQueues são objetos com namespace que os usuários em lote podem listar. Eles apontam para CluterQueues, a partir dos quais os recursos são alocados para executar as cargas de trabalho da LocalQueue.
ClusterQueues permite que os recursos tenham diversas variações. Nesse caso, as duas
QueueQueues têm duas variações, on-demand
e spot
, cada uma fornecendo recursos cpu
.
A cota de spot
do ResourceFlavor está definida como 0
e não será usada no momento.
As duas ClusterQueues compartilham a mesma coorte chamada all-teams
, definida em .spec.cohort
.
Quando duas ou mais ClusterQueues compartilham a mesma coorte, é possível pedir emprestado uma cota não utilizada entre si.
Saiba mais sobre como as coortes funcionam e a semântica do empréstimo na documentação do Kueue
Implante as ClusterQueues e LocalQueues:
kubectl apply -f cq-team-a.yaml
kubectl apply -f cq-team-b.yaml
(Opcional) Monitorar cargas de trabalho usando o kube-prometheus
É possível usar o Prometheus para monitorar suas cargas de trabalho ativas e pendentes do Kueue.
Para monitorar as cargas de trabalho que estão sendo criadas e observar a carga em cada
ClusterQueue, implante o kube-prometheus no
cluster no namespace monitoring
:
Faça o download do código-fonte do operador do Prometheus:
cd git clone https://github.com/prometheus-operator/kube-prometheus.git
Crie os CustomResourceDefinitions(CRDs):
kubectl create -f kube-prometheus/manifests/setup
Crie os componentes de monitoramento:
kubectl create -f kube-prometheus/manifests
Permita que o
prometheus-operator
colete métricas dos componentes do Kueue:kubectl apply -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/prometheus.yaml
Mude para o diretório de trabalho:
cd kubernetes-engine-samples/batch/kueue-cohort
Configure o encaminhamento de portas para o serviço Prometheus em execução no cluster do GKE:
kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090
Abra a interface da Web do Prometheus em localhost:9090 no navegador.
No Cloud Shell:
Clique em Visualização da Web.
Clique em Alterar porta e defina o número da porta como
9090
.Clique em Alterar e visualizar.
A seguinte UI da Web do Prometheus aparece.
Na caixa de consulta Expressão, insira a consulta a seguir para criar o primeiro painel que monitora as cargas de trabalho ativas para
cq-team-a
ClusterQueue:kueue_pending_workloads{cluster_queue="cq-team-a", status="active"} or kueue_admitted_active_workloads{cluster_queue="cq-team-a"}
Clique em Adicionar painel.
Na caixa de consulta Expressão, insira a consulta a seguir para criar outro painel que monitora as cargas de trabalho ativas da ClusterQueue
cq-team-b
:kueue_pending_workloads{cluster_queue="cq-team-b", status="active"} or kueue_admitted_active_workloads{cluster_queue="cq-team-b"}
Clique em Adicionar painel.
Na caixa de consulta Expressão, insira a consulta a seguir para criar um painel que monitora o número de nós no cluster:
count(kube_node_info)
(Opcional) Monitorar cargas de trabalho usando o Google Cloud Managed Service para Prometheus
É possível usar o Google Cloud Managed Service para Prometheus para monitorar as cargas de trabalho ativas e pendentes do Kueue. Confira a lista completa de métricas na documentação do Kueue.
Configure a identidade e o RBAC para acesso às métricas:
A configuração a seguir cria quatro recursos do Kubernetes que fornecem acesso a métricas para os coletores do Google Cloud Managed Service para Prometheus.
Uma ServiceAccount chamada
kueue-metrics-reader
no namespacekueue-system
será usada para autenticar ao acessar as métricas do Kueue.Um Secret associado à conta de serviço
kueue-metrics-reader
, armazena um token de autenticação usado pelo coletor para se autenticar com o endpoint de métricas exposto pela implantação do Kueue.Uma função chamada
kueue-secret-reader
no namespacekueue-system
, que permite ler o secret que contém o token da conta de serviço.Um ClusterRoleBinding que concede à conta de serviço
kueue-metrics-reader
o ClusterRolekueue-metrics-reader
.
apiVersion: v1 kind: ServiceAccount metadata: name: kueue-metrics-reader namespace: kueue-system --- apiVersion: v1 kind: Secret metadata: name: kueue-metrics-reader-token namespace: kueue-system annotations: kubernetes.io/service-account.name: kueue-metrics-reader type: kubernetes.io/service-account-token --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: kueue-secret-reader namespace: kueue-system rules: - resources: - secrets apiGroups: [""] verbs: ["get", "list", "watch"] resourceNames: ["kueue-metrics-reader-token"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kueue-metrics-reader subjects: - kind: ServiceAccount name: kueue-metrics-reader namespace: kueue-system roleRef: kind: ClusterRole name: kueue-metrics-reader apiGroup: rbac.authorization.k8s.io
Configure o RoleBinding para o Google Cloud Managed Service para Prometheus:
Dependendo se você estiver usando um cluster do Autopilot ou Standard, será necessário criar o RoleBinding no namespace
gke-gmp-system
ougmp-system
. Esse recurso permite que a conta de serviço do coletor acesse o secretokueue-metrics-reader-token
para autenticar e extrair as métricas do Kueue.Piloto automático
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gmp-system:collector:kueue-secret-reader namespace: kueue-system roleRef: name: kueue-secret-reader kind: Role apiGroup: rbac.authorization.k8s.io subjects: - name: collector namespace: gke-gmp-system kind: ServiceAccount
Padrão
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gmp-system:collector:kueue-secret-reader namespace: kueue-system roleRef: name: kueue-secret-reader kind: Role apiGroup: rbac.authorization.k8s.io subjects: - name: collector namespace: gmp-system kind: ServiceAccount
Configure o recurso PodMonitoring:
O recurso a seguir configura o monitoramento da implantação do Kueue e especifica que as métricas são expostas no caminho /metrics por HTTPS. Ele usa o secret
kueue-metrics-reader-token
para autenticação ao extrair as métricas.apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: kueue namespace: kueue-system spec: selector: matchLabels: control-plane: controller-manager endpoints: - port: https interval: 30s path: /metrics scheme: https tls: insecureSkipVerify: true authorization: type: Bearer credentials: secret: name: kueue-metrics-reader-token key: token
Consultar métricas exportadas
Exemplos de consultas PromQL para monitorar sistemas baseados no Kueue
Com essas consultas do PromQL, é possível monitorar as principais métricas do Kueue, como capacidade de processamento de jobs, utilização de recursos por fila e tempos de espera da carga de trabalho, para entender o desempenho do sistema e identificar possíveis gargalos.
Capacidade de jobs
Isso calcula a taxa por segundo de cargas de trabalho aceitas em cinco minutos para cada cluster_queue. Essa métrica pode ajudar a detalhar por fila, identificar gargalos e somar o throughput geral do sistema.
Consulta:
sum(rate(kueue_admitted_workloads_total[5m])) by (cluster_queue)
Uso de recursos
Isso pressupõe que metrics.enableClusterQueueResources
esteja ativado. Ele calcula a proporção do uso atual da CPU em relação à cota nominal de CPU para cada fila. Um valor próximo de 1 indica alta utilização. Você pode adaptar isso para memória ou outros recursos mudando o rótulo do recurso.
Para instalar uma versão lançada do Kueue com configuração personalizada no cluster, siga a documentação do Kueue.
Consulta:
sum(kueue_cluster_queue_resource_usage{resource="cpu"}) by (cluster_queue) / sum(kueue_cluster_queue_nominal_quota{resource="cpu"}) by (cluster_queue)
Tempo de espera na fila
Isso fornece o tempo de espera do 90º percentil para cargas de trabalho em uma fila específica. É possível modificar o valor do quantil (por exemplo, 0,5 para mediana, 0,99 para o percentil 99) para entender a distribuição do tempo de espera.
Consulta:
histogram_quantile(0.9, kueue_admission_wait_time_seconds_bucket{cluster_queue="QUEUE_NAME"})
Criar Jobs e observar as cargas de trabalho admitidas
Nesta seção, você cria jobs do Kubernetes nos namespaces team-a
e team-b
. Um controlador de job no Kubernetes cria um ou mais pods e garante que eles executem uma tarefa específica com sucesso.
Gerar jobs para os ClusterQueues que ficarão suspensos por 10 segundos, com três jobs em paralelo e com três conclusões concluídas. Em seguida, ele será limpo após 60 segundos.
job-team-a.yaml
cria jobs no namespace team-a
e aponta para o LocalQueue lq-team-a
e o ClusterQueue cq-team-a
.
Da mesma forma, job-team-b.yaml
cria jobs no namespace team-b
e aponta para o LocalQueue lq-team-b
e a ClusterQueue cq-team-b
.
Inicie um novo terminal e execute este script para gerar um job a cada segundo:
./create_jobs.sh job-team-a.yaml 1
Inicie outro terminal e crie jobs para o namespace
team-b
:./create_jobs.sh job-team-b.yaml 1
Observe os jobs que estão sendo enfileirados no Prometheus. Ou com este comando:
watch -n 2 kubectl get clusterqueues -o wide
A saída será semelhante a esta:
NAME COHORT STRATEGY PENDING WORKLOADS ADMITTED WORKLOADS
cq-team-a all-teams BestEffortFIFO 0 5
cq-team-b all-teams BestEffortFIFO 0 4
Pedir emprestado cota não utilizada com coortes
As ClusterQueues podem não estar com capacidade total o tempo todo. O uso de cotas não é maximizado quando as cargas de trabalho não são distribuídas uniformemente entre os ClusterQueues. Se ClusterQueues compartilharem a mesma coorte entre si, elas poderão pegar emprestado cotas de outras ClusterQueues para maximizar a utilização da cota.
Quando houver jobs enfileirados para os ClusterQueues
cq-team-a
ecq-team-b
, interrompa o script do namespaceteam-b
pressionandoCTRL+c
no terminal correspondente.Depois que todos os jobs pendentes do namespace
team-b
forem processados, os jobs do namespaceteam-a
poderão usar os recursos disponíveis emcq-team-b
:kubectl describe clusterqueue cq-team-a
Como
cq-team-a
ecq-team-b
compartilham a mesma coorte chamadaall-teams
, essas ClusterQueues podem compartilhar recursos que não são utilizados.Flavors Usage: Name: on-demand Resources: Borrowed: 5 Name: cpu Total: 15 Borrowed: 5Gi Name: memory Total: 15Gi
Retome o script para o namespace
team-b
../create_jobs.sh job-team-b.yaml 3
Observe como os recursos emprestados de
cq-team-a
retornam a0
, enquanto os recursos decq-team-b
são usados para as próprias cargas de trabalho:kubectl describe clusterqueue cq-team-a
Flavors Usage: Name: on-demand Resources: Borrowed: 0 Name: cpu Total: 9 Borrowed: 0 Name: memory Total: 9Gi
Aumentar a cota com VMs do Spot
Quando a cota precisar ser aumentada temporariamente, por exemplo, para atender à alta demanda em cargas de trabalho pendentes, é possível configurar o Kueue para acomodar a demanda adicionando mais ClusterQueues à coorte. ClusterQueues com recursos não utilizados podem compartilhá-los com outras ClusterQueues que pertencem à mesma coorte.
No início do tutorial, você criou um pool de nós chamado spot
usando VMs do Spot e um ResourceFlavor chamado spot
com o rótulo definido como cloud.google.com/gke-provisioning: spot
. Crie um ClusterQueue para usar este pool de nós e o ResourceFlavor que o representa:
Crie um novo ClusterQueue chamado
cq-spot
com a coorte definida comoall-teams
:Como essa ClusterQueue compartilha a mesma coorte com
cq-team-a
ecq-team-b
, acq-team-a
e acq-team-b
podem receber recursos de até 15 solicitações de CPU e 15 Gi de memória.kubectl apply -f cq-spot.yaml
No Prometheus, observe como as cargas de trabalho admitidas aumentam para
cq-team-a
ecq-team-b
graças à cota adicionada porcq-spot
que compartilha a mesma coorte. Ou com este comando:watch -n 2 kubectl get clusterqueues -o wide
No Prometheus, observe o número de nós no cluster. Ou com este comando:
watch -n 2 kubectl get nodes -o wide
Interrompa os dois scripts pressionando
CTRL+c
para os namespacesteam-a
eteam-b
.
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.
Excluir o projeto
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Excluir o recurso individual
Excluir o sistema de cotas do Kueue:
kubectl delete -n team-a localqueue lq-team-a kubectl delete -n team-b localqueue lq-team-b kubectl delete clusterqueue cq-team-a kubectl delete clusterqueue cq-team-b kubectl delete clusterqueue cq-spot kubectl delete resourceflavor default kubectl delete resourceflavor on-demand kubectl delete resourceflavor spot
Excluir o manifesto do Kueue:
VERSION=VERSION kubectl delete -f \ https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
Exclua o cluster:
gcloud container clusters delete kueue-cohort --region=COMPUTE_REGION
A seguir
Saiba mais sobre Implantar um sistema em lote usando o Kueue.
Saiba mais sobre os jobs no GKE.