All Products
Search
Document Center

Alibaba Cloud Service Mesh:Tulis plug-in Wasm dalam Rust untuk proxy Envoy di ASM

Last Updated:Mar 11, 2026

Service Mesh (ASM) mendukung plug-in Wasm di proxy Envoy untuk pemrosesan permintaan kustom. Tutorial ini memandu Anda menulis plug-in Wasm dalam Rust yang memeriksa header permintaan HTTP dan mengizinkan atau memblokir permintaan berdasarkan hasil pemeriksaan tersebut.

Plug-in ini memeriksa apakah permintaan masuk berisi header allow: true. Jika header tidak ada atau diatur ke nilai lain, plug-in mengembalikan HTTP 403 dengan pesan error kustom. Jika header tersebut ada dan diatur ke true, permintaan diteruskan ke layanan hulu (upstream service).

Cara kerja

Plug-in Wasm berjalan di dalam proxy Envoy sebagai modul sandbox. Spesifikasi Proxy-Wasm mendefinisikan Application Binary Interface (ABI) standar untuk komunikasi antara host proxy dan modul Wasm. Karena Proxy-Wasm bersifat agnostik terhadap proxy, plug-in yang dibangun berdasarkan ABI ini dapat digunakan lintas proxy apa pun yang menerapkan spesifikasi tersebut.

Proxy-Wasm Rust SDK mengorganisasi logika plug-in di sekitar tiga jenis trait:

TraitPeran
RootContextMengelola siklus hidup dan konfigurasi plug-in. Membuat konteks HTTP atau stream baru untuk setiap permintaan.
HttpContextMenangani satu siklus permintaan/tanggapan HTTP. Implementasikan callback seperti on_http_request_headers untuk memeriksa atau memodifikasi traffic.
ContextMenyediakan fungsi utilitas bersama (akses properti, pengatur waktu, dan lainnya) yang diwariskan oleh konteks root maupun HTTP.

Saat Envoy menerima permintaan HTTP, Envoy membuat instans HttpContext baru melalui RootContext. Callback HttpContext dipicu pada setiap tahap pemrosesan permintaan, memberikan plug-in kontrol penuh atas header, body, dan trailer.

Informasi latar belakang

Wasm menyediakan performa eksekusi mendekati native dan berjalan dalam sandbox yang aman dari segi memori, sehingga sangat cocok untuk memperluas Envoy tanpa perlu mengompilasi ulang binari proxy. Namun, bahasa pemrograman yang memiliki garbage collection bawaan dapat menimbulkan overhead performa dalam Wasm. Oleh karena itu, bahasa dengan manajemen memori manual—seperti C++ dan Rust—merupakan pilihan yang direkomendasikan.

Dibandingkan C++, Rust menawarkan alur kerja kompilasi dan build yang lebih sederhana, meskipun memiliki kurva pembelajaran yang lebih curam. Pilih berdasarkan keakraban tim Anda dengan masing-masing bahasa.

Prasyarat

Sebelum memulai, pastikan Anda telah:

Ikhtisar alur kerja

Proses end-to-end terdiri dari lima langkah:

  1. Siapkan lingkungan pengembangan — Instal rantai alat Rust dan target kompilasi Wasm.

  2. Tulis plug-in — Buat proyek library Rust, definisikan dependensi, dan implementasikan logika pemeriksaan header permintaan.

  3. Build dan paket — Kompilasi kode Rust menjadi binari Wasm dan kemas sebagai image OCI.

  4. Deploy — Dorong image ke Container Registry dan terapkan resource plug-in Wasm di ASM.

  5. Verifikasi — Kirim permintaan uji untuk memastikan plug-in memblokir dan mengizinkan traffic sesuai harapan.

Langkah 1: Siapkan lingkungan pengembangan

  1. Instal rantai alat Rust melalui rustup. Untuk instruksi, lihat Instal Rust.

  2. Tambahkan target kompilasi wasm32-wasi: Target wasm32-wasi mengompilasi kode Rust ke WebAssembly dengan akses ke antarmuka sistem WASI, yang diharapkan oleh runtime Wasm Envoy. Jika Rust sudah terinstal, perbarui terlebih dahulu:

       rustup target add wasm32-wasi
       rustup update

Langkah 2: Tulis plug-in

Langkah ini mencakup tiga bagian: membuat proyek, mengonfigurasi dependensi, dan mengimplementasikan logika plug-in.

Buat proyek

Buat direktori bernama rust-example, masuk ke direktori tersebut, lalu inisialisasi library Rust baru:

mkdir rust-example && cd rust-example
cargo init --lib

Konfigurasikan dependensi

Ganti isi file Cargo.toml dengan berikut ini:

[package]
name = "rust-example"
version = "0.1.0"
edition = "2021"

[lib]
# Build sebagai dynamic library yang kompatibel dengan C agar Envoy dapat memuatnya
crate-type = ["cdylib"]

[dependencies]
log = "0.4.8"
proxy-wasm = "0.2.2"

Jenis crate cdylib menghasilkan dynamic library yang kompatibel dengan runtime Wasm. Dua dependensi tersebut adalah:

  • log — Fasad logging standar Rust untuk output log terstruktur.

  • proxy-wasm — Proxy-Wasm Rust SDK, yang menyediakan definisi trait dan binding fungsi host.

Implementasikan logika plug-in

Plug-in perlu:

  1. Mendaftarkan RootContext yang memberi tahu Envoy bahwa plug-in ini menangani traffic HTTP.

  2. Untuk setiap permintaan HTTP masuk, membuat HttpContext yang memeriksa header permintaan.

  3. Pada callback on_http_request_headers, periksa header allow: true. Blokir permintaan dengan HTTP 403 jika header tidak ada, atau izinkan jika ada.

Ganti isi file src/lib.rs dengan:

use log::info;
use proxy_wasm::traits::*;
use proxy_wasm::types::*;

proxy_wasm::main! {{
    proxy_wasm::set_log_level(LogLevel::Trace);
    proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(HttpHeadersRoot) });
}}

struct HttpHeadersRoot;

// Warisi fungsi utilitas bersama (akses properti, pengatur waktu, dll.)
impl Context for HttpHeadersRoot {}

impl RootContext for HttpHeadersRoot {
    fn get_type(&self) -> Option<ContextType> {
        Some(ContextType::HttpContext)
    }

    fn create_http_context(&self, context_id: u32) -> Option<Box<dyn HttpContext>> {
        Some(Box::new(HttpHeaders { context_id }))
    }
}

struct HttpHeaders {
    context_id: u32,
}

impl Context for HttpHeaders {}

impl HttpContext for HttpHeaders {
    fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
        info!("#{} wasm-rust: on_http_request_headers", self.context_id);

        match self.get_http_request_header("allow") {
            Some(allow) if allow == "true" => {
                Action::Continue
            }
            _ => {
                info!("#{} wasm-rust: allow header not found or is not true, deny by default", self.context_id);
                self.send_http_response(
                    403,
                    vec![("Content-Type", "text/plain")],
                    Some(b"Forbidden by ASM Wasm Plugin, rust version\n"),
                );
                Action::Pause
            }
        }
    }
}

Penjelasan kode:

BagianTujuan
proxy_wasm::main!Makro titik masuk. Mengatur tingkat log ke Trace dan mendaftarkan HttpHeadersRoot sebagai konteks root.
HttpHeadersRoot + RootContextMengembalikan ContextType::HttpContext untuk memberi tahu Envoy bahwa plug-in ini memproses traffic HTTP. Membuat instans HttpHeaders baru untuk setiap permintaan.
HttpHeaders + HttpContextMengimplementasikan on_http_request_headers. Membaca header allow: mengembalikan Action::Continue jika nilainya "true", jika tidak mengirim respons HTTP 403 dan mengembalikan Action::Pause untuk menghentikan permintaan.

Kompilasi plug-in

Build plug-in dengan target wasm32-wasi:

cargo build --target wasm32-wasi --release

Setelah build berhasil, binari Wasm tersedia di:

target/wasm32-wasi/release/rust_example.wasm

Langkah 3: Build image OCI dan dorong ke Container Registry

Kemas binari Wasm sebagai image OCI agar ASM dapat menarik dan memuatnya.

  1. Buat file Dockerfile di root proyek:

       FROM scratch
       # Salin binari Wasm yang telah dikompilasi ke dalam image sebagai plugin.wasm
       ADD target/wasm32-wasi/release/rust_example.wasm ./plugin.wasm
  2. Build dan dorong image tersebut. Untuk langkah lengkap, lihat Buat image OCI dari plug-in Wasm dan dorong ke instans Container Registry Enterprise Edition. Ganti <your-registry> dan <tag> dengan alamat registry dan tag image Anda:

       docker build -t <your-registry>/wasm-rust-example:<tag> .
       docker push <your-registry>/wasm-rust-example:<tag>

Langkah 4: Terapkan plug-in Wasm ke gerbang masuk

Konfigurasikan resource WasmPlugin di ASM untuk memuat plug-in ke proxy Envoy pada gerbang masuk.

Untuk prosedur lengkap, lihat Terapkan plug-in Wasm ke gerbang masuk. Pastikan field url mengarah ke image yang telah Anda dorong pada Langkah 3.

Langkah 5: Verifikasi plug-in

Setelah plug-in dideploy, uji dengan mengirim permintaan yang menyertakan dan tidak menyertakan header allow: true.

Aktifkan logging debug

Gunakan kubeconfig kluster bidang data untuk mengaktifkan log debug Wasm pada Pod gerbang:

kubectl -n istio-system exec <gateway-pod-name> -c istio-proxy -- \
  curl -XPOST "localhost:15000/logging?wasm=debug"

Ganti <gateway-pod-name> dengan nama aktual Pod gerbang Anda.

Uji tanpa header allow

Kirim permintaan tanpa header allow:

curl <ASM-gateway-IP>/status/418

Output yang diharapkan:

Forbidden by ASM Wasm Plugin, rust version

Plug-in memblokir permintaan dan mengembalikan HTTP 403.

Periksa log gerbang

Periksa log Pod gerbang untuk entri seperti berikut:

2024-09-05T08:33:31.079869Z  info  envoy wasm  wasm log istio-system.header-authorization: #2 wasm-rust: on_http_request_headers
2024-09-05T08:33:31.079943Z  info  envoy wasm  wasm log istio-system.header-authorization: #2 wasm-rust: allow header not found or is not true, deny by default
{"authority_for":"xx.xx.xx.xx","bytes_received":"0","bytes_sent":"43","downstream_local_address":"xx.xx.xx.xx:80","downstream_remote_address":"xx.xx.xx.xx:xxxxx","duration":"0","istio_policy_status":"-","method":"GET","path":"/status/418","protocol":"HTTP/1.1","request_id":"d5250d1a-54b3-406d-8bea-5a51b617b579","requested_server_name":"-","response_code":"403","response_flags":"-","route_name":"httpbin","start_time":"2024-09-05T08:33:31.079Z","trace_id":"-","upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local","upstream_host":"-","upstream_local_address":"-","upstream_response_time":"-","upstream_service_time":"-","upstream_transport_failure_reason":"-","user_agent":"curl/8.9.0-DEV","x_forwarded_for":"xx.xx.xx.xx"}

Baris log ini mengonfirmasi bahwa plug-in telah dieksekusi dan menolak permintaan.

Uji dengan header allow

Kirim permintaan dengan allow: true:

curl <ASM-gateway-IP>/status/418 -H "allow: true"

Output yang diharapkan:

    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`

Permintaan diteruskan ke HTTPBin, yang mengembalikan respons teapot HTTP 418 standar. Plug-in berfungsi dengan benar.

Langkah berikutnya

  • Untuk menulis plug-in Wasm dalam Go, lihat versi tutorial ini untuk Go.

  • Jelajahi lebih banyak contoh plug-in di repositori proxy-wasm Rust SDK, termasuk modifikasi body respons HTTP, pemuatan konfigurasi, dan autentikasi gRPC.