WebAssembly for Proxies adalah spesifikasi baru yang memungkinkan pengembang menulis plug-in portabel menggunakan WebAssembly (Wasm). Plug-in ini dapat dijalankan pada berbagai server proxy. Service Mesh (ASM) mendukung spesifikasi WebAssembly for Proxies. Topik ini menjelaskan cara menulis plug-in Wasm dalam Go untuk proxy Envoy di ASM.
Prasyarat
Sebuah kluster telah ditambahkan ke instans ASM dengan versi 1.18 atau lebih baru. Untuk informasi selengkapnya tentang cara menambahkan kluster ke instans ASM, lihat Add a cluster to an ASM instance.
Injeksi proxy sidecar otomatis telah diaktifkan. Untuk informasi selengkapnya, lihat Configure sidecar injection policies.
Gerbang masuk (ingress gateway) telah dideploy. Untuk informasi selengkapnya, lihat Create an ingress gateway.
Aplikasi HTTPBin telah dideploy dan dapat diakses. Untuk informasi selengkapnya tentang cara deploy aplikasi HTTPBin, lihat Deploy the HTTPBin application.
Instans Container Registry Enterprise Edition telah dibuat. Instans Container Registry Enterprise Edition mendukung gambar Open Container Initiative (OCI). Untuk informasi selengkapnya, lihat Create an Enterprise Edition instance.
Informasi latar belakang
Wasm adalah format biner portabel yang sedang berkembang untuk kode yang dapat dieksekusi. Kode tersebut dieksekusi dengan kecepatan hampir setara native di dalam sandbox yang aman dari segi memori (bagi host). Sandbox tersebut memiliki batasan sumber daya yang jelas dan menyediakan API terdefinisi dengan baik untuk berkomunikasi dengan lingkungan host penyematannya (dalam hal ini merujuk pada proxy).
Plug-in Wasm memberikan manfaat berikut:
Kelincahan: Anda dapat memperbarui plug-in tanpa me-restart proxy Envoy sehingga permintaan tetap dapat ditangani sebagaimana mestinya.
Keandalan dan isolasi: Karena plug-in dideploy di dalam sandbox dengan batasan sumber daya, mereka dapat mengalami crash tanpa membuat proxy Envoy mati.
Keamanan: Karena plug-in dideploy di dalam sandbox dengan API terdefinisi dengan baik untuk berkomunikasi dengan proxy, mereka dikendalikan secara ketat.
Keanekaragaman: Plug-in dapat ditulis dalam berbagai bahasa pemrograman, seperti C++, Go, dan Rust.
Untuk informasi selengkapnya tentang plug-in Wasm, lihat WebAssembly-in-Envoy.md, dan OVERVIEW.md.
Contoh konfigurasi
Pada contoh ini, sebuah plug-in Wasm ditulis dalam Go. Setelah plug-in ditulis, file biner Wasm dihasilkan, lalu dikemas ke dalam gambar. Gambar tersebut harus diunggah ke repositori gambar OCI. Setelah gambar diunggah, konfigurasikan resource WasmPlugin di ASM dan terapkan plug-in tersebut ke proxy Envoy yang ditentukan.
Pada contoh ini, sebuah plug-in dikembangkan untuk memeriksa apakah permintaan berisi header allow: true. Jika tidak, kode status 403 dan isi respons tertentu akan dikembalikan. Jika ya, aplikasi HTTPBin dapat diakses sebagaimana mestinya.
Langkah 1: Siapkan lingkungan pengembangan
Untuk mengembangkan plug-in Wasm dalam Go untuk proxy Envoy, Anda harus menginstal alat-alat berikut terlebih dahulu:
Go: Kompilator Go dan alat terkait digunakan untuk menulis proyek Go. Untuk informasi selengkapnya, lihat The Go Programming Language.
Docker: Pada contoh ini, Docker digunakan untuk membangun dan mendorong gambar OCI.
TinyGo: Meskipun Go digunakan untuk menulis plug-in Wasm, kompilator Go resmi tidak dapat mengompilasi kode Go ke format Wasm. Anda harus menggunakan TinyGo. Untuk informasi selengkapnya tentang cara menginstal TinyGo, lihat Quick install guide.
Untuk informasi selengkapnya tentang SDK yang menjadi dependensi plug-in Wasm, lihat proxy-wasm-go-sdk di situs GitHub. Anda dapat menemukan kode lengkap SDK Go untuk Proxy-Wasm di situs tersebut. Jika ingin menggunakan SDK lain, rujuklah kode SDK Go untuk Proxy-Wasm.
Langkah 2: Tulis kode plug-in
-
Buat folder dan buat file main.go yang berisi konten berikut:
Jalankan perintah berikut di folder yang telah dibuat untuk mendapatkan dependensi SDK:
go mod init go mod tidyJalankan perintah berikut untuk mengompilasi kode menjadi file biner Wasm:
tinygo build -o plugin.wasm -scheduler=none -target=wasi main.goFile plugin.wasm dihasilkan. File ini merupakan file eksekusi biner Wasm.
Langkah 3: Buat gambar OCI dari plug-in Wasm dan dorong ke instans Container Registry Enterprise Edition
Di folder yang dibuat pada Langkah 2, buat file Dockerfile yang berisi konten berikut:
FROM scratch ADD ./plugin.wasm ./plugin.wasmJalankan perintah berikut untuk membuat gambar:
docker build -t header-authorization:v0.0.1 .-
Buat repositori gambar. Untuk informasi selengkapnya, lihat langkah-langkah 2.a dan 2.b pada Langkah 1 dalam topik Implement a WAF on an ASM gateway with the Coraza Wasm plugin.
Pada contoh ini, namespace adalah
test-ocidan nama repositorinya adalahheader-authorization. Gambar berikut menunjukkan repositori yang telah dibuat.Pada halaman detail repositori, di bagian Image Guide, bagian Push image to the Registry menyediakan perintah untuk login ke instans Registry dengan
docker login, memberi tag gambar dengandocker tag [ImageId] <registry-url>/<namespace>/<repository>:[image-version], dan mendorong gambar dengandocker push <registry-url>/<namespace>/<repository>:[image-version]. Ganti[ImageId]dan[image-version]dengan nilai aktual.Untuk informasi selengkapnya tentang cara mendorong gambar ke instans Container Registry Enterprise Edition, lihat Push image to the registry pada gambar di atas.
Langkah 4: Terapkan plug-in Wasm ke gerbang masuk (ingress gateway)
Konfigurasikan izin untuk menarik gambar. Untuk informasi selengkapnya, lihat Step 2: Configure permissions to pull images.
Jalankan perintah berikut untuk membuat Secret bernama
wasm-secret:kubectl create secret docker-registry -n istio-system wasm-secret --docker-server=${Domain name of the Container Registry Enterprise Edition instance} --docker-username =${Username} --docker-password =${Password}Buat file asm-plugin.yaml yang berisi konten berikut:
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://${Domain name of the Container Registry Enterprise Edition instance}/test-oci/header-authorization:v0.0.1 phase: AUTHNGunakan kubectl untuk terhubung ke instans ASM berdasarkan informasi dalam file kubeconfig. Kemudian, jalankan perintah berikut untuk menerapkan plug-in Wasm ke instans ASM:
kubectl apply -f wasm-plugin.yaml
Langkah 5: Verifikasi bahwa plug-in Wasm berlaku
Gunakan file kubeconfig dari kluster pada bidang data tempat gerbang masuk berada dan jalankan perintah berikut untuk mengaktifkan fitur logging debug untuk plug-in Wasm yang diterapkan pada gerbang masuk:
kubectl -n istio-system exec ${Name of the pod where the ingress gateway resides} -c istio-proxy -- curl -XPOST "localhost:15000/logging?wasm=debug"Jalankan perintah berikut untuk mengakses aplikasi HTTPBin yang diekspos melalui gerbang masuk:
curl ${IP address of the ingress gateway}/status/418Output yang diharapkan:
Forbidden by ASM Wasm PluginLihat log Pod tempat gerbang masuk berada.
Contoh log:
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' is , only true can passthrough 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"}-
Jalankan perintah berikut untuk mengakses aplikasi HTTPBin yang diekspos melalui gerbang masuk:
curl ${IP address of the ingress gateway}/status/418 -H "allow: true"Output yang diharapkan:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`Output tersebut menunjukkan bahwa aplikasi HTTPBin dapat diakses sebagaimana mestinya.
Memory leak pada TinyGo
Terjadi memory leak pada plug-in Wasm untuk proxy Envoy yang dikompilasi menggunakan TinyGo. Komunitas proxy-wasm-go-sdk merekomendasikan agar Anda menggunakan nottinygc untuk optimasi kompilasi. Lakukan langkah-langkah berikut untuk menggunakan nottinygc dalam optimasi kompilasi:
Tambahkan kode
importberikut ke awal file main.go:import _ "github.com/wasilibs/nottinygc"Jika dependensi tidak ditemukan, Anda dapat menjalankan perintah
go mod tidyuntuk mengunduh dependensi secara otomatis.Jalankan perintah berikut untuk mengompilasi kode:
tinygo build -o plugin.wasm -gc=custom -tags='custommalloc nottinygc_envoy' -target=wasi -scheduler=none main.goPerintah di atas mengatur parameter
-gcdan-tags. Untuk informasi selengkapnya, lihat nottinygc.