Menggunakan Envoy Proxy untuk melakukan load balance pada layanan gRPC di GKE

Last reviewed 2019-05-30 UTC

Tutorial ini menunjukkan cara mengekspos beberapa layanan gRPC yang di-deploy di Google Kubernetes Engine (GKE) pada satu alamat IP eksternal menggunakan Load Balancer Jaringan passthrough eksternal dan Envoy Proxy. Tutorial ini menyoroti beberapa fitur lanjutan yang disediakan Envoy untuk gRPC.

Pengantar

gRPC adalah framework RPC open source, tanpa dependensi bahasa, dan berbasis HTTP/2 yang menggunakan buffering protokol untuk menghadirkan representasi operasi yang efisien dan serialisasi yang cepat. Terinspirasi oleh Stubby, framework RPC Google internal, gRPC memungkinkan komunikasi berlatensi rendah di antara microservice serta di antara klien seluler dan API.

gRPC berjalan melalui HTTP/2 dan menawarkan beberapa keunggulan dibandingkan HTTP/1.1, seperti encoding biner yang efisien, multiplexing permintaan dan respons melalui satu koneksi, serta kontrol alur otomatis. gRPC juga menawarkan beberapa opsi untuk load balancing. Tutorial ini berfokus pada situasi saat klien tidak tepercaya, seperti klien seluler dan klien yang berjalan di luar batas kepercayaan penyedia layanan. Dari opsi load balancing yang disediakan gRPC, Anda menggunakan load balancing berbasis proxy dalam tutorial ini.

Dalam tutorial ini, Anda akan men-deploy Service Kubernetes TYPE=LoadBalancer, yang diekspos sebagai Load Balancer Jaringan passthrough eksternal lapisan transpor (lapisan 4) di Google Cloud. Layanan ini menyediakan satu alamat IP publik dan meneruskan koneksi TCP langsung ke backend yang dikonfigurasi. Dalam tutorial, backend adalah Deployment Kubernetes dari instance Envoy.

Envoy adalah proxy lapisan aplikasi open source (lapisan 7) yang menawarkan banyak fitur lanjutan. Dalam tutorial ini, Anda akan menggunakannya untuk menghentikan koneksi TLS dan merutekan traffic gRPC ke Service Kubernetes yang sesuai. Dibandingkan dengan solusi lapisan aplikasi lainnya seperti Ingress Kubernetes, penggunaan Envoy secara langsung akan memberikan beberapa opsi penyesuaian, seperti berikut:

  • Penemuan layanan
  • Algoritma load-balancing
  • Mengubah permintaan dan respons—misalnya, ke JSON atau gRPC-Web
  • Mengautentikasi permintaan dengan memvalidasi token JWT
  • Health check gRPC

Melalui penggabungan Load Balancer Jaringan passthrough eksternal dengan Envoy, Anda dapat menyiapkan endpoint (alamat IP eksternal) yang meneruskan traffic ke sekumpulan instance Envoy yang berjalan di cluster Google Kubernetes Engine. Instance ini kemudian menggunakan informasi lapisan aplikasi untuk mem-proxy permintaan ke berbagai layanan gRPC yang berjalan di cluster. Instance Envoy menggunakan DNS cluster untuk mengidentifikasi dan melakukan load balancing pada permintaan gRPC yang masuk ke pod yang responsif dan berjalan untuk setiap layanan. Artinya, traffic akan di-load balance ke pod per permintaan RPC, bukan per koneksi TCP dari klien.

Arsitektur

Dalam tutorial ini, Anda akan men-deploy dua layanan gRPC, echo-grpc dan reverse-grpc, di cluster Google Kubernetes Engine (GKE) dan mengeksposnya ke internet di alamat IP publik. Diagram berikut menunjukkan arsitektur untuk mengekspos kedua layanan ini melalui satu endpoint:

arsitektur untuk mengekspos `echo-grpc` dan `reverse-grpc` melalui satu endpoint

Load Balancer Jaringan passthrough eksternal menerima permintaan masuk dari internet (misalnya, dari klien seluler atau konsumen layanan di luar perusahaan Anda). Load Balancer Jaringan passthrough eksternal melakukan tugas-tugas berikut:

  • Melakukan load balancing koneksi masuk ke node dalam kumpulan. Traffic diteruskan ke Service Kubernetes envoy, yang diekspos di semua node dalam cluster. Proxy jaringan Kubernetes meneruskan koneksi ini ke pod yang menjalankan Envoy.
  • Melakukan health check HTTP terhadap node di cluster.

Envoy melakukan tugas berikut:

  • Menghentikan koneksi TLS.
  • Menemukan pod yang menjalankan layanan gRPC dengan membuat kueri layanan DNS cluster internal.
  • Merutekan dan melakukan load balancing traffic ke pod layanan gRPC.
  • Melakukan health check pada layanan gRPC sesuai dengan Protokol Health Check gRPC.
  • Mengekspos endpoint untuk health check atas instance Envoy oleh Load Balancer Jaringan passthrough eksternal.

Layanan gRPC (echo-grpc dan reverse-grpc) diekspos sebagai Service headless Kubernetes. Artinya, tidak ada alamat clusterIP yang ditetapkan, dan proxy jaringan Kubernetes tidak melakukan load balancing pada traffic ke pod. Sebagai gantinya, data A DNS yang berisi alamat IP pod dibuat di layanan DNS cluster. Envoy menemukan alamat IP pod dari entri DNS ini dan melakukan load balancing berdasarkan kebijakan yang dikonfigurasi di Envoy.

Diagram berikut menunjukkan objek Kubernetes yang terlibat dalam tutorial ini:

Objek Kubernetes digunakan dalam tutorial ini, termasuk layanan, file YAML, data A DNS, secret, pod, dan entri proxy

Biaya

Dalam dokumen ini, Anda menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga. Pengguna baru Google Cloud mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

  1. Di konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.

    Buka pemilih project

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

  3. Di konsol Google Cloud, aktifkan Cloud Shell.

    Aktifkan Cloud Shell

Menyiapkan lingkungan

  1. Di Cloud Shell, tetapkan project Google Cloud yang ingin Anda gunakan untuk tutorial ini:

    gcloud config set project PROJECT_ID
    

    Ganti PROJECT_ID dengan project ID Google Cloud Anda.

  2. Aktifkan Artifact Registry API dan GKE API:

    gcloud services enable artifactregistry.googleapis.com \
        container.googleapis.com
    

Membuat cluster GKE

  1. Di Cloud Shell, buat cluster GKE untuk menjalankan layanan gRPC Anda:

    gcloud container clusters create envoy-grpc-tutorial \
        --enable-ip-alias \
        --release-channel rapid \
        --scopes cloud-platform \
        --workload-pool PROJECT_ID.svc.id.goog \
        --zone us-central1-f
    

    Tutorial ini menggunakan zona us-central1-f. Anda dapat menggunakan zona atau region yang berbeda.

  2. Pastikan konteks kubectl telah disiapkan dengan mencantumkan node di cluster Anda:

    kubectl get nodes --output name
    

    Output-nya terlihat mirip dengan ini:

    node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-1kpt
    node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-qn92
    node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-wf2h
    

Membuat repositori Artifact Registry

  1. Di Cloud Shell, buat repositori baru untuk menyimpan image container:

    gcloud artifacts repositories create envoy-grpc-tutorial-images \
        --repository-format docker \
        --location us-central1
    

    Anda membuat repositori di region yang sama dengan cluster GKE untuk membantu mengoptimalkan latensi dan bandwidth jaringan saat node mengambil image container.

  2. Berikan peran Reader Artifact Registry pada repositori ke akun layanan Google yang digunakan oleh VM node cluster GKE:

    PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'value(projectNumber)')
    
    gcloud artifacts repositories add-iam-policy-binding envoy-grpc-tutorial-images \
        --location us-central1 \
        --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
        --role roles/artifactregistry.reader
    
  3. Tambahkan entri helper kredensial untuk nama host repositori ke file konfigurasi Docker di direktori beranda Cloud Shell Anda:

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

    Entri helper kredensial memungkinkan alat image container yang berjalan di Cloud Shell melakukan autentikasi ke lokasi repositori Artifact Registry untuk mengambil dan mengirim image.

Men-deploy layanan gRPC

Untuk merutekan traffic ke beberapa layanan gRPC di balik satu load balancer, Anda harus men-deploy dua contoh layanan gRPC: echo-grpc dan reverse-grpc. Kedua layanan ini mengekspos metode unary yang mengambil string dalam kolom permintaan content. echo-grpc merespons dengan konten yang tidak diubah, sedangkan reverse-grpc merespons dengan string konten yang dibalik.

  1. Di Cloud Shell, buat clone repositori yang berisi layanan gRPC dan beralih ke direktori repositori:

    git clone https://github.com/GoogleCloudPlatform/grpc-gke-nlb-tutorial.git ~/grpc-gke-nlb-tutorial
    
    cd ~/grpc-gke-nlb-tutorial
    
  2. Buat kunci pribadi dan sertifikat TLS yang ditandatangani sendiri:

    openssl req -x509 -newkey rsa:4096 -nodes -sha256 -days 365 \
        -keyout privkey.pem -out cert.pem -extensions san \
        -config \
        <(echo "[req]";
          echo distinguished_name=req;
          echo "[san]";
          echo subjectAltName=DNS:grpc.example.com
         ) \
        -subj '/CN=grpc.example.com'
    
  3. Buat Secret Kubernetes bernama envoy-certs yang berisi kunci pribadi dan sertifikat TLS yang ditandatangani sendiri:

    kubectl create secret tls envoy-certs \
        --key privkey.pem --cert cert.pem \
        --dry-run=client --output yaml | kubectl apply --filename -
    

    Envoy menggunakan sertifikat TLS dan kunci pribadi ini saat menghentikan koneksi TLS.

  4. Bangun image container untuk aplikasi contoh echo-grpc dan reverse-grpc, kirim image ke Artifact Registry, dan deploy aplikasi ke cluster GKE menggunakan Skaffold:

    skaffold run \
        --default-repo=us-central1-docker.pkg.dev/PROJECT_ID/envoy-grpc-tutorial-images \
        --module=echo-grpc,reverse-grpc \
        --skip-tests
    

    Skaffold adalah alat open source dari Google yang mengotomatiskan alur kerja untuk mengembangkan, membangun, mengirim, dan men-deploy aplikasi sebagai container.

  5. Deploy Envoy ke cluster GKE menggunakan Skaffold:

    skaffold run \
        --digest-source=none \
        --module=envoy \
        --skip-tests
    
  6. Pastikan dua pod sudah siap untuk setiap deployment:

    kubectl get deployments
    

    Output-nya terlihat mirip dengan ini: Nilai untuk READY harus 2/2 untuk semua deployment.

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    echo-grpc      2/2     2            2           1m
    envoy          2/2     2            2           1m
    reverse-grpc   2/2     2            2           1m
    
  7. Verifikasi bahwa echo-grpc, envoy, dan reverse-grpc ada sebagai Service Kubernetes:

    kubectl get services --selector skaffold.dev/run-id
    

    Output-nya terlihat mirip dengan ini: echo-grpc dan reverse-grpc harus memiliki TYPE=ClusterIP dan CLUSTER-IP=None.

    NAME           TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)         AGE
    echo-grpc      ClusterIP      None          <none>           8081/TCP        2m
    envoy          LoadBalancer   10.40.2.203   203.0.113.1      443:31516/TCP   2m
    reverse-grpc   ClusterIP      None          <none>           8082/TCP        2m
    

Menguji layanan gRPC

Untuk menguji layanan, gunakan alat command line grpcurl.

  1. Di Cloud Shell, instal grpcurl:

    go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
    
  2. Dapatkan alamat IP eksternal Service Kubernetes envoy dan simpan di variabel lingkungan:

    EXTERNAL_IP=$(kubectl get service envoy \
        --output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
    
  3. Kirim permintaan ke aplikasi contoh echo-grpc:

    grpcurl -v -d '{"content": "echo"}' \
        -proto echo-grpc/api/echo.proto \
        -authority grpc.example.com -cacert cert.pem \
        $EXTERNAL_IP:443 api.Echo/Echo
    

    Output-nya terlihat mirip dengan ini:

    Resolved method descriptor:
    rpc Echo ( .api.EchoRequest ) returns ( .api.EchoResponse );
    
    Request metadata to send:
    (empty)
    
    Response headers received:
    content-type: application/grpc
    date: Wed, 02 Jun 2021 07:18:22 GMT
    hostname: echo-grpc-75947768c9-jkdcw
    server: envoy
    x-envoy-upstream-service-time: 3
    
    Response contents:
    {
      "content": "echo"
    }
    
    Response trailers received:
    (empty)
    Sent 1 request and received 1 response
    

    Header respons hostname menampilkan nama pod echo-grpc yang menangani permintaan. Jika mengulangi perintah ini beberapa kali, Anda akan melihat dua nilai berbeda untuk header respons hostname, yang sesuai dengan nama pod echo-grpc.

  4. Verifikasi perilaku yang sama dengan layanan Reverse gRPC:

    grpcurl -v -d '{"content": "reverse"}' \
        -proto reverse-grpc/api/reverse.proto \
        -authority grpc.example.com -cacert cert.pem \
        $EXTERNAL_IP:443 api.Reverse/Reverse
    

    Output-nya terlihat mirip dengan ini:

    Resolved method descriptor:
    rpc Reverse ( .api.ReverseRequest ) returns ( .api.ReverseResponse );
    
    Request metadata to send:
    (empty)
    
    Response headers received:
    content-type: application/grpc
    date: Wed, 02 Jun 2021 07:20:15 GMT
    hostname: reverse-grpc-5c9b974f54-wlfwt
    server: envoy
    x-envoy-upstream-service-time: 1
    
    Response contents:
    {
      "content": "esrever"
    }
    
    Response trailers received:
    (empty)
    Sent 1 request and received 1 response
    

Konfigurasi envoy

Untuk lebih memahami konfigurasi Envoy, Anda dapat melihat file konfigurasi envoy/k8s/envoy.yaml di repositori Git.

Bagian route_config menentukan cara permintaan masuk dirutekan ke aplikasi contoh echo-grpc dan reverse-grpc.

route_config:
  name: local_route
  virtual_hosts:
  - name: local_service
    domains:
    - "*"
    routes:
    - match:
        prefix: "/api.Echo/"
      route:
        cluster: echo-grpc
    - match:
        prefix: "/api.Reverse/"
      route:
        cluster: reverse-grpc

Aplikasi contoh ditentukan sebagai cluster Envoy.

clusters:
- name: echo-grpc
  connect_timeout: 0.5s
  type: STRICT_DNS
  dns_lookup_family: V4_ONLY
  lb_policy: ROUND_ROBIN
  http2_protocol_options: {}
  load_assignment:
    cluster_name: echo-grpc
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: echo-grpc.default.svc.cluster.local
              port_value: 8081
  health_checks:
    timeout: 1s
    interval: 10s
    unhealthy_threshold: 2
    healthy_threshold: 2
    grpc_health_check: {}

Kolom type: STRICT_DNS dan lb_policy: ROUND_ROBIN dalam definisi cluster menentukan bahwa Envoy melakukan pencarian DNS untuk nama host yang ditentukan dalam kolom address dan melakukan load balancing di seluruh alamat IP sebagai respons terhadap pencarian DNS. Respons ini berisi beberapa alamat IP karena objek Service Kubernetes yang menentukan aplikasi contoh menentukan layanan headless.

Kolom http2_protocol_options menentukan bahwa Envoy menggunakan protokol HTTP/2 ke aplikasi contoh.

Kolom grpc_health_check di bagian health_checks menentukan bahwa Envoy menggunakan protokol health check gRPC untuk menentukan kondisi aplikasi contoh.

Memecahkan masalah

Jika Anda mengalami masalah dengan tutorial ini, sebaiknya tinjau dokumen berikut:

Anda juga dapat menjelajahi antarmuka administrasi Envoy untuk mendiagnosis masalah pada konfigurasi Envoy.

  1. Untuk membuka antarmuka administrasi, siapkan penerusan port dari Cloud Shell ke port admin di salah satu pod Envoy:

    kubectl port-forward \
        $(kubectl get pods -o name | grep envoy | head -n1) 8080:8090
    
  2. Tunggu hingga Anda melihat output ini di konsol:

    Forwarding from 127.0.0.1:8080 -> 8090
    
  3. Klik tombol Web preview di Cloud Shell dan pilih Preview on port 8080. Tindakan ini akan membuka jendela browser baru yang menampilkan antarmuka administrasi.

    Antarmuka admin Envoy dengan pratinjau yang dipilih

  4. Setelah selesai, beralihlah kembali ke Cloud Shell dan tekan Control+C untuk mengakhiri penerusan port.

Cara alternatif untuk merutekan traffic gRPC

Anda dapat memodifikasi solusi ini dengan beberapa cara agar sesuai dengan lingkungan Anda.

Load balancer lapisan aplikasi alternatif

Beberapa fungsi lapisan aplikasi yang disediakan Envoy juga dapat disediakan oleh solusi load balancing lainnya:

  • Anda dapat menggunakan Load Balancer Aplikasi eksternal global atau Load Balancer Aplikasi eksternal regional, bukan Load Balancer Jaringan passthrough eksternal dan Envoy yang dikelola sendiri. Menggunakan Load Balancer Aplikasi eksternal memberikan beberapa manfaat dibandingkan dengan Load Balancer Jaringan passthrough eksternal, seperti kemampuan pengelolaan traffic lanjutan, sertifikat TLS terkelola, serta integrasi dengan produk Google Cloud lainnya, seperti Cloud CDN, Google Cloud Armor, dan IAP.

    Sebaiknya gunakan Load Balancer Aplikasi eksternal global atau Load Balancer Aplikasi eksternal regional jika kemampuan pengelolaan traffic yang ditawarkannya memenuhi kasus penggunaan Anda, dan jika Anda tidak memerlukan dukungan untuk autentikasi berbasis sertifikat klien, yang juga dikenal sebagai autentikasi TLS mutual (mTLS). Untuk informasi selengkapnya, baca dokumen berikut:

  • Jika menggunakan Anthos Service Mesh atau Istio, Anda dapat menggunakan fitur-fiturnya untuk merutekan dan melakukan load balancing pada traffic gRPC. Anthos Service Mesh dan Istio menyediakan gateway ingress yang di-deploy sebagai Load Balancer Jaringan passthrough eksternal dengan backend Envoy, mirip dengan arsitektur dalam tutorial ini. Perbedaan utamanya adalah Envoy dikonfigurasi melalui objek perutean traffic Istio.

    Agar contoh layanan dalam tutorial ini dapat dirutekan di Anthos Service Mesh atau mesh layanan Istio, Anda harus menghapus baris clusterIP: None dari manifes Service Kubernetes (echo-service.yaml dan reverse-service.yaml). Ini berarti menggunakan fungsi penemuan layanan dan load balancing dari Anthos Service Mesh atau Istio, bukan fungsi serupa di Envoy.

    Jika Anda sudah menggunakan Anthos Service Mesh atau Istio, sebaiknya gunakan gateway ingress untuk merutekan ke layanan gRPC Anda.

  • Anda dapat menggunakan NGINX sebagai pengganti Envoy, baik sebagai Deployment maupun menggunakan NGINX Ingress Controller untuk Kubernetes. Envoy digunakan dalam tutorial ini karena menyediakan fungsi gRPC yang lebih canggih, seperti dukungan untuk protokol health check gRPC.

Konektivitas jaringan VPC internal

Jika ingin mengekspos layanan di luar cluster GKE, tetapi hanya di dalam jaringan VPC, Anda dapat menggunakan Load Balancer Jaringan passthrough internal atau Load Balancer Aplikasi internal.

Untuk menggunakan Load Balancer Jaringan passthrough internal sebagai pengganti Load Balancer Jaringan passthrough eksternal, tambahkan anotasi cloud.google.com/load-balancer-type: "Internal" ke manifes envoy-service.yaml.

Untuk menggunakan Load Balancer Aplikasi internal, lihat dokumentasi tentang cara mengonfigurasi Ingress untuk Load Balancer Aplikasi internal.

Pembersihan

Setelah menyelesaikan tutorial, Anda dapat membersihkan resource yang dibuat agar resource tersebut berhenti menggunakan kuota dan dikenai biaya. Bagian berikut menjelaskan cara menghapus atau menonaktifkan resource ini.

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

Jika ingin menyimpan project Google Cloud yang digunakan dalam tutorial ini, hapus setiap resource:

  1. Di Cloud Shell, hapus clone repositori Git lokal:

    cd ; rm -rf ~/grpc-gke-nlb-tutorial
    
  2. Hapus cluster GKE:

    gcloud container clusters delete envoy-grpc-tutorial \
        --zone us-central1-f --async --quiet
    
  3. Hapus repositori di Artifact Registry:

    gcloud artifacts repositories delete envoy-grpc-tutorial-images \
        --location us-central1 --async --quiet
    

Langkah selanjutnya