プラグイン コードを準備する

Service Extensions プラグイン用に作成するカスタムコードは、他のサービスがアクセスできるように、パッケージ化して Artifact Registry にアップロードする必要があります。このページでは、プラグイン コードを作成し、コードをパッケージ化して、Artifact Registry リポジトリにアップロードする方法について説明します。

この機能は Media CDN のプレビュー版です。

Service Extensions については、Service Extensions の概要をご覧ください。

始める前に、プラグイン コードの作成に関するベスト プラクティスを確認してください。

その他の例については、プラグインのコードサンプルをご覧ください。

始める前に

  1. Google Cloud アカウントにログインします。 Google Cloudを初めて使用する場合は、 アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Network Services, Network Actions, Artifact Registry, Cloud Build, Cloud Logging, and Cloud Monitoring APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. Google Cloud CLI をインストールします。

  6. 外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。

  7. gcloud CLI を初期化するには、次のコマンドを実行します。

    gcloud init
  8. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  9. Verify that billing is enabled for your Google Cloud project.

  10. Enable the Network Services, Network Actions, Artifact Registry, Cloud Build, Cloud Logging, and Cloud Monitoring APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  11. Google Cloud CLI をインストールします。

  12. 外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。

  13. gcloud CLI を初期化するには、次のコマンドを実行します。

    gcloud init

ツールチェーンを設定する

C++

Proxy-Wasm C++ SDK を使用すると、デベロッパーは C++ を使用して Service Extensions 用の WebAssembly(Wasm)プラグインを実装できます。この SDK は、C++ WebAssembly ツールチェーン Emscripten と、protobuf などの他のライブラリ(Abseil はオプション)を使用します。

C++ で記述されたプラグインのビルドは、これらのツールとライブラリの特定のバージョンに依存するため、Proxy-Wasm C++ SDK によって提供される Docker イメージを使用することをおすすめします。このページの C++ の手順では、Docker メソッドを使用します。Docker を使用せずに C++ プラグインをビルドするには、Proxy-Wasm C++ SDK のドキュメントをご覧ください。

  1. Docker をまだインストールしていなければ、インストールします。Docker は、 Google Cloud インタラクティブ シェル環境である Cloud Shell に含まれています。

  2. Proxy-Wasm C++ SDK のコピーをダウンロードします。最も簡単な方法は、Git リポジトリのクローンを作成することです。

    git clone https://github.com/proxy-wasm/proxy-wasm-cpp-sdk.git
    
  3. SDK で提供されている Dockerfile から Proxy-Wasm C++ SDK Docker イメージをビルドします。

    cd proxy-wasm-cpp-sdk
    docker build -t wasmsdk:v3 -f Dockerfile-sdk .
    

    コマンドが SDK ライブラリと依存関係のビルドを完了すると、生成された Docker イメージが指定されたタグ(この例では wasmsdk:v3)に関連付けられます。

Go

Proxy-Wasm Go SDK は、フル機能の Go SDK を提供します。Go は、優れたパフォーマンスと、純粋な Go で記述されたサードパーティ ライブラリの豊富なサポートを提供します。

Go ツールチェーン v1.24.0 をインストールします

Rust

Service Extensions のカスタマイズ機能は、WebAssembly と Proxy-Wasm を使用して提供されます。WebAssembly は、多くのプログラミング言語をサポートしています。Google は、優れた WebAssembly サポートを提供し、Proxy-Wasm がフル機能の Rust SDK を提供しているため、Rust を推奨しています。Rust は、優れたパフォーマンスと強力な型安全性も提供します。

  1. Rust ツールチェーンをインストールします

    インストール プロセスの最後に、コンソールに表示された手順に沿って構成プロセスを完了します。

  2. Rust ツールチェーンに Wasm のサポートを追加します。

    rustup target add wasm32-wasip1
    

プラグイン パッケージを作成する

C++

  1. proxy-wasm-cpp-sdk とは別の新しいディレクトリを作成します。

    mkdir myproject
    
  2. ディレクトリに、次の内容の Makefile を作成します。

    # Express any dependencies
    PROTOBUF=     # full / lite / none
    WASM_DEPS=    # absl_base re2 ...
    
    # Include the SDK Makefile
    PROXY_WASM_CPP_SDK=/sdk
    include ${PROXY_WASM_CPP_SDK}/Makefile
    
  3. 同じディレクトリにプラグイン用の C++ ソースファイルを追加します。C++ ソースファイルの名前は、Makefile がターゲットとする Wasm ファイルと一致する必要があります。ただし、.wasm 接尾辞は .cc に置き換えられます。この例では、ソースファイルの名前は myproject.cc にする必要があります。

  4. プラグイン コードをソースファイルに追加します。

    次のサンプル ソースコードは、リクエスト ホストを書き換え、レスポンス ヘッダーを出力するプラグインです。

    #include "proxy_wasm_intrinsics.h"
    
    class MyHttpContext : public Context {
     public:
      explicit MyHttpContext(uint32_t id, RootContext* root) : Context(id, root) {}
    
      FilterHeadersStatus onRequestHeaders(uint32_t headers,
                                           bool end_of_stream) override {
        LOG_INFO("onRequestHeaders: hello from wasm");
    
        // Route Extension example: host rewrite
        if (replaceRequestHeader(":authority", "service-extensions.com") != WasmResult::Ok) {
          LOG_ERROR("Failed to replace :authority header");
        }
        if (replaceRequestHeader(":path", "/") != WasmResult::Ok) {
          LOG_ERROR("Failed to replace :path header");
        }
        return FilterHeadersStatus::Continue;
      }
    
      FilterHeadersStatus onResponseHeaders(uint32_t headers,
                                            bool end_of_stream) override {
        LOG_INFO("onResponseHeaders: hello from wasm");
    
        // Traffic Extension example: add response header
        if (addResponseHeader("hello", "service-extensions") != WasmResult::Ok) {
          LOG_ERROR("Failed to add response header");
        }
        return FilterHeadersStatus::Continue;
      }
    };
    
    static RegisterContextFactory register_StaticContext(
        CONTEXT_FACTORY(MyHttpContext), ROOT_FACTORY(RootContext));

    onRequestHeaders メソッドは、Service Extensions が呼び出すコールバックです。

Go

  1. プラグイン用の新しいディレクトリを作成します。

    mkdir go-plugin
    
  2. ディレクトリで、Go ツールを使用して go.mod ファイルを作成します。

    go mod init go-plugin
    
  3. 同じディレクトリに、main.go という名前のソースファイルを作成し、プラグイン コードをファイルに追加します。

    次のサンプル ソースコードは、リクエスト ホストを書き換え、レスポンス ヘッダーを出力するプラグインです。

    package main
    
    import (
    	"fmt"
    
    	"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm"
    	"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm/types"
    )
    
    func main() {}
    func init() {
    	proxywasm.SetVMContext(&vmContext{})
    }
    
    type vmContext struct {
    	types.DefaultVMContext
    }
    
    type pluginContext struct {
    	types.DefaultPluginContext
    }
    
    type httpContext struct {
    	types.DefaultHttpContext
    }
    
    func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
    	return &pluginContext{}
    }
    
    func (*pluginContext) NewHttpContext(uint32) types.HttpContext {
    	return &httpContext{}
    }
    
    func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
    	defer func() {
    		err := recover()
    		if err != nil {
    			proxywasm.SendHttpResponse(500, [][2]string{}, []byte(fmt.Sprintf("%v", err)), 0)
    		}
    	}()
    	proxywasm.LogInfof("onRequestHeaders: hello from wasm")
    
    	// Route Extension example: host rewrite
    	err := proxywasm.ReplaceHttpRequestHeader(":authority", "service-extensions.com")
    	if err != nil {
    		panic(err)
    	}
    	err = proxywasm.ReplaceHttpRequestHeader(":path", "/")
    	if err != nil {
    		panic(err)
    	}
    	return types.ActionContinue
    }
    
    func (ctx *httpContext) OnHttpResponseHeaders(numHeaders int, endOfStream bool) types.Action {
    	defer func() {
    		err := recover()
    		if err != nil {
    			proxywasm.SendHttpResponse(500, [][2]string{}, []byte(fmt.Sprintf("%v", err)), 0)
    		}
    	}()
    	proxywasm.LogInfof("onResponseHeaders: hello from wasm")
    
    	// Traffic Extension example: add response header
    	err := proxywasm.AddHttpResponseHeader("hello", "service-extensions")
    	if err != nil {
    		panic(err)
    	}
    	return types.ActionContinue
    }
    

    OnHttpRequestHeaders メソッドは、Service Extensions が呼び出すコールバックです。

  4. ライブラリの依存関係をダウンロードして固定するには、go mod tidy を実行します。

    go mod tidy
    

Rust

  1. Rust のパッケージ マネージャーである Cargocargo new コマンドを使用して、Rust パッケージ ディレクトリを作成します。

    cargo new --lib my-wasm-plugin
    

    このコマンドにより、Rust パッケージのビルド方法を記述するために更新できる cargo.toml ファイルと、プラグイン コードを保存する src ディレクトリを含むディレクトリが作成されます。

  2. cargo.toml ファイルを更新して、パッケージのビルドに必要なパラメータを指定します。

    [package]
    name = "my-wasm-plugin"
    version = "0.1.0"
    edition = "2021"
    
  3. Proxy-Wasm Rust SDK とロギング サポートを依存関係として登録するには、dependencies セクションを追加します。次に例を示します。

    [dependencies]
    proxy-wasm = "0.2"
    log = "0.4"
    
  4. プラグインに必要な動的ライブラリをビルドするには、lib セクションを追加します。次に例を示します。

    [lib]
    crate-type = ["cdylib"]
    
  5. コンパイル済みプラグインのサイズを小さくするには、profile.release セクションを追加します。次に例を示します。

    [profile.release]
    lto = true
    opt-level = 3
    codegen-units = 1
    panic = "abort"
    strip = "debuginfo"
    
  6. プラグイン コードを src ディレクトリの lib.rs ファイルに追加します。

    次のサンプル ソースコードは、リクエスト ホストを書き換え、レスポンス ヘッダーを出力するプラグインです。

    use log::info;
    use proxy_wasm::traits::*;
    use proxy_wasm::types::*;
    
    proxy_wasm::main! { {
        proxy_wasm::set_log_level(LogLevel::Trace);
        proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(MyHttpContext) });
    } }
    
    struct MyHttpContext;
    
    impl Context for MyHttpContext {}
    
    impl HttpContext for MyHttpContext {
        fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
            info!("onRequestHeaders: hello from wasm");
    
            // Route extension example: host rewrite
            self.set_http_request_header(":authority", Some("service-extensions.com"));
            self.set_http_request_header(":path", Some("/"));
            return Action::Continue;
        }
    
        fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {
            info!("onResponseHeaders: hello from wasm");
    
            // Traffic extension example: add response header
            self.add_http_response_header("hello", "service-extensions");
            return Action::Continue;
        }
    }

    on_http_request_headers メソッドは、Service Extensions が呼び出すコールバックです。

プラグインをコンパイルする

C++

プラグインをコンパイルするには、Makefile と C++ プラグインのソースファイルが置かれているディレクトリから次のコマンドを実行します。

docker run -v $PWD:/work -w /work wasmsdk:v3 /build_wasm.sh myproject.wasm

このコマンドは、現在のディレクトリを Docker イメージ内の work ディレクトリにマッピングし、Docker イメージで提供される build_wasm.sh スクリプトを実行してプラグイン コードをビルドします。コンパイル オペレーションが正常に完了すると、コンパイルされた Wasm バイトコードを含む myproject.wasm ファイルが現在のディレクトリに作成されます。

Docker イメージを使用してプラグイン コードを初めてコンパイルすると、Emscripten によって標準ライブラリが生成されます。これらを Docker イメージにキャッシュに保存して、毎回再生成する必要がないようにするには、最初のコンパイルが成功した後に、標準ライブラリを含むイメージを commit します。

docker commit `docker ps -l | grep wasmsdk:v3 | awk '{print $1}'` wasmsdk:v3

C++ プラグインのビルドの詳細については、Proxy-Wasm C++ SDK のドキュメントをご覧ください。

Go

プラグイン コードをコンパイルするには、go build コマンドを実行します。

env GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o main.wasm main.go

コンパイルが成功すると、現在のディレクトリに main.wasm ファイルが作成されます。

Rust

プラグイン コードをコンパイルするには、cargo build コマンドを実行します。

cargo build --release --target wasm32-wasip1

ビルドが正常に完了すると、Finished release [optimized] target(s) メッセージが表示されます。Envoy に精通している場合は、Envoy にプラグインを読み込んで、その動作を確認することをおすすめします。

コンパイルされたプラグイン コードを Artifact Registry にアップロードする

コンパイルされたプラグイン コードを Artifact Registry リポジトリにアップロードして、 Google Cloud サービスがアクセスできるようにします。

グローバル ロードバランサで Service Extensions を使用している場合は、マルチリージョン us ロケーションのリポジトリを使用します。リージョン ロードバランサを使用している場合は、同じリージョンまたは同じ大陸のマルチリージョン ロケーションにあるリポジトリを使用します。

プラグインをグローバル ロードバランサに接続すると、Service Extensions は Artifact Registry リポジトリから Wasm モジュールをコピーし、世界各地の独自のストレージに保存します。そのため、リポジトリのロケーションは、ロードバランサに送信されるリクエストのレイテンシに影響しません。リージョン ロードバランサの場合、プラグインはロードバランサが配置されている同じリージョンのロケーションにコピーされます。

Service Extensions プラグインは、Artifact Registry の汎用リポジトリまたは Docker リポジトリにアップロードできます。

スタンドアロン バイナリをより直接的に管理するには、汎用リポジトリを使用して Wasm ファイルを保存することをおすすめします。このオプションはプレビュー版です。

汎用リポジトリ

  1. ローカルの package/ ディレクトリを作成し、公開可能なプラグイン モジュールをコピーします。プラグイン アーティファクトの名前は plugin.wasm にする必要があります。次のサンプル コマンドは、Rust でビルドされたプラグイン アーティファクトをコピーします。

    mkdir -p package && cp -f target/wasm32-wasip1/release/my_wasm_plugin.wasm package/plugin.wasm
    
  2. --repository-formatgeneric に設定して、Artifact Registry リポジトリを作成します。

  3. リポジトリに必要な権限が付与されていることを確認します。

  4. Wasm モジュールを汎用アーティファクトとしてリポジトリにアップロードするには、gcloud artifacts generic upload コマンドを使用します。

    gcloud artifacts generic upload \
        --project=PROJECT_ID \
        --location=LOCATION \
        --repository=REPOSITORY \
        --source=package/plugin.wasm \
        --package=PACKAGE \
        --version=VERSION
    

    次のように置き換えます。

    • PROJECT_ID: 実際の Google Cloud プロジェクト ID
    • LOCATION: リポジトリのリージョンまたはマルチリージョンのロケーション
    • REPOSITORY: Wasm モジュールをアップロードするリポジトリの名前
    • PACKAGE: ファイルのパッケージ名
    • VERSION: Wasm モジュールのバージョン

    アップロードが完了したら、name ラベルで指定された汎用アーティファクトの名前(次の例の add_header_plugin:v4 など)をメモします。この名前は、プラグインまたはプラグイン バージョンを作成するときに指定します。

    Uploading file: plugin.wasm...done.
    '@type': type.googleapis.com/google.devtools.artifactregistry.v1.GenericArtifact
    createTime: '2025-06-16T11:02:25.080248Z'
    name: projects/my-project/locations/us/repositories/my-generic-repo/genericArtifacts/add_header_plugin:v4
    updateTime: '2025-06-16T11:02:25.080248Z'
    version: v4
    
  5. アーティファクトが Artifact Registry に正常にアップロードされたことを確認するには、gcloud artifacts files list コマンドを実行し、リストに PACKAGE:VERSION:plugin.wasm という名前のファイルがあることを確認します。

     gcloud artifacts files list \
         --project=PROJECT_ID \
         --location=LOCATION \
         --repository=REPOSITORY
    

Docker リポジトリ

  1. --repository-formatdocker に設定して、Artifact Registry リポジトリを作成します。

  2. リポジトリに必要な権限が付与されていることを確認します。

  3. ローカルの package/ ディレクトリを作成し、公開可能なプラグイン アーティファクトをそのディレクトリにコピーします。次のサンプルは、Rust でビルドされたプラグイン アーティファクトをコピーします。

    mkdir -p package && cp -f target/wasm32-wasip1/release/my_wasm_plugin.wasm package/plugin.wasm
    
  4. package/Dockerfile ファイルを作成し、次の内容を追加します。

    FROM scratch
    COPY plugin.wasm plugin.wasm
    
  5. Cloud Build または Docker を使用して、プラグイン コードをパッケージ化します。

    Cloud Build

    1. 次の内容の package/cloudbuild.yaml ビルド構成ファイルを作成します。

      steps:
        - name: 'gcr.io/cloud-builders/docker'
          args: [ 'build', '--no-cache', '--platform', 'wasm',
                '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:IMAGE_TAG', '.' ]
      images: [ 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:IMAGE_TAG' ]
      

      プラグインを保存するパスは次の形式にする必要があります。

      LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:IMAGE_TAG
      

      次のように置き換えます。

      • LOCATION: リポジトリのリージョンまたはマルチリージョン ロケーション
      • PROJECT_ID: Google Cloud コンソール プロジェクト ID
      • REPOSITORY: イメージを保存するリポジトリの名前
      • IMAGE: リポジトリ内のコンテナ イメージの名前(例: us-docker.pkg.dev/my-project/my-repo/my-wasm-plugin
      • IMAGE_TAG: コンテナに割り当てるイメージタグ(例: production
    2. プラグイン コンテナをビルドして Artifact Registry にアップロードするオペレーションをトリガーします。

      gcloud builds submit --config package/cloudbuild.yaml package/
      

    Docker

    1. Docker をまだインストールしていなければ、インストールします。Docker は、 Google Cloud インタラクティブ シェル環境である Cloud Shell に含まれています。

    2. Artifact Registry で認証するように Docker を構成します。次に例を示します。

      gcloud auth login
      gcloud auth configure-docker LOCATION-docker.pkg.dev
      gcloud auth print-access-token | docker login -u oauth2accesstoken --password-stdin https://LOCATION-docker.pkg.dev