Tüm Ürünler
Search
Belge Merkezi

Alibaba Cloud Service Mesh:Write a Wasm plug-in in Rust for an Envoy proxy in ASM

Son Güncelleme:Oct 07, 2026

Service Mesh (ASM), özel istek işleme amacıyla Envoy sunucularında Wasm eklentilerini destekler. Bu öğretici, HTTP istek başlıklarını inceleyen ve sonuca göre isteklere izin veren ya da bunları engelleyen bir Wasm eklentisinin Rust dilinde nasıl yazılacağını adım adım açıklar.

Eklenti, gelen bir isteğin allow: true başlığını içerip içermediğini kontrol eder. Başlık eksikse veya başka bir değere ayarlanmışsa eklenti, özel bir hata mesajıyla birlikte HTTP 403 durumu döndürür. Başlık mevcut ve true olarak ayarlanmışsa istek upstream hizmetine iletilir.

Nasıl çalışır

Wasm eklentisi, Envoy sunucusu içinde yalıtılmış bir modül olarak çalışır. Proxy-Wasm belirtimi, sunucu ana makinesi ile Wasm modülleri arasındaki iletişim için standart bir Application Binary Interface (ABI) tanımlar. Proxy-Wasm sunucudan bağımsız olduğundan bu ABI'ye göre oluşturulan eklentiler, belirtimi uygulayan herhangi bir sunucuda taşınabilir.

Proxy-Wasm Rust SDK'sı, eklenti mantığını üç trait türü etrafında düzenler:

Trait Rolü
RootContext Eklentinin yaşam döngüsünü ve yapılandırmasını yönetir. Her istek için yeni HTTP veya akış bağlamları oluşturur.
HttpContext Tek bir HTTP istek/yanıt döngüsünü işler. Trafiği incelemek veya değiştirmek için on_http_request_headers gibi geri aramaları uygulayın.
Context Hem kök hem de HTTP bağlamlarının devraldığı paylaşılan yardımcı işlevleri (özellik erişimi, zamanlayıcılar vb.) sağlar.

Envoy bir HTTP isteği aldığında RootContext aracılığıyla yeni bir HttpContext örneği oluşturur. HttpContext geri aramaları, istek işlemenin her aşamasında tetiklenerek eklentinin başlıklar, gövde ve altbilgiler üzerinde tam kontrol sahibi olmasını sağlar.

Arka plan bilgileri

Wasm, neredeyse yerel düzeyde yürütme performansı sunar ve bellek açısından güvenli bir yalıtılmış alanda çalışır; bu durum, sunucu ikili dosyasını yeniden derlemeye gerek kalmadan Envoy'u genişletmek için uygun hale getirir. Ancak, yerleşik çöp toplama özelliğine sahip diller Wasm ortamında performans ek yüküne neden olabilir. Bu nedenle manuel bellek yönetimi sunan C++ ve Rust dilleri önerilir.

Rust, C++ ile karşılaştırıldığında daha basit bir derleme ve oluşturma iş akışı sunar ancak öğrenme eğrisi daha dik olabilir. Seçiminizi ekibinizin ilgili dillere olan aşinalığına göre yapın.

Ön koşullar

Başlamadan önce aşağıdaki ön koşulları sağladığınızdan emin olun:

İş akışı genel bakış

Uçtan uca süreç beş adımdan oluşur:

  1. Geliştirme ortamını hazırlayın: Rust araç zincirini ve Wasm derleme hedefini yükleyin.

  2. Eklentiyi yazın: Bir Rust kitaplığı projesi oluşturun, bağımlılıkları tanımlayın ve istek başlığı inceleme mantığını uygulayın.

  3. Derleyin ve paketleyin: Rust kodunu bir Wasm ikili dosyasına derleyin ve bunu bir OCI görüntüsü olarak paketleyin.

  4. Dağıtın: Görüntüyü Container Registry'ye gönderin ve ASM'de Wasm eklentisi kaynağını uygulayın.

  5. Doğrulayın: Eklentinin trafiği beklendiği şekilde engellediğini ve izin verdiğini onaylamak için test istekleri gönderin.

Adım 1: Geliştirme ortamını hazırlayın

  1. Rust araç zincirini rustup üzerinden yükleyin. Talimatlar için bkz. Rust yükleme.

  2. wasm32-wasi derleme hedefini ekleyin: wasm32-wasi hedefi, Rust kodunu Envoy'un Wasm çalışma zamanının beklediği WASI sistem arayüzüne erişim sağlayan WebAssembly'e derler. Rust zaten yüklüyse önce güncelleyin:

       rustup target add wasm32-wasi
       rustup update

Adım 2: Eklentiyi yazın

Bu adım üç bölümü kapsar: projeyi oluşturma, bağımlılıkları yapılandırma ve eklenti mantığını uygulama.

Projeyi oluşturun

rust-example adında bir dizin oluşturun, bu dizine geçin ve yeni bir Rust kitaplığı başlatın:

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

Bağımlılıkları yapılandırın

Cargo.toml dosyasının içeriğini aşağıdakilerle değiştirin:

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

[lib]
# Build as a C-compatible dynamic library so Envoy can load it
crate-type = ["cdylib"]

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

cdylib crate türü, Wasm çalışma zamanıyla uyumlu bir dinamik kitaplık üretir. İki bağımlılık şunlardır:

  • **log**: Yapılandırılmış günlük çıkışı için standart Rust günlük kaydı arabirimi.

  • **proxy-wasm**: Trait tanımlamalarını ve ana makine işlevi bağlamalarını sağlayan Proxy-Wasm Rust SDK'sı.

Eklenti mantığını uygulayın

Eklentinin aşağıdaki görevleri yerine getirmesi gerekir:

  1. Envoy'a bu eklentinin HTTP trafiğini işlediğini bildiren bir RootContext kaydedin.

  2. Gelen her HTTP isteği için istek başlıklarını inceleyen bir HttpContext oluşturun.

  3. on_http_request_headers geri çağrısında allow: true başlığını kontrol edin. Başlık eksikse isteği HTTP 403 ile engelleyin, mevcutsa geçmesine izin verin.

src/lib.rs dosyasının içeriğini aşağıdakilerle değiştirin:

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;

// Inherit shared utility functions (property access, timers, etc.)
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
            }
        }
    }
}

Kodun dökümü aşağıdaki gibidir:

Bölüm Amacı
proxy_wasm::main! Giriş noktası makrosu. Günlük düzeyini Trace olarak ayarlar ve HttpHeadersRoot öğesini kök bağlam olarak kaydeder.
HttpHeadersRoot + RootContext Envoy'a bu eklentinin HTTP trafiğini işlediğini bildirmek için ContextType::HttpContext döndürür. Her istek için yeni bir HttpHeaders örneği oluşturur.
HttpHeaders + HttpContext on_http_request_headers yöntemini uygular. allow başlığını okur: değer "true" ise Action::Continue döndürür, aksi takdirde bir HTTP 403 yanıtı gönderir ve isteği durdurmak için Action::Pause döndürür.

Eklentiyi derleyin

Eklentiyi wasm32-wasi hedefiyle derleyin:

cargo build --target wasm32-wasi --release

Başarılı bir derlemeden sonra Wasm ikili dosyası şu konumda bulunur:

target/wasm32-wasi/release/rust_example.wasm

Adım 3: Bir OCI görüntüsü oluşturun ve Container Registry'ye gönderin

ASM'nin görüntüyü çekip yükleyebilmesi için Wasm ikili dosyasını bir OCI görüntüsü olarak paketleyin.

  1. Proje kökünde bir Dockerfile oluşturun:

       FROM scratch
       # Copy the compiled Wasm binary into the image as plugin.wasm
       ADD target/wasm32-wasi/release/rust_example.wasm ./plugin.wasm
  2. Görüntüyü derleyin ve gönderin. Ayrıntılı adımlar için bkz. Wasm eklentisinin OCI görüntüsünü oluşturma ve Container Registry Enterprise Edition örneğine gönderme. <your-registry> ve <tag> yerine gerçek kayıt defteri adresinizi ve görüntü etiketinizi girin:

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

Adım 4: Wasm eklentisini ingress gateway'e uygulayın

Eklentiyi ingress gateway'in Envoy sunucusuna yüklemek için ASM'de WasmPlugin kaynağını yapılandırın.

Tam prosedür için bkz. Wasm eklentisini ingress gateway'e uygulama. url alanının 3. Adımda gönderdiğiniz görüntüyü işaret ettiğinden emin olun.

Adım 5: Eklentiyi doğrulayın

Eklentiyi dağıttıktan sonra allow: true başlığı içeren ve içermeyen istekler göndererek testi gerçekleştirin.

Hata ayıklama günlüğünü etkinleştirin

Gateway Pod'unda Wasm hata ayıklama günlüklerini etkinleştirmek için veri düzlemi kümesinin kubeconfig dosyasını kullanın:

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

<gateway-pod-name> yerine gateway Pod'unuzun gerçek adını girin.

Allow başlığı olmadan test edin

allow başlığı olmadan bir istek gönderin:

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

Beklenen çıktı:

Forbidden by ASM Wasm Plugin, rust version

Eklenti isteği engeller ve HTTP 403 döndürür.

Gateway günlüklerini kontrol edin

Aşağıdakine benzer girişler için gateway Pod günlüklerini inceleyin:

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"}

Bu günlük satırları, eklentinin yürütüldüğünü ve isteği reddettiğini doğrular.

Allow başlığı ile test edin

allow: true içeren bir istek gönderin:

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

Beklenen çıktı:

    -=[ teapot ]=-

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

İstek, standart HTTP 418 çaydanlık yanıtını döndüren HTTPBin'e iletilir. Eklenti doğru şekilde çalışmaktadır.

Sonraki adımlar

  • Go diliyle bir Wasm eklentisi yazmak için bu öğreticinin Go sürümüne bakın.

  • HTTP yanıt gövdesi değişikliği, yapılandırma yükleme ve gRPC kimlik doğrulama dahil olmak üzere proxy-wasm Rust SDK deposundaki diğer eklenti örneklerini keşfedin.