Service Mesh (ASM) mendukung spesifikasi WebAssembly for Proxies, yang memungkinkan Anda memperluas perilaku proxy Envoy dengan plug-in portabel yang dikompilasi ke WebAssembly (Wasm). Plug-in ini dapat berjalan di berbagai server proxy, dieksekusi dalam sandbox yang aman secara memori dengan kecepatan mendekati native, serta dapat diperbarui tanpa perlu me-restart proxy.
Topik ini menjelaskan langkah-langkah untuk membuat plug-in Wasm berbasis Go yang menerapkan otorisasi berbasis header, mengemasnya sebagai image Open Container Initiative (OCI), dan men-deploy-nya ke gerbang masuk ASM.
Cara kerja plug-in Wasm di Envoy
Plug-in Wasm dieksekusi di dalam lingkungan sandbox dengan API terdefinisi dengan baik untuk berkomunikasi dengan host proxy. Arsitektur ini memberikan beberapa manfaat:
| Manfaat | Deskripsi |
|---|---|
| Hot-reloadable | Perbarui plug-in tanpa me-restart proxy Envoy, sehingga traffic tetap mengalir |
| Fault-isolated | Keruntuhan plug-in tidak menyebabkan proxy Envoy down |
| Secure | Sandbox membatasi kemampuan plug-in hanya pada permukaan API yang terdefinisi dengan baik |
| Polyglot | Tulis plug-in dalam C++, Go, dan Rust |
Untuk detail lebih lanjut, lihat WebAssembly in Envoy, dan ikhtisar proxy-wasm-go-sdk.
Alur kerja end-to-end
Plug-in yang Anda buat dalam tutorial ini memeriksa apakah permintaan masuk berisi header allow: true. Permintaan tanpa header ini akan menerima tanggapan 403 Forbidden, sedangkan permintaan dengan header tersebut diteruskan ke layanan backend.
Tulis logika plug-in dalam Go menggunakan proxy-wasm-go-sdk.
Kompilasi kode Go menjadi binary Wasm dengan TinyGo.
Kemas binary tersebut sebagai image OCI dan dorong ke Container Registry Enterprise Edition.
Buat resource
WasmPlugindi ASM untuk menerapkan plug-in ke proxy Envoy.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Instans ASM (v1.18 atau lebih baru) dengan kluster yang ditambahkan. Lihat Tambahkan kluster ke instans ASM.
Injeksi sidecar proxy otomatis diaktifkan. Lihat Konfigurasikan kebijakan injeksi sidecar proxy.
Gerbang masuk yang telah di-deploy. Lihat Buat gerbang masuk.
Aplikasi HTTPBin yang telah di-deploy dan dapat diakses. Lihat Deploy aplikasi HTTPBin.
Instans Container Registry Enterprise Edition yang telah dibuat (diperlukan untuk dukungan image OCI). Lihat Buat instans Container Registry Enterprise Edition.
Langkah 1: Siapkan lingkungan pengembangan
Instal tool berikut di mesin lokal Anda:
| Tool | Tujuan | Referensi |
|---|---|---|
| Go | Kompilator dan rantai alat Go | go.dev |
| Docker | Bangun dan dorong image OCI | docker.com |
| TinyGo | Kompilasi Go ke Wasm (kompilator Go standar tidak mendukung output Wasm) | Panduan instalasi TinyGo |
Plug-in ini bergantung pada proxy-wasm-go-sdk, yang menyediakan API SDK Go lengkap beserta contoh tambahan.
Langkah 2: Tulis kode plug-in
Buat direktori proyek dan tambahkan file
main.godengan konten berikut:Inisialisasi modul Go dan unduh dependensi:
go mod init go mod tidyKompilasi kode menjadi binary Wasm. Perintah ini menghasilkan file
plugin.wasmdi direktori saat ini.tinygo build -o plugin.wasm -scheduler=none -target=wasi main.go
Langkah 3: Kemas dan dorong image OCI
Di direktori proyek yang sama, buat
Dockerfile:FROM scratch ADD ./plugin.wasm ./plugin.wasmBangun image:
docker build -t header-authorization:v0.0.1 .Buat repository image di Container Registry Enterprise Edition. Untuk langkah-langkah detail, lihat sublangkah 2.a dan 2.b Langkah 1 dalam Gunakan plug-in Wasm Coraza untuk menerapkan kemampuan WAF pada gerbang ASM. Dalam contoh ini, namespace adalah
test-ocidan nama repository adalahheader-authorization.
Beri tag dan dorong image ke instans Container Registry Enterprise Edition Anda. Ikuti instruksi Push image to the registry yang ditampilkan di halaman detail repository.
Langkah 4: Terapkan plug-in Wasm ke gerbang masuk
Buat Secret untuk menarik image. Untuk latar belakangnya, lihat Langkah 2: Konfigurasikan izin untuk menarik image. Ganti placeholder berikut dengan nilai aktual Anda:
Placeholder Deskripsi <your-registry-domain>Nama domain instans Container Registry Enterprise Edition <your-username>Username registri <your-password>Password registri kubectl create secret docker-registry -n istio-system wasm-secret \ --docker-server=<your-registry-domain> \ --docker-username=<your-username> \ --docker-password=<your-password>Buat file bernama
asm-plugin.yamldengan konten berikut. Ganti<your-registry-domain>dengan nama domain instans Container Registry Enterprise Edition Anda.apiVersion: extensions.istio.io/v1alpha1 kind: WasmPlugin metadata: name: header-authorization namespace: istio-system spec: imagePullPolicy: IfNotPresent imagePullSecret: wasm-secret selector: matchLabels: istio: ingressgateway url: oci://<your-registry-domain>/test-oci/header-authorization:v0.0.1 phase: AUTHNSambungkan ke instans ASM menggunakan file kubeconfig-nya dan terapkan resource tersebut:
kubectl apply -f asm-plugin.yaml
Langkah 5: Verifikasi plug-in
Aktifkan logging debug untuk plug-in Wasm pada gerbang masuk. Gunakan file kubeconfig kluster data-plane tempat gerbang masuk berjalan. Ganti
<ingress-gateway-pod>dengan nama Pod yang menjalankan gerbang masuk.kubectl -n istio-system exec <ingress-gateway-pod> -c istio-proxy -- \ curl -XPOST "localhost:15000/logging?wasm=debug"Kirim permintaan tanpa header
allow. Output yang diharapkan:curl <ingress-gateway-ip>/status/418Forbidden by ASM Wasm PluginPeriksa log Pod gerbang masuk. Entri log ini mengonfirmasi bahwa plug-in memblokir permintaan:
2024-03-08T08:16:46.747394Z debug envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1168 wasm log istio-system.header-authorization: request header: 'allow' adalah , hanya true yang dapat diteruskan thread=24 {"bytes_received":"0","bytes_sent":"28","downstream_local_address":"xxxxxxx","downstream_remote_address":"xxxxxxxx","duration":"0","istio_policy_status":"-","method":"GET","path":"/status/418","protocol":"HTTP/1.1","request_id":"780c8493-13e4-4f97-9771-486efe30347c","requested_server_name":"-","response_code":"403","response_flags":"-","route_name":"httpbin","start_time":"2024-03-08T08:16:46.747Z","trace_id":"-","upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local","upstream_host":"-","upstream_local_address":"-","upstream_service_time":"-","upstream_response_time":"-","upstream_transport_failure_reason":"-","user_agent":"curl/8.4.0","x_forwarded_for":"xxxxxx","authority_for":"xxxxxx"}Kirim permintaan dengan header
allow: true. Output yang diharapkan: Tanggapan teapot mengonfirmasi bahwa aplikasi HTTPBin dapat diakses dan plug-in berfungsi dengan benar.curl <ingress-gateway-ip>/status/418 -H "allow: true"-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`
Perbaiki kebocoran memori TinyGo dengan nottinygc
Plug-in Wasm yang dikompilasi dengan TinyGo mungkin mengalami kebocoran memori. Komunitas proxy-wasm-go-sdk merekomendasikan penggunaan nottinygc sebagai garbage collector kustom untuk mengatasi masalah ini.
Tambahkan import berikut di bagian atas file
main.go. Jika dependensi ini belum tersedia, jalankango mod tidyuntuk mengunduhnya.import _ "github.com/wasilibs/nottinygc"Bangun ulang binary Wasm dengan flag GC kustom. Flag
-gc=custommenggantikan garbage collector default TinyGo dengan nottinygc, dan-tags='custommalloc nottinygc_envoy'mengaktifkan allocator yang dioptimalkan untuk Envoy.tinygo build -o plugin.wasm -gc=custom -tags='custommalloc nottinygc_envoy' \ -target=wasi -scheduler=none main.goBangun ulang image OCI dan dorong versi yang diperbarui ke Container Registry Enterprise Edition, lalu terapkan ulang resource
WasmPluginuntuk menerapkan perbaikan tersebut.