Service Extensions 플러그인용으로 만든 맞춤 코드는 다른 서비스가 액세스할 수 있도록 패키징하여 Artifact Registry에 업로드해야 합니다. 이 페이지에서는 플러그인 코드를 만들고, 코드를 패키징하고, Artifact Registry 저장소에 업로드하는 방법을 설명합니다.
이 기능은 Media CDN의 미리보기 상태입니다.
서비스 확장 프로그램에 대한 자세한 내용은 서비스 확장 프로그램 개요를 참고하세요.
시작하기 전에 플러그인 코드 작성에 관한 권장사항을 검토하세요.
더 많은 예는 플러그인 코드 샘플을 참고하세요.
시작하기 전에
- Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
-
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
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 theserviceusage.services.enablepermission. Learn how to grant roles.-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init -
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
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 theserviceusage.services.enablepermission. Learn how to grant roles.-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init
도구 모음 설정
C++
Proxy-Wasm C++ SDK를 사용하면 개발자가 C++를 사용하여 서비스 확장 프로그램용 WebAssembly (Wasm) 플러그인을 구현할 수 있습니다. SDK는 C++ WebAssembly 도구 모음 Emscripten과 protobuf, 선택적으로 Abseil과 같은 기타 라이브러리를 사용합니다.
C++로 작성된 플러그인 빌드는 이러한 도구와 라이브러리의 특정 버전에 따라 달라지므로 Proxy-Wasm C++ SDK에서 제공하는 Docker 이미지를 사용하는 것이 좋습니다. 이 페이지의 C++ 안내에서는 Docker 메서드를 사용합니다. Docker를 사용하지 않고 C++ 플러그인을 빌드하려면 Proxy-Wasm C++ SDK 문서를 참고하세요.
Docker가 아직 설치되어 있지 않으면 설치합니다. Docker는 Google Cloud 대화형 셸 환경인 Cloud Shell에 포함되어 있습니다.
Proxy-Wasm C++ SDK의 사본을 다운로드합니다. 가장 간단한 방법은 Git 저장소를 클론하는 것입니다.
git clone https://github.com/proxy-wasm/proxy-wasm-cpp-sdk.gitSDK에서 제공하는 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로 작성된 서드 파티 라이브러리를 풍부하게 지원합니다.
Rust
서비스 확장 프로그램의 맞춤설정 기능은 WebAssembly 및 Proxy-Wasm을 사용하여 제공됩니다. WebAssembly는 여러 프로그래밍 언어를 지원합니다. Google에서는 Rust를 권장합니다. Rust는 뛰어난 WebAssembly 지원을 제공하고 Proxy-Wasm은 완전한 기능을 갖춘 Rust SDK를 제공하기 때문입니다. Rust는 우수한 성능과 강력한 유형 안전성도 제공합니다.
-
설치 프로세스가 끝나면 콘솔에 인쇄된 안내에 따라 구성 프로세스를 완료합니다.
Rust 도구 모음에 Wasm 지원을 추가합니다.
rustup target add wasm32-wasip1
플러그인 패키지 만들기
C++
proxy-wasm-cpp-sdk와 별도로 새 디렉터리를 만듭니다.mkdir myproject디렉터리에서 다음 내용이 포함된 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동일한 디렉터리에 플러그인의 C++ 소스 파일을 추가합니다. C++ 소스 파일의 이름은 Makefile이 타겟팅하는 Wasm 파일과 일치해야 하며
.wasm접미사가.cc로 대체되어야 합니다. 이 예시에서 소스 파일 이름은myproject.cc여야 합니다.소스 파일에 플러그인 코드를 추가합니다.
다음 샘플 소스 코드는 요청 호스트를 다시 작성하고 응답 헤더를 내보내는 플러그인입니다.
onRequestHeaders메서드는 서비스 확장 프로그램이 호출하는 콜백입니다.
Go
플러그인의 새 디렉터리를 만듭니다.
mkdir go-plugin디렉터리에서 Go 도구를 사용하여
go.mod파일을 만듭니다.go mod init go-plugin동일한 디렉터리에서
main.go라는 소스 파일을 만들고 파일에 플러그인 코드를 추가합니다.다음 샘플 소스 코드는 요청 호스트를 다시 작성하고 응답 헤더를 내보내는 플러그인입니다.
OnHttpRequestHeaders메서드는 서비스 확장 프로그램이 호출하는 콜백입니다.라이브러리 종속 항목을 다운로드하고 고정하려면
go mod tidy를 실행하세요.go mod tidy
Rust
Rust 패키지 관리자 Cargo에서
cargo new명령어를 사용하여 Rust 패키지 디렉터리를 만듭니다.cargo new --lib my-wasm-plugin이 명령어는 Rust 패키지를 빌드하는 방법을 설명하기 위해 업데이트할 수 있는
cargo.toml파일과 플러그인 코드를 저장하는src디렉터리가 포함된 디렉터리를 만듭니다.cargo.toml파일을 업데이트하여 패키지를 빌드하는 데 필요한 매개변수를 지정합니다.[package] name = "my-wasm-plugin" version = "0.1.0" edition = "2021"Proxy-Wasm Rust SDK와 로깅 지원을 종속 항목으로 등록하려면
dependencies섹션을 추가합니다. 예를 들면 다음과 같습니다.[dependencies] proxy-wasm = "0.2" log = "0.4"플러그인에 필요한 동적 라이브러리를 빌드하려면
lib섹션을 추가합니다. 예를 들면 다음과 같습니다.[lib] crate-type = ["cdylib"]컴파일된 플러그인의 크기를 줄이려면
profile.release섹션을 추가하세요. 예를 들면 다음과 같습니다.[profile.release] lto = true opt-level = 3 codegen-units = 1 panic = "abort" strip = "debuginfo"src디렉터리의lib.rs파일에 플러그인 코드를 추가합니다.다음 샘플 소스 코드는 요청 호스트를 다시 작성하고 응답 헤더를 내보내는 플러그인입니다.
on_http_request_headers메서드는 서비스 확장 프로그램이 호출하는 콜백입니다.
플러그인 컴파일
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 이미지에 캐시하려면 첫 번째 컴파일이 성공한 후 표준 라이브러리를 사용하여 이미지를 커밋하세요.
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에 업로드
Google Cloud 서비스가 액세스할 수 있도록 컴파일된 플러그인 코드를 Artifact Registry 저장소에 업로드합니다.
전역 부하 분산기와 함께 서비스 확장 프로그램을 사용하는 경우 멀티 리전 us 위치의 저장소를 사용하세요.
리전 부하 분산기를 사용하는 경우 동일한 리전 또는 동일한 대륙의 멀티 리전 위치에 있는 저장소를 사용합니다.
플러그인을 전역 부하 분산기에 연결하면 서비스 확장 프로그램이 Artifact Registry 저장소의 Wasm 모듈을 전 세계 위치에 있는 자체 스토리지에 복사합니다. 따라서 저장소의 위치는 부하 분산기로 전송된 요청의 지연 시간에 영향을 미치지 않습니다. 리전 부하 분산기의 경우 플러그인이 부하 분산기가 있는 동일한 리전의 위치에 복사됩니다.
서비스 확장 프로그램 플러그인은 Artifact Registry 일반 또는 Docker 저장소에 업로드할 수 있습니다.
독립형 바이너리를 관리하는 더 직접적인 방법을 사용하려면 일반 저장소를 사용하여 Wasm 파일을 저장하는 것이 좋습니다. 이 옵션은 미리보기에 있습니다.
일반 저장소
로컬
package/디렉터리를 만들고 게시 가능한 플러그인 모듈을 여기에 복사합니다. 플러그인 아티팩트의 이름은plugin.wasm여야 합니다. 다음 샘플 명령어는 Rust로 빌드된 플러그인 아티팩트를 복사합니다.mkdir -p package && cp -f target/wasm32-wasip1/release/my_wasm_plugin.wasm package/plugin.wasm--repository-format이generic로 설정된 Artifact Registry 저장소를 만듭니다.저장소에 대해 필요한 권한이 있는지 확인합니다.
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 프로젝트 IDLOCATION: 저장소의 리전 또는 멀티 리전 위치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아티팩트가 Artifact Registry에 성공적으로 업로드되었는지 확인하려면
gcloud artifacts files list명령어를 실행하고 목록에PACKAGE:VERSION:plugin.wasm라는 파일이 있는지 확인합니다.gcloud artifacts files list \ --project=PROJECT_ID \ --location=LOCATION \ --repository=REPOSITORY
Docker 저장소
--repository-format이docker로 설정된 Artifact Registry 저장소를 만듭니다.저장소에 대해 필요한 권한이 있는지 확인합니다.
로컬
package/디렉터리를 만들고 게시 가능한 플러그인 아티팩트를 여기에 복사합니다. 다음 샘플은 Rust로 빌드된 플러그인 아티팩트를 복사합니다.mkdir -p package && cp -f target/wasm32-wasip1/release/my_wasm_plugin.wasm package/plugin.wasm다음 콘텐츠로
package/Dockerfile이라는 파일을 만듭니다.FROM scratch COPY plugin.wasm plugin.wasmCloud Build 또는 Docker를 사용하여 플러그인 코드를 패키징합니다.
Cloud Build
다음 콘텐츠로
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
다음을 바꿉니다.
플러그인 컨테이너를 빌드하고 Artifact Registry에 업로드하는 작업을 트리거합니다.
gcloud builds submit --config package/cloudbuild.yaml package/
Docker
Docker가 아직 설치되어 있지 않으면 설치합니다. Docker는 Google Cloud 대화형 셸 환경인 Cloud Shell에 포함되어 있습니다.
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
컨테이너 이미지를 빌드합니다.
docker build --no-cache --platform wasm -t my-wasm-plugin package/
저장소 이미지 이름으로 로컬 이미지에 태그를 지정하려면 이미지 태그를 사용하세요.
docker tag my-wasm-plugin LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:IMAGE_TAG
다음을 바꿉니다.
태그가 지정된 컨테이너 이미지를 Artifact Registry에 업로드합니다.
docker push LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:IMAGE_TAG
이미지가 Artifact Registry에 성공적으로 업로드되었는지 확인하려면
gcloud artifacts docker images list명령어를 실행합니다.gcloud artifacts docker images list LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ --include-tags
구성 파일 준비 및 업로드
플러그인은 선택적으로 구성 데이터를 수신할 수 있으며, 이는 런타임에 플러그인 동작에 영향을 줄 수 있습니다. 구성 데이터는 텍스트 또는 바이너리일 수 있으며 플러그인에서 허용하는 모든 형식일 수 있습니다. 구성 데이터의 크기가 큰 경우 구성 파일을 Artifact Registry에 업로드해야 할 수 있습니다.
구성 데이터를 읽는 플러그인 코드 작성
C++
구성 데이터는 플러그인 시작 시 한 번 인스턴스화되고 플러그인을 호스팅하는 Wasm 런타임의 수명 동안 활성 상태로 유지되는 루트 컨텍스트 객체의 onConfigure 메서드에 전달됩니다. 루트 컨텍스트 객체는 RootContext 클래스 또는 RootContext의 서브클래스의 인스턴스입니다.
플러그인 코드는 RegisterContextFactory 값을 통해 루트 컨텍스트에 사용되는 클래스를 제어할 수 있습니다. 예를 들어 다음 플러그인 코드는 MyRootContext 및 MyHttpContext을 루트 및 스트림 컨텍스트 인스턴스에 사용할 클래스로 등록합니다. 그런 다음 플러그인 구성 데이터에서 비밀 값을 읽어옵니다. 스트림 컨텍스트 인스턴스는 루트 컨텍스트 객체를 통해 이 값에 액세스할 수 있습니다.
Go
구성 데이터는 플러그인 시작 시 런타임이 PluginContext 구조체에서 한 번 실행하는 메서드 수신기인 OnPluginStart를 실행하는 동안 읽습니다. 구성 데이터는 플러그인을 호스팅하는 Wasm 런타임의 수명 동안 변경되지 않습니다. PluginContext는 초기화 로직을 실행하고 여러 요청에서 상태를 유지하는 데 유용합니다.
플러그인 코드는 PluginContext를 인스턴스화하는 VMContext에서 NewPluginContext 메서드를 구현하여 PluginContext에 사용되는 컨텍스트를 제어할 수 있습니다. 그러면 PluginContext이 HttpContext 컨텍스트를 인스턴스화합니다.
예를 들어 다음 플러그인 코드는 구성 데이터를 읽고 필요에 따라 HttpContext 컨텍스트를 인스턴스화하는 컨텍스트인 PluginContext를 인스턴스화하는 VMContext를 등록합니다.
PluginContext는 플러그인 구성 데이터에서 비밀 값을 읽고 PluginContext 컨텍스트 내에 저장하며 NewHttpContext에서 HttpContext에 전달합니다.
Rust
구성 데이터는 플러그인 시작 시 한 번 인스턴스화되고 플러그인을 호스팅하는 Wasm 런타임의 수명 동안 활성 상태로 유지되는 RootContext 특성에서 읽어옵니다. RootContext 특성은 여러 요청에서 작업을 실행하거나 상태를 유지하는 데 유용합니다.
플러그인 코드는 set_root_context 메서드를 통해 루트 컨텍스트에 사용되는 클래스를 제어할 수 있으며 루트 컨텍스트는 스트림 컨텍스트를 인스턴스화합니다.
예를 들어 다음 플러그인 코드는 필요에 따라 MyHttpContext를 인스턴스화하는 MyRootContext를 등록합니다. 루트 컨텍스트는 플러그인 구성 데이터에서 비밀 값을 읽고 스트림 컨텍스트에 전달합니다.
구성 파일 업로드
on_configure에서 플러그인에 전달할 데이터의 크기가 900KiB를 초과하면 컴파일된 플러그인 코드를 Artifact Registry에 업로드에 설명된 방법에 따라 Artifact Registry에 업로드합니다.
이 경우 구성 파일을 plugin.config(plugin.wasm 아님) 이름으로 저장합니다.
다음 단계는 플러그인을 만드는 것입니다.
플러그인을 만드는 동안 업로드된 Wasm 모듈 또는 이미지의 URI를 제공해야 합니다.
플러그인 코드의 새 버전 만들기
플러그인 코드의 새 버전을 만들려면 플러그인 파일을 수정하세요. 그런 다음 앞의 섹션에 설명된 대로 플러그인 코드를 컴파일하고, 다시 패키징하고, Artifact Registry에 업로드합니다.
콜백
Wasm으로 컴파일하는 코드는 임의의 메서드나 함수를 정의할 수 있지만 일부는 특별한 의미를 갖습니다. 이는 선택한 언어의 프록시-Wasm SDK에 정의되어 있으며 프록시-Wasm 애플리케이션 바이너리 인터페이스 (ABI) 사양에 매핑되는 메서드입니다. 서비스 확장 프로그램은 사용자 요청에 대한 응답으로 또는 플러그인 수명 주기 이벤트에 대한 응답으로 이러한 콜백을 호출합니다.
이러한 콜백은 일반적으로 호출되는 순서대로 다음 표에 나열되어 있습니다.
| 콜백 이름 및 설명 | C++ 메서드 이름 | Go 메서드 이름 | Rust 메서드 이름 |
|---|---|---|---|
START_PLUGIN: 플러그인이 시작될 때 호출됩니다. |
RootContext::onStart |
VMContext.OnVmStart |
RootContext::on_vm_start |
CONFIGURE_PLUGIN: 플러그인이 시작된 후 호출되어 플러그인에 구성 데이터를 제공합니다. |
RootContext::onConfigure |
PluginContext.OnPluginStart |
RootContext::on_configure |
CREATE_CONTEXT: 새 스트림 컨텍스트가 생성될 때 호출됩니다. 각 스트림은 클라이언트 HTTP 요청에 해당합니다. |
Context::onCreate |
PluginContext.NewHttpContext |
RootContext::create_http_context |
HTTP_REQUEST_HEADERS: HTTP 요청 헤더를 처리하기 위해 호출됩니다. |
Context::onRequestHeaders |
HttpContext.OnHttpRequestHeaders |
HttpContext::on_http_request_headers |
HTTP_REQUEST_BODY: HTTP 요청 본문 청크를 처리하기 위해 반복적으로 호출됩니다. |
Context::onRequestBody |
HttpContext.OnHttpRequestBody |
HttpContext::on_http_request_body |
HTTP_RESPONSE_HEADERS: HTTP 응답 헤더를 처리하기 위해 호출됩니다. |
Context::onResponseHeaders |
HttpContext.OnHttpResponseHeaders |
HttpContext::on_http_response_headers |
HTTP_RESPONSE_BODY: HTTP 응답 본문 청크를 처리하기 위해 반복적으로 호출됩니다. |
Context::onResponseBody |
HttpContext.OnHttpResponseBody |
HttpContext::on_http_response_body |
DONE: 플러그인 처리가 완료되면 호출됩니다. |
Context::onDone |
HttpContext.OnHttpStreamDone |
Context::on_done |
DELETE: 클라이언트 HTTP 요청에 해당하는 스트림 컨텍스트 객체가 삭제될 때 호출됩니다. |
Context::onDelete |
(콜백 없음) | (콜백 없음) |
다음 단계
- 플러그인 만들기
- 서비스 확장 프로그램 개요를 참고하세요.