Load balancing berbasis container melalui Ingress


Halaman ini menjelaskan cara menggunakan load balancing berbasis container di Google Kubernetes Engine (GKE). Load balancing berbasis container memungkinkan load balancer langsung menarget Pod Kubernetes dan mendistribusikan traffic ke Pod secara merata.

Untuk mengetahui informasi selengkapnya tentang manfaat, persyaratan, dan batasan load balancing berbasis container, lihat Load balancing berbasis container.

Sebelum memulai

Sebelum memulai, pastikan Anda telah menjalankan tugas berikut:

  • Aktifkan Google Kubernetes Engine API.
  • Aktifkan Google Kubernetes Engine API
  • Jika ingin menggunakan Google Cloud CLI untuk tugas ini, instal lalu lakukan inisialisasi gcloud CLI. Jika sebelumnya Anda telah menginstal gcloud CLI, dapatkan versi terbaru dengan menjalankan gcloud components update.

Menggunakan load balancing berbasis container

Bagian berikut akan memandu Anda melakukan konfigurasi load balancing berbasis container di GKE. Perlu diperhatikan bahwa untuk cluster GKE yang menjalankan versi 1.17 atau yang lebih baru dan dalam kondisi tertentu, load balancing berbasis container bersifat default dan tidak memerlukan anotasi Layanan cloud.google.com/neg: '{"ingress": true}' yang eksplisit.

Membuat cluster VPC native

Untuk menggunakan load balancing native container, cluster GKE Anda harus mengaktifkan IP alias.

Misalnya, perintah berikut akan membuat cluster GKE, neg-demo-cluster, dengan subnetwork yang disediakan otomatis:

  • Untuk mode Autopilot, alamat IP alias diaktifkan secara default:

    gcloud container clusters create-auto neg-demo-cluster \
        --location=COMPUTE_LOCATION
    

    Ganti COMPUTE_LOCATION dengan lokasi Compute Engine untuk cluster.

  • Untuk mode Standar, aktifkan alamat IP alias saat Anda membuat cluster:

    gcloud container clusters create neg-demo-cluster \
        --enable-ip-alias \
        --create-subnetwork="" \
        --network=default \
        --zone=us-central1-a
    

Membuat Deployment

Contoh Deployment berikut, neg-demo-app, menjalankan satu instance server HTTP dalam container. Sebaiknya gunakan workload yang menggunakan masukan Kesiapan Pod.

Menggunakan masukan kesiapan Pod

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: registry.k8s.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
        ports:
        - containerPort: 9376
          protocol: TCP
  

Menggunakan penundaan yang di-harcode

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  minReadySeconds: 60 # Number of seconds to wait after a Pod is created and its status is Ready
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: registry.k8s.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
      # Note: The following line is necessary only on clusters running GKE v1.11 and lower.
      # For details, see https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
        ports:
        - containerPort: 9376
          protocol: TCP
      terminationGracePeriodSeconds: 60 # Number of seconds to wait for connections to terminate before shutting down Pods
  

Dalam Deployment ini, setiap container menjalankan server HTTP. Server HTTP menampilkan nama host server aplikasi (nama Pod tempat server berjalan) sebagai respons.

Simpan manifes ini sebagai neg-demo-app.yaml, lalu buat Deployment:

kubectl apply -f neg-demo-app.yaml

Membuat Layanan untuk load balancer berbasis container

Setelah membuat Deployment, Anda perlu mengelompokkan Pod-nya ke dalam Layanan.

Contoh Layanan berikut, neg-demo-svc, menargetkan contoh Deployment yang Anda buat di bagian sebelumnya:

apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc # Name of Service
  annotations:
    cloud.google.com/neg: '{"ingress": true}' # Creates a NEG after an Ingress is created
spec: # Service's specification
  type: ClusterIP
  selector:
    run: neg-demo-app # Selects Pods labelled run: neg-demo-app
  ports:
  - name: http
    port: 80 # Service's port
    protocol: TCP
    targetPort: 9376

Anotasi Layanan, cloud.google.com/neg: '{"ingress": true}', akan mengaktifkan load balancing berbasis container. Namun, load balancer tidak dibuat sebelum Anda membuat Ingress untuk Layanan.

Simpan manifes ini sebagai neg-demo-svc.yaml, lalu buat Service:

kubectl apply -f neg-demo-svc.yaml

Membuat Ingress untuk Layanan

Contoh Ingress berikut, neg-demo-ing, menargetkan Layanan yang Anda buat:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: neg-demo-ing
spec:
  defaultBackend:
    service:
      name: neg-demo-svc # Name of the Service targeted by the Ingress
      port:
        number: 80 # Should match the port used by the Service

Simpan manifes ini sebagai neg-demo-ing.yaml, lalu buat Ingress:

kubectl apply -f neg-demo-ing.yaml

Setelah membuat Ingress, Application Load Balancer akan dibuat di project, dan Grup Endpoint Jaringan(NEG) dibuat di setiap zona tempat cluster berjalan. Endpoint di NEG dan endpoint Layanan terus disinkronkan.

Memverifikasi Ingress

Setelah men-deploy workload, mengelompokkan Pod-nya ke dalam Layanan, dan membuat Ingress untuk Layanan, Anda harus memverifikasi bahwa Ingress telah berhasil menyediakan load balancer berbasis container.

Ambil status Ingress:

kubectl describe ingress neg-demo-ing

Output-nya mencakup peristiwa ADD dan CREATE:

Events:
Type     Reason   Age                From                     Message
----     ------   ----               ----                     -------
Normal   ADD      16m                loadbalancer-controller  default/neg-demo-ing
Normal   Service  4s                 loadbalancer-controller  default backend set to neg-demo-svc:32524
Normal   CREATE   2s                 loadbalancer-controller  ip: 192.0.2.0

Menguji load balancer

Bagian berikut menjelaskan cara menguji fungsi load balancer berbasis container.

Membuka alamat IP Ingress

Tunggu beberapa menit hingga Load Balancer Aplikasi dikonfigurasi.

Anda dapat memverifikasi bahwa load balancer berbasis container berfungsi dengan membuka alamat IP Ingress.

Untuk mendapatkan alamat IP Ingress, jalankan perintah berikut:

kubectl get ingress neg-demo-ing

Dalam output perintah, alamat IP Ingress ditampilkan di kolom ADDRESS. Buka alamat IP di browser web.

Memeriksa status responsivitas layanan backend

Anda juga bisa mendapatkan status responsivitas layanan backend load balancer.

  1. Dapatkan daftar layanan backend yang berjalan di project Anda:

    gcloud compute backend-services list
    

    Catat nama layanan backend yang menyertakan nama Layanan, seperti neg-demo-svc.

  2. Dapatkan status responsivitas layanan backend:

    gcloud compute backend-services get-health BACKEND_SERVICE_NAME --global
    

    Ganti BACKEND_SERVICE_NAME dengan nama layanan backend.

Menguji Ingress

Cara lain untuk menguji apakah load balancer berfungsi sesuai ekspektasi adalah dengan menskalakan Deployment contoh, mengirimkan permintaan pengujian ke Ingress, dan memverifikasi bahwa jumlah replika yang merespons sudah benar.

  1. Menskalakan Deployment neg-demo-app dari satu instance menjadi dua instance:

    kubectl scale deployment neg-demo-app --replicas 2
    

    Pemrosesan perintah ini mungkin memerlukan waktu beberapa menit.

  2. Pastikan peluncuran selesai:

    kubectl get deployment neg-demo-app
    

    Output harus menyertakan dua replika yang tersedia:

    NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    neg-demo-app   2         2         2            2           26m
    
  3. Dapatkan alamat IP Ingress:

    kubectl describe ingress neg-demo-ing
    

    Jika perintah ini menampilkan error 404, tunggu beberapa menit hingga load balancer dimulai, lalu coba lagi.

  4. Hitung jumlah respons yang berbeda dari load balancer:

    for i in `seq 1 100`; do \
      curl --connect-timeout 1 -s IP_ADDRESS && echo; \
    done  | sort | uniq -c
    

    Ganti IP_ADDRESS dengan alamat IP Ingress.

    Outputnya mirip dengan hal berikut ini:

    44 neg-demo-app-7f7dfd7bc6-dcn95
    56 neg-demo-app-7f7dfd7bc6-jrmzf
    

    Dalam output ini, jumlah respons yang berbeda sama dengan jumlah replika, yang menunjukkan bahwa semua Pod backend melayani traffic.

Pembersihan

Setelah menyelesaikan tugas di halaman ini, ikuti langkah-langkah berikut untuk menghapus resource guna mencegah timbulnya biaya yang tidak diinginkan pada akun Anda:

Menghapus cluster

gcloud

gcloud container clusters delete neg-demo-cluster

Konsol

  1. Buka halaman Google Kubernetes Engine di konsol Google Cloud.

    Buka halaman Google Kubernetes Engine

  2. Pilih neg-demo-cluster lalu klik Delete.

  3. Saat diminta untuk mengonfirmasi, klik Delete.

Pemecahan masalah

Gunakan teknik di bawah ini untuk memverifikasi konfigurasi jaringan Anda. Bagian berikut menjelaskan cara menyelesaikan masalah tertentu terkait load balancing berbasis container.

  • Lihat dokumentasi load balancing untuk mengetahui cara mencantumkan grup endpoint jaringan Anda.

  • Anda dapat menemukan nama dan zona NEG yang sesuai dengan layanan dalam anotasi neg-status layanan. Dapatkan spesifikasi Layanan dengan:

    kubectl get svc SVC_NAME -o yaml
    

    Anotasi metadata:annotations:cloud.google.com/neg-status mencantumkan nama NEG yang terkait dengan layanan dan zona NEG.

  • Anda dapat memeriksa responsivitas layanan backend yang sesuai dengan NEG menggunakan perintah berikut:

    gcloud compute backend-services --project PROJECT_NAME \
        get-health BACKEND_SERVICE_NAME --global
    

    Layanan backend memiliki nama yang sama dengan NEG-nya.

  • Untuk mencetak log aktivitas layanan:

    kubectl describe svc SERVICE_NAME
    

    String nama layanan mencakup nama dan namespace Layanan GKE yang terkait.

Tidak dapat membuat cluster dengan IP alias

Gejala

Saat mencoba membuat cluster dengan IP alias, Anda mungkin mengalami error berikut:

ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
Kemungkinan penyebab

Anda mengalami error ini jika mencoba membuat cluster dengan IP alias yang juga menggunakan jaringan lama.

Resolusi

Pastikan Anda tidak membuat cluster dengan IP alias dan jaringan lama yang diaktifkan secara bersamaan. Untuk mengetahui informasi selengkapnya tentang penggunaan IP alias, lihat Membuat cluster VPC native.

Traffic tidak mencapai endpoint

Gejala
Error 502/503 atau koneksi ditolak.
Kemungkinan penyebab

Endpoint baru umumnya dapat dijangkau setelah memasangkan endpoint tersebut ke load balancer, asalkan endpoint itu merespons health check. Anda mungkin mengalami error 502 atau koneksi ditolak jika traffic tidak dapat mencapai endpoint.

Error 502 dan koneksi yang ditolak juga dapat disebabkan oleh container yang tidak menangani SIGTERM. Jika container tidak menangani SIGTERM secara eksplisit, container tersebut akan segera menghentikan dan berhenti menangani permintaan. Load balancer terus mengirim traffic masuk ke container yang dihentikan, sehingga menyebabkan error.

Load balancer berbasis container hanya memiliki satu endpoint backend. Selama update berkelanjutan, endpoint lama di-deprogram sebelum endpoint baru diprogram.

Pod Backend akan di-deploy ke zona baru untuk pertama kalinya setelah load balancer berbasis container disediakan. Infrastruktur load balancer diprogram di zona saat setidaknya ada satu endpoint di zona tersebut. Saat endpoint baru ditambahkan ke suatu zona, infrastruktur load balancer diprogram dan menyebabkan gangguan layanan.

Resolusi

Konfigurasikan container untuk menangani SIGTERM dan terus respons permintaan selama masa tenggang penghentian (30 detik secara default). Konfigurasi Pod untuk mulai gagal dalam health check saat menerima SIGTERM. Sinyal ini akan memberi tahu load balancer untuk berhenti mengirim traffic ke Pod saat proses deprogram endpoint sedang berlangsung.

Jika aplikasi Anda tidak dinonaktifkan dengan baik dan berhenti merespons permintaan saat menerima SIGTERM, hook preStop dapat digunakan untuk menangani SIGTERM dan tetap menyalurkan traffic saat proses deprogram endpoint sedang berlangsung.

lifecycle:
  preStop:
    exec:
      # if SIGTERM triggers a quick exit; keep serving traffic instead
      command: ["sleep","60"]

Lihat dokumentasi tentang penghentian Pod.

Jika backend load balancer hanya memiliki satu instance, konfigurasi strategi peluncuran agar tidak menghilangkan satu-satunya instance sebelum instance baru diprogram sepenuhnya. Untuk pod aplikasi yang dikelola oleh workload Deployment, hal ini dapat dicapai dengan mengonfigurasi strategi peluncuran dengan parameter maxUnavailable yang setara dengan 0.

strategy:
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

Untuk memecahkan masalah traffic yang tidak mencapai endpoint, pastikan aturan firewall mengizinkan traffic TCP masuk ke endpoint Anda dalam rentang 130.211.0.0/22 dan 35.191.0.0/16. Untuk mempelajari lebih lanjut, lihat Menambahkan Health Check di dokumentasi Cloud Load Balancing.

Lihat layanan backend di project Anda. String nama layanan backend yang relevan mencakup nama dan namespace Layanan GKE yang sesuai:

gcloud compute backend-services list

Ambil status respons backend dari layanan backend:

gcloud compute backend-services get-health BACKEND_SERVICE_NAME

Jika semua backend tidak responsif, firewall, Ingress, atau Layanan Anda mungkin salah dikonfigurasi.

Jika beberapa backend tidak responsif dalam waktu singkat, kemungkinan penyebabnya adalah latensi pemrograman jaringan.

Jika beberapa backend tidak muncul dalam daftar layanan backend, kemungkinan penyebabnya adalah latensi pemrograman. Anda dapat memverifikasinya dengan menjalankan perintah berikut, dengan NEG_NAME adalah nama layanan backend. (NEG dan layanan backend menggunakan nama yang sama):

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME

Periksa apakah semua endpoint yang diharapkan ada di NEG.

Jika Anda memiliki sedikit backend (misalnya, 1 Pod) yang dipilih oleh load balancer berbasis container, sebaiknya tingkatkan jumlah replika dan distribusikan Pod backend di semua zona yang dicakup cluster GKE. Tindakan ini akan memastikan infrastruktur load balancer dasar sudah diprogram sepenuhnya. Jika tidak, pertimbangkan untuk membatasi Pod backend ke satu zona.

Jika Anda mengonfigurasi kebijakan jaringan untuk endpoint, pastikan traffic masuk dari subnet khusus Proxy diizinkan.

Peluncuran terhenti

Gejala
Peluncuran peluncuran Deployment yang diupdate terhenti, dan jumlah replika terbaru tidak sesuai dengan jumlah replika yang diinginkan.
Kemungkinan penyebab

Health check deployment gagal. Image container mungkin buruk atau health check mungkin salah dikonfigurasi. Penggantian peluncuran Pod menunggu hingga Pod yang baru dimulai lulus gate kesiapan Pod-nya. Ini hanya terjadi jika Pod merespons health check load balancer. Jika Pod tidak merespons, atau jika health check salah dikonfigurasi, kondisi gate kesiapan tidak dapat terpenuhi dan peluncuran tidak dapat dilanjutkan.

Jika menggunakan kubectl 1.13 atau yang lebih tinggi, Anda dapat memeriksa status gateway kesiapan Pod dengan perintah berikut:

kubectl get pod POD_NAME -o wide

Periksa kolom READINESS GATES.

Kolom ini tidak ada di kubectl 1.12 dan versi sebelumnya. Pod yang ditandai sebagai berada dalam status READY mungkin memiliki gate kesiapan yang gagal. Untuk memastikannya, gunakan perintah berikut:

kubectl get pod POD_NAME -o yaml

Gate kesiapan dan statusnya tercantum di output.

Resolusi

Verifikasi bahwa image container di spesifikasi Pod Deployment Anda berfungsi dengan benar dan dapat merespons health check. Pastikan health check dikonfigurasi dengan benar.

Error mode yang terdegradasi

Gejala

Mulai dari GKE versi 1.29.2-gke.1643000, Anda mungkin mendapatkan peringatan berikut di layanan Anda di Logs Explorer saat NEG diperbarui:

Entering degraded mode for NEG <service-namespace>/<service-name>-<neg-name>... due to sync err: endpoint has missing nodeName field
Kemungkinan penyebab

Peringatan ini menunjukkan bahwa GKE telah mendeteksi kesalahan konfigurasi endpoint selama update NEG berdasarkan objek EndpointSlice, yang memicu proses penghitungan yang lebih mendalam yang disebut mode menurun. GKE terus memperbarui NEG berdasarkan upaya terbaik, dengan memperbaiki kesalahan konfigurasi atau mengecualikan endpoint yang tidak valid dari update NEG.

Beberapa error umum adalah:

  • endpoint has missing pod/nodeName field
  • endpoint corresponds to an non-existing pod/node
  • endpoint information for attach/detach operation is incorrect
Resolusi

Biasanya, status sementara menyebabkan peristiwa ini dan peristiwa ini akan diperbaiki dengan sendirinya. Namun, peristiwa yang disebabkan oleh kesalahan konfigurasi dalam objek EndpointSlice kustom tetap tidak terselesaikan. Untuk memahami kesalahan konfigurasi, periksa objek EndpointSlice yang sesuai dengan layanan:

kubectl get endpointslice -l kubernetes.io/service-name=<service-name>

Validasi setiap endpoint berdasarkan error dalam peristiwa.

Untuk mengatasi masalah ini, Anda harus mengubah objek EndpointSlice secara manual. Pembaruan tersebut memicu NEG untuk diperbarui lagi. Setelah kesalahan konfigurasi tidak ada lagi, output-nya akan mirip dengan yang berikut ini:

NEG <service-namespace>/<service-name>-<neg-name>... is no longer in degraded mode

Masalah umum

Load balancing berbasis container di GKE memiliki masalah umum berikut:

Pembersihan sampah memori tidak selesai

Sampah GKE membersihkan load balancer berbasis container setiap dua menit. Jika cluster dihapus sebelum load balancer sepenuhnya dihapus, Anda harus menghapus NEG load balancer secara manual.

Lihat NEG di project Anda dengan menjalankan perintah berikut:

gcloud compute network-endpoint-groups list

Di output perintah, cari NEG yang relevan.

Untuk menghapus NEG, jalankan perintah berikut, dengan mengganti NEG_NAME dengan nama NEG:

gcloud compute network-endpoint-groups delete NEG_NAME

Menyelaraskan peluncuran workload dengan penerapan endpoint

Saat Anda men-deploy workload ke cluster, atau saat mengupdate workload yang sudah ada, load balancer berbasis container dapat memerlukan waktu lebih lama untuk menerapkan endpoint baru daripada yang diperlukan untuk menyelesaikan peluncuran workload. Contoh Deployment yang Anda deploy dalam panduan ini menggunakan dua kolom untuk menyelaraskan peluncurannya dengan penerapan endpoint: terminationGracePeriodSeconds dan minReadySeconds.

terminationGracePeriodSeconds memungkinkan Pod dimatikan secara tuntas dengan menunggu koneksi dihentikan setelah Pod dijadwalkan untuk dihapus.

minReadySeconds akan menambahkan periode latensi setelah Pod dibuat. Anda menentukan jumlah detik minimum kapan Pod baru akan berada dalam status Ready, tanpa container-nya mengalami error, agar Pod dapat dianggap tersedia.

Anda harus mengonfigurasi nilai minReadySeconds dan terminationGracePeriodSeconds workload menjadi 60 detik atau lebih untuk memastikan layanan tidak terganggu karena peluncuran workload.

terminationGracePeriodSeconds tersedia di semua spesifikasi Pod, dan minReadySeconds tersedia untuk Deployment dan DaemonSet.

Untuk mempelajari lebih lanjut cara menyesuaikan peluncuran, lihat RollingUpdateStrategy.

initialDelaySeconds di Pod readinessProbe tidak dipatuhi

Anda mungkin berharap konfigurasi initialDelaySeconds di readinessProbe Pod akan dipatuhi oleh load balancer berbasis container. Namun, readinessProbe diterapkan oleh kubelet, dan konfigurasi initialDelaySeconds akan mengontrol health check kubelet, bukan load balancer berbasis container. Load balancing berbasis container memiliki health check load balancing-nya sendiri.

Langkah berikutnya