全部产品
Search
文档中心

Alibaba Cloud Service Mesh:Tulis plug-in Wasm dalam Go untuk proxy Envoy

更新时间:Jul 02, 2025

WebAssembly untuk Proxies adalah spesifikasi baru yang memungkinkan pengembang menulis plug-in portabel menggunakan WebAssembly (Wasm). Plug-in ini dapat berjalan pada berbagai server proxy. Service Mesh (ASM) mendukung spesifikasi WebAssembly untuk Proxies. Topik ini menjelaskan cara menulis plug-in Wasm dalam Go untuk proxy Envoy di ASM.

Prasyarat

Informasi latar belakang

Wasm adalah format biner yang sedang berkembang dan portabel untuk kode yang dapat dieksekusi. Kode tersebut dijalankan dengan kecepatan hampir asli dalam sandbox yang aman dari segi memori (untuk host). Sandbox memiliki batasan sumber daya yang jelas dan menyediakan API yang terdefinisi dengan baik untuk berkomunikasi dengan lingkungan host penyematan (di sini mengacu pada proxy).

Plug-in Wasm memberikan manfaat sebagai berikut:

  • Kelincahan: Anda dapat memperbarui plug-in tanpa memulai ulang proxy Envoy, sehingga permintaan dapat ditangani sesuai harapan.

  • Keandalan dan isolasi: Karena plug-in diterapkan di dalam sandbox dengan batasan sumber daya, mereka dapat gagal tanpa membuat proxy Envoy down.

  • Keamanan: Karena plug-in diterapkan di dalam sandbox dengan API yang terdefinisi dengan baik untuk berkomunikasi dengan proxy, mereka dikendalikan dengan baik.

  • Keragaman: Plug-in dapat ditulis dalam beberapa bahasa pemrograman, seperti C++, Go, dan Rust.

Untuk informasi lebih lanjut tentang plug-in Wasm, lihat WebAssembly-in-Envoy.md dan OVERVIEW.md.

Contoh konfigurasi

Dalam contoh ini, sebuah plug-in Wasm ditulis dalam Go. Setelah plug-in selesai ditulis, file biner Wasm dihasilkan, kemudian dikemas menjadi gambar. Gambar tersebut harus diunggah ke repositori gambar OCI. Setelah gambar diunggah, konfigurasikan sumber daya WasmPlugin di ASM dan terapkan plug-in ke proxy Envoy yang ditentukan.

Dalam contoh ini, sebuah plug-in dikembangkan untuk memeriksa apakah permintaan berisi header allow: true. Jika tidak, kode status 403 dan body yang ditentukan akan dikembalikan. Jika ya, aplikasi HTTPBin dapat diakses sesuai harapan.

Langkah 1: Siapkan lingkungan pengembangan

Untuk mengembangkan plug-in Wasm dalam Go untuk proxy Envoy, Anda harus menginstal alat-alat berikut terlebih dahulu:

  • Go: Kompiler Go dan alat terkait digunakan untuk menulis proyek Go. Untuk informasi lebih lanjut, lihat Bahasa Pemrograman Go.

  • Docker: Dalam contoh ini, Docker digunakan untuk membangun dan mendorong gambar OCI.

  • TinyGo: Go digunakan untuk menulis plug-in Wasm. Namun, Anda tidak dapat menggunakan kompiler Go resmi untuk mengompilasi kode Go ke format Wasm. Anda harus menggunakan TinyGo. Untuk informasi lebih lanjut tentang cara menginstal TinyGo, lihat Panduan instalasi cepat.

Untuk informasi lebih lanjut tentang SDK tempat plug-in Wasm bergantung, lihat proxy-wasm-go-sdk di situs web GitHub. Anda dapat menemukan kode lengkap dari Go SDK untuk Proxy-Wasm di situs web tersebut. Jika Anda ingin menggunakan SDK lainnya, rujuklah kode dari Go SDK untuk Proxy-Wasm.

Langkah 2: Tulis kode plug-in

  1. Buat folder dan buat file main.go yang berisi konten berikut:

    Tampilkan file main.go

    package main
    
    import (
    	"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    	"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    )
    
    func main() {
    	proxywasm.SetVMContext(&vmContext{})
    }
    
    type vmContext struct {
    	// Embed the default VM context here,
    	// so that we don't need to reimplement all the methods.
    	types.DefaultVMContext
    }
    
    // Override types.DefaultVMContext.
    func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
    	return &pluginContext{}
    }
    
    type pluginContext struct {
    	// Embed the default plugin context here,
    	// so that we don't need to reimplement all the methods.
    	types.DefaultPluginContext
    }
    
    // Override types.DefaultPluginContext.
    func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
    	return types.OnPluginStartStatusOK
    }
    
    // Override types.DefaultPluginContext.
    func (ctx *pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
    	return &HeaderAuthorizationHandler{}
    }
    
    type HeaderAuthorizationHandler struct {
    	// Embed the default http context here,
    	// so that we don't need to reimplement all the methods.
    	types.DefaultHttpContext
    }
    
    // Override types.DefaultHttpContext.
    func (ctx *HeaderAuthorizationHandler) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
    	// Randomly routing to the canary cluster.
    
    	const AuthorizationKey = "allow"
    	value, err := proxywasm.GetHttpRequestHeader(AuthorizationKey)
    	if err != nil || value != "true" {
    		proxywasm.LogDebugf("request header: 'allow' is %v, only true can passthrough", value)
    		return ctx.DenyRequest()
    	}
    	return types.ActionContinue
    }
    
    func (ctx *HeaderAuthorizationHandler) DenyRequest() types.Action {
    	proxywasm.SendHttpResponse(403, [][2]string{{"Content-Type", "text/plain"}}, []byte("Forbidden by ASM Wasm Plugin"), -1)
    	return types.ActionPause
    }
    
  2. Jalankan perintah berikut di folder yang dibuat untuk mendapatkan dependensi SDK:

    go mod init
    go mod tidy
  3. Jalankan perintah berikut untuk mengompilasi kode menjadi file biner Wasm:

    tinygo build -o plugin.wasm -scheduler=none -target=wasi main.go

    File plugin.wasm dihasilkan. File ini adalah file biner Wasm yang dapat dieksekusi.

Langkah 3: Buat gambar OCI dari plug-in Wasm dan dorong ke instance Container Registry Enterprise Edition

  1. Di folder yang dibuat di Langkah 2, buat file Dockerfile yang berisi konten berikut:

    FROM scratch
    ADD ./plugin.wasm ./plugin.wasm
  2. Jalankan perintah berikut untuk membuat gambar:

    docker build -t header-authorization:v0.0.1 .
  3. Buat repositori gambar. Untuk informasi lebih lanjut, lihat sublangkah 2.a dan 2.b dari Langkah 1 dalam topik Gunakan plug-in Wasm Coraza untuk mengimplementasikan kemampuan WAF pada gateway ASM.

    Dalam contoh ini, namespace adalah test-oci dan nama repositori adalah header-authorization. Gambar berikut menunjukkan repositori yang dibuat.

    image

    Untuk informasi lebih lanjut tentang cara mendorong gambar ke instance Container Registry Enterprise Edition, lihat Dorong gambar ke registri pada gambar sebelumnya.

Langkah 4: Terapkan plug-in Wasm ke gateway masuk

  1. Konfigurasikan izin untuk menarik gambar. Untuk informasi lebih lanjut, lihat Langkah 2: Konfigurasikan izin untuk menarik gambar.

    Jalankan perintah berikut untuk membuat Secret bernama wasm-secret:

    kubectl create secret docker-registry -n istio-system wasm-secret --docker-server=${Nama domain instance Container Registry Enterprise Edition} --docker-username =${Username} --docker-password =${Password}
  2. 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://${Nama domain instance Container Registry Enterprise Edition}/test-oci/header-authorization:v0.0.1
      phase: AUTHN
  3. Gunakan kubectl untuk terhubung ke instance ASM berdasarkan informasi dalam file kubeconfig. Kemudian, jalankan perintah berikut untuk menerapkan plug-in Wasm ke instance ASM:

    kubectl apply -f wasm-plugin.yaml

Langkah 5: Verifikasi bahwa plug-in Wasm berlaku

  1. Gunakan file kubeconfig dari kluster pada bidang data tempat gateway masuk berada dan jalankan perintah berikut untuk mengaktifkan fitur pencatatan debug untuk plug-in Wasm yang diterapkan ke gateway masuk:

    kubectl -n istio-system exec ${Nama pod tempat gateway masuk berada} -c istio-proxy -- curl -XPOST "localhost:15000/logging?wasm=debug"
  2. Jalankan perintah berikut untuk mengakses aplikasi HTTPBin yang diekspos melalui gateway masuk:

    curl ${Alamat IP gateway masuk}/status/418

    Output yang diharapkan:

    Forbidden by ASM Wasm Plugin
  3. Lihat log dari pod tempat gateway 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"}
  4. Jalankan perintah berikut untuk mengakses aplikasi HTTPBin yang diekspos melalui gateway masuk:

    curl ${Alamat IP gateway masuk}/status/418 -H "allow: true"

    Output yang diharapkan:

        -=[ teapot ]=-
    
           _...._
         .'  _ _ `.
        | ."` ^ `". _,
        \_;`"---"`|//
          |       ;/
          \_     _/
            `"""`

    Output tersebut menunjukkan bahwa aplikasi HTTPBin dapat diakses sesuai harapan.

Kebocoran memori di TinyGo

Kebocoran memori ada dalam 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 untuk optimasi kompilasi:

  1. Tambahkan kode import berikut di awal file main.go:

    import _ "github.com/wasilibs/nottinygc"

    Jika tidak ada dependensi yang ditemukan, Anda dapat menjalankan perintah go mod tidy untuk secara otomatis mengunduh dependensi.

  2. Jalankan perintah berikut untuk mengompilasi kode:

    tinygo build -o plugin.wasm -gc=custom -tags='custommalloc nottinygc_envoy'  -target=wasi -scheduler=none main.go

    Perintah di atas menetapkan parameter -gc dan -tags. Untuk informasi lebih lanjut, lihat nottinygc.