Memecahkan masalah penjadwal Kubernetes

Halaman ini menunjukkan cara menyelesaikan masalah pada penjadwal Kubernetes (kube-scheduler) untuk Google Distributed Cloud.

Kubernetes selalu menjadwalkan Pod ke set node yang sama

Error ini dapat diamati dengan beberapa cara:

  • Penggunaan cluster yang tidak seimbang. Anda dapat memeriksa pemanfaatan cluster untuk setiap Node dengan perintah kubectl top nodes. Contoh output yang dilebih-lebihkan berikut menunjukkan penggunaan yang signifikan pada Node tertentu:

    NAME                   CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%
    XXX.gke.internal       222m         101%       3237Mi          61%
    YYY.gke.internal       91m          0%         2217Mi          0%
    ZZZ.gke.internal       512m         0%         8214Mi          0%
    
  • Terlalu banyak permintaan. Jika Anda menjadwalkan banyak Pod sekaligus ke Node yang sama dan Pod tersebut membuat permintaan HTTP, Node tersebut dapat dibatasi lajunya. Error umum yang ditampilkan oleh server dalam skenario ini adalah 429 Too Many Requests.

  • Layanan tidak tersedia. Misalnya, server web yang dihosting di Node dengan beban tinggi dapat merespons semua permintaan dengan error 503 Service Unavailable hingga beban berkurang.

Untuk memeriksa apakah Anda memiliki Pod yang selalu dijadwalkan ke node yang sama, gunakan langkah-langkah berikut:

  1. Jalankan perintah kubectl berikut untuk melihat status Pod:

    kubectl get pods -o wide -n default
    

    Untuk melihat distribusi Pod di seluruh Node, periksa kolom NODE dalam output. Dalam contoh output berikut, semua Pod dijadwalkan di Node yang sama:

    NAME                               READY  STATUS   RESTARTS  AGE  IP             NODE
    nginx-deployment-84c6674589-cxp55  1/1    Running  0         55s  10.20.152.138  10.128.224.44
    nginx-deployment-84c6674589-hzmnn  1/1    Running  0         55s  10.20.155.70   10.128.226.44
    nginx-deployment-84c6674589-vq4l2  1/1    Running  0         55s  10.20.225.7    10.128.226.44
    

Pod memiliki sejumlah fitur yang memungkinkan Anda menyesuaikan perilaku penjadwalannya. Fitur ini mencakup batasan penyebaran topologi dan aturan anti-afinitas. Anda dapat menggunakan salah satu atau kombinasi fitur ini. Persyaratan yang Anda tentukan digabungkan menggunakan fungsi AND oleh kube-scheduler.

Log penjadwal tidak dicatat pada tingkat keaktifan logging default. Jika Anda memerlukan log penjadwal untuk pemecahan masalah, lakukan langkah-langkah berikut untuk merekam log penjadwal:

  1. Tingkatkan level kejelasan logging:

    1. Edit Deployment kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Tambahkan tanda --v=5 di bagian spec.containers.command:

      containers:
      - command:
      - kube-scheduler
      - --profiling=false
      - --kubeconfig=/etc/kubernetes/scheduler.conf
      - --leader-elect=true
      - --v=5
      
  2. Setelah Anda selesai memecahkan masalah, reset kembali tingkat kejelasan ke tingkat default:

    1. Edit Deployment kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Setel kembali tingkat kejelasan ke nilai default:

      containers:
      - command:
      - kube-scheduler
      - --profiling=false
      - --kubeconfig=/etc/kubernetes/scheduler.conf
      - --leader-elect=true
      

Batasan penyebaran topologi

Batasan penyebaran topologi dapat digunakan untuk mendistribusikan Pod secara merata di antara Node sesuai dengan zones, regions, node, atau topologi yang ditentukan kustom lainnya.

Contoh manifes berikut menunjukkan Deployment yang menyebarkan replika secara merata di antara semua Node yang dapat dijadwalkan menggunakan batasan penyebaran topologi:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: topology-spread-deployment
  labels:
    app: myapp
spec:
  replicas: 30
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      topologySpreadConstraints:
      - maxSkew: 1 # Default. Spreads evenly. Maximum difference in scheduled Pods per Node.
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: DoNotSchedule # Default. Alternatively can be ScheduleAnyway
        labelSelector:
          matchLabels:
            app: myapp
        matchLabelKeys: # beta in 1.27
        - pod-template-hash
      containers:
      # pause is a lightweight container that simply sleeps
      - name: pause
        image: registry.k8s.io/pause:3.2

Pertimbangan berikut berlaku saat menggunakan batasan penyebaran topologi:

  • labels.app: myapp Pod dicocokkan dengan labelSelector batasan.
  • topologyKey menentukan kubernetes.io/hostname. Label ini secara otomatis dilampirkan ke semua Node dan diisi dengan nama host Node.
  • matchLabelKeys mencegah peluncuran Deployment baru mempertimbangkan Pod revisi lama saat menghitung tempat untuk menjadwalkan Pod. Label pod-template-hash diisi secara otomatis oleh Deployment.

Anti-afinitas Pod

Anti-afinitas Pod memungkinkan Anda menentukan batasan untuk Pod mana yang dapat ditempatkan bersama di Node yang sama.

Contoh manifes berikut menunjukkan Deployment yang menggunakan anti-afinitas untuk membatasi replika menjadi satu Pod per Node:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-affinity-deployment
  labels:
    app: myapp
spec:
  replicas: 30
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      name: with-pod-affinity
      labels:
        app: myapp
    spec:
      affinity:
        podAntiAffinity:
          # requiredDuringSchedulingIgnoredDuringExecution
          # prevents Pod from being scheduled on a Node if it
          # does not meet criteria.
          # Alternatively can use 'preferred' with a weight
          # rather than 'required'.
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - myapp
            # Your nodes might be configured with other keys
            # to use as `topologyKey`. `kubernetes.io/region`
            # and `kubernetes.io/zone` are common.
            topologyKey: kubernetes.io/hostname
      containers:
      # pause is a lightweight container that simply sleeps
      - name: pause
        image: registry.k8s.io/pause:3.2

Deployment contoh ini menentukan 30 replika, tetapi hanya diperluas sebanyak Node yang tersedia di cluster Anda.

Pertimbangan berikut berlaku saat menggunakan anti-afinitas Pod:

  • labels.app: myapp Pod dicocokkan dengan labelSelector batasan.
  • topologyKey menentukan kubernetes.io/hostname. Label ini secara otomatis dilampirkan ke semua Node dan diisi dengan nama host Node. Anda dapat memilih untuk menggunakan label lain jika cluster Anda mendukungnya, seperti region atau zone.

Menarik image container sebelumnya

Jika tidak ada batasan lain, secara default kube-scheduler lebih memilih untuk menjadwalkan Pod di Node yang telah mendownload image container ke Node tersebut. Perilaku ini mungkin menarik di cluster yang lebih kecil tanpa konfigurasi penjadwalan lain yang memungkinkan gambar didownload di setiap Node. Namun, mengandalkan konsep ini harus dilihat sebagai upaya terakhir. Solusi yang lebih baik adalah menggunakan nodeSelector, batasan penyebaran topologi, atau afinitas / anti-afinitas. Untuk mengetahui informasi selengkapnya, lihat bagian Menetapkan Pod ke Node.

Jika ingin memastikan image container ditarik sebelumnya ke semua Node, Anda dapat menggunakan DaemonSet seperti contoh berikut:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: prepulled-images
spec:
  selector:
    matchLabels:
      name: prepulled-images
  template:
    metadata:
      labels:
        name: prepulled-images
    spec:
      initContainers:
        - name: prepulled-image
          image: IMAGE
          # Use a command the terminates immediately
          command: ["sh", "-c", "'true'"]
      containers:
      # pause is a lightweight container that simply sleeps
      - name: pause
        image: registry.k8s.io/pause:3.2

Setelah Pod Running di semua Node, deploy ulang Pod Anda untuk melihat apakah container sekarang didistribusikan secara merata di seluruh Node.

Langkah berikutnya

Jika Anda memerlukan bantuan tambahan, hubungi Cloud Customer Care.

Anda juga dapat melihat bagian Mendapatkan dukungan untuk mengetahui informasi selengkapnya tentang sumber dukungan, termasuk yang berikut:

  • Persyaratan untuk membuka kasus dukungan.
  • Alat untuk membantu Anda memecahkan masalah, seperti log dan metrik.
  • Komponen yang didukung, versi, dan fitur Google Distributed Cloud untuk VMware (khusus software).