Mengimplementasikan sistem antrean Tugas dengan berbagi kuota antar-namespace di GKE


Tutorial ini menggunakan Kueue untuk menunjukkan cara menerapkan sistem antrean Tugas, mengonfigurasi resource workload, dan pembagian kuota antar-namespace yang berbeda di Google Kubernetes Engine (GKE), serta untuk memaksimalkan pemanfaatan cluster Anda.

Latar belakang

Sebagai engineer infrastruktur atau administrator cluster, memaksimalkan pemanfaatan antar-namespace sangatlah penting. Batch Tugas dalam satu namespace mungkin tidak sepenuhnya menggunakan seluruh kuota yang ditetapkan ke namespace, sementara namespace lain mungkin memiliki beberapa Tugas yang tertunda. Untuk memanfaatkan resource cluster secara efisien di antara Tugas dalam berbagai namespace dan untuk meningkatkan fleksibilitas pengelolaan kuota, Anda dapat mengonfigurasi kelompok di Kueue. Kelompok adalah grup ClusterQueue yang dapat meminjam kuota yang tidak digunakan dari satu sama lain. ClusterQueue mengatur kumpulan resource seperti CPU, memori, dan akselerator hardware.

Anda dapat menemukan definisi yang lebih mendetail dari semua konsep ini di dokumentasi Kueue

Tujuan

Tutorial ini ditujukan untuk engineer infrastruktur atau administrator cluster yang ingin menerapkan sistem antrean Tugas di Kubernetes menggunakan Kueue dengan pembagian kuota.

Tutorial ini akan meniru dua tim dalam dua namespace berbeda, dan setiap tim memiliki resource khusus, tetapi dapat saling meminjam. Set ketiga dari resource dapat digunakan sebagai spillover ketika tugas terakumulasi.

Gunakan operator Prometheus untuk memantau Tugas dan alokasi resource di namespace yang berbeda.

Tutorial ini membahas langkah-langkah berikut:

  1. Membuat cluster GKE
  2. Membuat ResourceFlavors
  3. Untuk setiap tim, buat ClusterQueue dan LocalQueue
  4. (Opsional) Men-deploy kube-prometheus dan memantau Workload menggunakan Prometheus
  5. Membuat Tugas dan mengamati workload yang diizinkan
  6. Meminjam kuota yang tidak digunakan dengan kelompok
  7. Menambahkan spillover ClusterQueue yang mengatur spot VM

Biaya

Tutorial ini menggunakan komponen Google Cloud yang dapat ditagih berikut:

Gunakan Kalkulator Harga untuk membuat perkiraan biaya berdasarkan penggunaan yang Anda proyeksikan.

Setelah menyelesaikan tutorial ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk informasi selengkapnya, lihat Membersihkan.

Sebelum memulai

Menyiapkan project

  1. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. Di konsol Google Cloud, pada halaman pemilih project, klik Buat project untuk mulai membuat project Google Cloud baru.

    Buka pemilih project

  3. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  4. Aktifkan API GKE.

    Mengaktifkan API

  5. Di konsol Google Cloud, pada halaman pemilih project, klik Buat project untuk mulai membuat project Google Cloud baru.

    Buka pemilih project

  6. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  7. Aktifkan API GKE.

    Mengaktifkan API

Menetapkan setelan default untuk Google Cloud CLI

  1. Di konsol Google Cloud, mulai instance Cloud Shell:
    Buka Cloud Shell

  2. Download kode sumber untuk aplikasi contoh ini:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. Tetapkan variabel lingkungan default:

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    

    Ganti nilai berikut:

Membuat cluster GKE

  1. Buat cluster GKE bernama kueue-cohort:

    Anda akan membuat cluster dengan 6 node (2 per zona) di kumpulan default tanpa penskalaan otomatis. Jumlah tersebut adalah seluruh resource yang tersedia untuk tim di awal, sehingga harus bersaing untuk mendapatkannya.

    Anda akan melihat nanti bagaimana Kueue mengelola workload yang akan dikirim oleh kedua tim ke antrean masing-masing.

      gcloud container clusters create kueue-cohort --region COMPUTE_REGION \
      --release-channel rapid --machine-type e2-standard-4 --num-nodes 2
    

    Setelah cluster dibuat, hasilnya tampak seperti berikut ini:

      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
    

    Dengan STATUS adalah RUNNING untuk kueue-cluster.

  2. Buat node pool bernama spot.

    Node pool ini menggunakan Spot VM dan mengaktifkan penskalaan otomatis. Node pool dimulai dengan 0 node, tetapi kemudian Anda akan menyediakannya bagi tim untuk digunakan sebagai kapasitas overspill.

    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
    
  3. Instal versi rilis Kueue ke cluster:

    VERSION=VERSION
    kubectl apply -f \
      https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    

    Ganti VERSION dengan huruf v setelah versi terbaru Kueue, misalnya v0.4.0. Untuk informasi selengkapnya tentang versi Kueue, lihat rilis Kueue.

    Tunggu hingga pengontrol Kueue siap:

    watch kubectl -n kueue-system get pods
    

    Outputnya akan mirip dengan berikut ini sebelum Anda dapat melanjutkan:

    NAME                                        READY   STATUS    RESTARTS   AGE
    kueue-controller-manager-6cfcbb5dc5-rsf8k   2/2     Running   0          3m
    
  4. Buat dua namespace baru bernama team-a dan team-b:

    kubectl create namespace team-a
    kubectl create namespace team-b
    

    Tugas akan dibuat untuk setiap namespace.

Membuat ResourceFlavors

ResourceFlavor mewakili variasi resource di node cluster Anda, seperti VM yang berbeda (misalnya spot versus on-demand), arsitektur (misalnya, CPU x86 vs ARM), merek, dan model (misalnya, GPU Nvidia A100 versus T4).

ResourceFlavors menggunakan label dan taint node agar cocok dengan set node dalam cluster.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: on-demand # This ResourceFlavor will be used for the CPU resource
spec:
  nodeLabels:
    cloud.google.com/gke-provisioning: standard # This label was applied automatically by GKE
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: spot # This ResourceFlavor will be used as added resource for the CPU resource
spec:
  nodeLabels:
    cloud.google.com/gke-provisioning: spot # This label was applied automatically by GKE

Dalam manifes ini:

  • on-demand ResourceFlavor memiliki label yang ditetapkan ke cloud.google.com/gke-provisioning: standard.
  • spot ResourceFlavor memiliki label yang ditetapkan ke cloud.google.com/gke-provisioning: spot.

Saat workload diberi ResourceFlavor, Kueue menetapkan Pod workload ke node yang cocok dengan label node yang ditentukan untuk ResourceFlavor.

Men-deploy ResourceFlavor:

kubectl apply -f flavors.yaml

Membuat ClusterQueue dan LocalQueue

Membuat dua ClusterQueue cq-team-a dan cq-team-b, serta LocalQueues lq-team-a dan lq-team-b yang sesuai, dengan namespace masing-masing team-a dan team-b.

ClusterQueues adalah objek cakupan cluster yang mengatur kumpulan resource seperti CPU, memori, dan akselerator hardware. Administrator batch dapat membatasi visibilitas objek ini untuk pengguna batch.

LocalQueue adalah objek dengan namespace yang dapat dicantumkan oleh pengguna batch. Antrean mengarah ke CluterQueues, tempat resource dialokasikan untuk menjalankan workload LocalQueue.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: cq-team-a
spec:
  cohort: all-teams # cq-team-a and cq-team-b share the same cohort
  namespaceSelector:
    matchLabels:
      kubernetes.io/metadata.name: team-a #Only team-a can submit jobs direclty to this queue, but will be able to share it through the cohort
  resourceGroups:
  - coveredResources: ["cpu", "memory"]
    flavors:
    - name: on-demand
      resources:
      - name: "cpu"
        nominalQuota: 10
        borrowingLimit: 5
      - name: "memory"
        nominalQuota: 10Gi
        borrowingLimit: 15Gi
    - name: spot # This ClusterQueue doesn't have nominalQuota for spot, but it can borrow from others
      resources:
      - name: "cpu"
        nominalQuota: 0
      - name: "memory"
        nominalQuota: 0
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: team-a # LocalQueue under team-a namespace
  name: lq-team-a
spec:
  clusterQueue: cq-team-a # Point to the ClusterQueue team-a-cq

ClusterQueues memungkinkan resource memiliki beberapa ragam. Dalam hal ini, kedua ClusterQueues memiliki dua ragam, on-demand dan spot, masing-masing menyediakan resource cpu. Kuota spot ResourceFlavor ditetapkan ke 0, dan tidak akan digunakan untuk saat ini.

Kedua ClusterQueues memiliki kelompok yang sama bernama all-teams, yang ditentukan di .spec.cohort. Jika dua atau beberapa ClusterQueue berbagi kelompok yang sama, cluster tersebut dapat meminjam kuota yang tidak digunakan dari satu sama lain.

Anda dapat mempelajari lebih lanjut cara kerja kelompok dan semantik pinjaman di dokumentasi Kueue

Men-deploy ClusterQueues dan LocalQueues:

kubectl apply -f cq-team-a.yaml
kubectl apply -f cq-team-b.yaml

(Opsional) Men-deploy kube-prometheus dan memantau Workload menggunakan Prometheus

Anda dapat menggunakan Prometheus untuk memantau workload tertunda dan workload aktif Kueue. Untuk memantau workload yang ditampilkan dan mengamati muatan di setiap ClusterQueue, siapkan Prometheus ke cluster di bagian pemantauan namespace.

  1. Download kode sumber operator prometheus untuk pemantauan:

    cd
    git clone https://github.com/prometheus-operator/kube-prometheus.git
    
  2. Buat CustomResourceDefinitions(CRD):

    kubectl create -f kube-prometheus/manifests/setup
    
  3. Buat komponen pemantauan:

    kubectl create -f kube-prometheus/manifests
    
  4. Izinkan operator prometheus untuk melakukan scraping metrik dari komponen Kueue:

    kubectl apply -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/prometheus.yaml
    
  5. Ubah ke direktori kerja:

    cd kubernetes-engine-samples/batch/kueue-cohort
    
  6. Mulai terminal baru untuk mengakses Prometheus dengan penerusan port layanan:

    kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090
    
  7. Buka Prometheus di localhost:9090 pada browser

  8. Jika menggunakan Cloud Shell, klik Pratinjau Web, pilih ubah port, tetapkan nomor port ke 9090, lalu pilih Change and Preview.

  9. Masukkan kueri untuk panel pertama yang memantau ClusterQueue cq-team-a aktif:

    kueue_pending_workloads{cluster_queue="cq-team-a", status="active"} or kueue_admitted_active_workloads{cluster_queue="cq-team-a"}
    
  10. Tambahkan panel lain dan masukkan kueri yang memantau cq-team-b ClusterQueue aktif:

    kueue_pending_workloads{cluster_queue="cq-team-b", status="active"} or kueue_admitted_active_workloads{cluster_queue="cq-team-b"}
    
  11. Tambahkan panel lain dan masukkan kueri yang memantau jumlah node di cluster:

    count(kube_node_info)
    

Membuat Job dan mengamati workload yang diterima

Hasilkan Tugas ke kedua ClusterQueue yang akan tidur selama 10 detik, dengan tiga Tugas yang setara dan akan diselesaikan dengan tiga penyelesaian. Kemudian, data akan dibersihkan setelah 60 detik.

apiVersion: batch/v1
kind: Job
metadata:
  namespace: team-a # Job under team-a namespace
  generateName: sample-job-team-a-
  labels:
    kueue.x-k8s.io/queue-name: lq-team-a # Point to the LocalQueue
spec:
  ttlSecondsAfterFinished: 60 # Job will be deleted after 60 seconds
  parallelism: 3 # This Job will have 3 replicas running at the same time
  completions: 3 # This Job requires 3 completions
  suspend: true # Set to true to allow Kueue to control the Job when it starts
  template:
    spec:
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:latest
        args: ["10s"] # Sleep for 10 seconds
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
      restartPolicy: Never

job-team-a.yaml membuat Tugas pada namespace team-a dan mengarah ke LocalQueue lq-team-a dan ClusterQueue cq-team-a.

Demikian pula, job-team-b.yaml membuat Tugas pada namespace team-b, dan menunjuk ke LocalQueue lq-team-b dan ClusterQueue cq-team-b.

  1. Mulai terminal baru dan jalankan skrip ini untuk menghasilkan Tugas setiap detik:

    ./create_jobs.sh job-team-a.yaml 1
    
  2. Mulai terminal lain dan buat Tugas untuk namespace team-b:

    ./create_jobs.sh job-team-b.yaml 1
    
  3. Amati Tugas yang mengantre di Prometheus. Atau dengan perintah ini:

    watch -n 2 kubectl get clusterqueues -o wide
    

Outputnya akan mirip dengan berikut ini:

    NAME        COHORT      STRATEGY         PENDING WORKLOADS   ADMITTED WORKLOADS
    cq-team-a   all-teams   BestEffortFIFO   0                   5
    cq-team-b   all-teams   BestEffortFIFO   0                   4

Meminjam kuota yang tidak digunakan dengan kelompok

ClusterQueues mungkin tidak selalu memiliki kapasitas penuh. Penggunaan kuota tidak akan dimaksimalkan saat workload tidak tersebar secara merata di antara ClusterQueue. Jika ClusterQueues berbagi kelompok yang sama satu sama lain, ClusterQueues dapat meminjam kuota dari ClusterQueues lain untuk memaksimalkan penggunaan kuota.

  1. Setelah ada Tugas yang diantrekan untuk ClusterQueues cq-team-a dan cq-team-b, hentikan skrip untuk namespace team-b dengan menekan CTRL+c di terminal yang sesuai.

  2. Setelah semua Tugas yang tertunda dari namespace team-b diproses, tugas dari namespace team-a dapat meminjam resource yang tersedia di cq-team-b:

    kubectl describe clusterqueue cq-team-a
    

    Karena cq-team-a dan cq-team-b memiliki kelompok yang sama yang disebut all-teams, ClusterQueues ini dapat berbagi resource yang tidak digunakan.

      Flavors Usage:
        Name:  on-demand
        Resources:
          Borrowed:  5
          Name:      cpu
          Total:     15
          Borrowed:  5Gi
          Name:      memory
          Total:     15Gi
    
  3. Melanjutkan skrip untuk namespace team-b.

    ./create_jobs.sh job-team-b.yaml 3
    

    Amati bagaimana resource yang dipinjam dari cq-team-a kembali ke 0, sedangkan resource dari cq-team-b digunakan untuk workloadnya sendiri:

    kubectl describe clusterqueue cq-team-a
    
      Flavors Usage:
        Name:  on-demand
        Resources:
          Borrowed:  0
          Name:      cpu
          Total:     9
          Borrowed:  0
          Name:      memory
          Total:     9Gi
    

Meningkatkan kuota dengan Spot VM

Ketika kuota perlu ditingkatkan sementara, misalnya untuk memenuhi permintaan tinggi dalam workload yang tertunda, Anda dapat mengonfigurasi Kueue untuk mengakomodasi permintaan dengan menambahkan lebih banyak ClusterQueues ke kelompok. ClusterQueue dengan resource yang tidak digunakan dapat berbagi resource tersebut dengan ClusterQueues lain yang termasuk dalam kelompok yang sama.

Di awal tutorial, Anda telah membuat node pool bernama spot menggunakan Spot VM dan ResourceFlavor bernama spot dengan label yang ditetapkan ke cloud.google.com/gke-provisioning: spot. Buat ClusterQueue untuk menggunakan node pool ini dan ResourceFlavor yang mewakilinya:

  1. Buat ClusterQueue baru bernama cq-spot dengan kelompok yang ditetapkan ke all-teams:

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
      name: spot-cq
    spec:
      cohort: all-teams # Same cohort as cq-team-a and cq-team-b
      resourceGroups:
      - coveredResources: ["cpu", "memory"]
        flavors:
        - name: spot
          resources:
          - name: "cpu"
            nominalQuota: 40
          - name: "memory"
            nominalQuota: 144Gi

    Karena ClusterQueue ini berbagi kelompok yang sama dengan cq-team-a dan cq-team-b, ClusterQueue cq-team-a dan cq-team-b dapat meminjam resource hingga 15 permintaan CPU, dan 15 Gi memori.

    kubectl apply -f cq-spot.yaml
    
  2. Di Prometheus, amati lonjakan workload yang diterima untuk cq-team-a dan cq-team-b berkat kuota tambahan oleh cq-spot yang berbagi kelompok yang sama. Atau dengan perintah ini:

    watch -n 2 kubectl get clusterqueues -o wide
    
  3. Di Prometheus, amati jumlah node dalam cluster. Atau dengan perintah ini:

    watch -n 2 kubectl get nodes -o wide
    
  4. Hentikan kedua skrip dengan menekan CTRL+c untuk namespace team-a dan team-b.

Pembersihan

Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

Menghapus project

  1. Di konsol Google Cloud, buka halaman Manage resource.

    Buka Manage resource

  2. Pada daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.

Menghapus resource satu per satu

  1. Hapus sistem kuota 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
    
  2. Hapus manifes Kueue:

    VERSION=VERSION
    kubectl delete -f \
      https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    
  3. Hapus kluster:

    gcloud container clusters delete kueue-cohort --region=COMPUTE_REGION
    

Langkah selanjutnya