Istio扩展性
source link: https://zhuanlan.zhihu.com/p/269777095
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Istio的扩展性,主要体现在数据平面代理的扩展性。
WebAssembly是一种沙箱技术,可用于扩展Istio代理(Envoy)。 Proxy-Wasm 沙箱API取代了Mixer,成为Istio中的主要扩展机制。 Istio 1.6将为Proxy-Wasm插件提供统一的配置API。
WebAssembly 沙箱具备以下特点:
高效 功能 隔离 配置 开发友好
架构
Istio扩展(Proxy-Wasm插件)具有几个方面:
- Filter Service Provider Interface (SPI) for building Proxy-Wasm plugins for filters.
- Sandbox V8 Wasm Runtime embedded in Envoy.
- Host APIs for headers, trailers and metadata.
- Call out APIs for gRPC and HTTP calls.
- Stats and Logging APIs for metrics and monitoring.
为了使Envoy能够加载WebAssembly插件并能够对其进行调用并被该插件调用,我们需要一个稳定的接口。这是proxy-wasm的意义。它定义了一个应用程序二进制接口-从WebAssembly模块导出并在运行时可调用的一组函数。从本质上讲,这与动态链接库没有什么不同。
目前官方提供了 Rust 和 C++ 两种语言的sdk,此外社区另外提供了 TinyGo 和 AssemblyScript 的实现,我们可以基于sdk更加方便地扩展Envoy。
Demo
我们的演示使用rust语言完成。大致包括以下三步:
- 构建一段Rust代码,该代码实现并使用ABI
- 将代码编译为WebAssembly
- 将此部署到Envoy代理中并进行测试。
工具准备
确保你已经安装了最新版的rust。可以通过以下命令检查并查看具体版本:
$ rustc -V rustc 1.46.0 (04488afe3 2020-08-24)
然后检查是否安装了 wasm32-unknown-unknown
编译目标:
$ rustup target list | grep wasm32 wasm32-unknown-emscripten wasm32-unknown-unknown (installed) wasm32-wasi (installed)
如果大家没有安装,那么可以执行以下命令进行安装:
$ rustup update $ rustup target add wasm32-unknown-unknown
创建库并设置
Wasm过滤器是从Rust库项目编译而成的,因此首先我们需要创建该项目:
cargo new --lib my-wasm-filter
生产的库是要被Envoy C++ 代码加载的,因此无需包含任何Rust特定的信息。故我们编辑Cargo.toml文件,将库的类型设置为"cdylib"。
同时我们需要引用proxy-wasm-rust SDK,故需要配置一下proxy-wasm-rust SDK依赖。
如下:
[package] name = "my-wasm-filter" version = "0.1.0" authors = ["iyacontrol <[email protected]>"] edition = "2018" [lib] crate-type = ["cdylib"] [dependencies] chrono = "0.4" log = "0.4.8" proxy-wasm = "0.1.0" # The Rust SDK for proxy-wasm
编写代码
src/lib.rs 代码如下:
use chrono::{DateTime, Utc}; use log::info; use proxy_wasm::traits::*; use proxy_wasm::types::*; use std::time::Duration; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(HelloWorld) }); } struct HelloWorld; impl Context for HelloWorld {} impl RootContext for HelloWorld { fn on_vm_start(&mut self, _: usize) -> bool { info!("Hello, World!"); self.set_tick_period(Duration::from_secs(5)); true } fn on_tick(&mut self) { let datetime: DateTime<Utc> = self.get_current_time().into(); info!("It's {}", datetime); } }
首先,我们定义了一个名为_start的特殊函数,该函数是ABI的一部分(我们使用no_mangle宏保留名称),然后让我们初始化事情。在其中,我们设置日志级别以跟踪和注册稍后定义的HttpContext。 HTTP上下文是可用的三种上下文类型之一,用于构建HTTP Filter以及RootContext和StreamContext,可分别用于配置和使用计时器以及TCP Filter。您可以阅读可用的API,它们非常简单。
其余代码定义了我们的HelloWorld扩展,实现了必需的Context特性和HttpContext特性。
编译
执行如下语句:
cargo build --target wasm32-unknown-unknown --release
生成结果如下:
主要是 my_wasm_filter.wasm
文件。后续我们会使用到该文件。
运行
配置envoy启动文件,如下:
# envoy-bootstrap.yml admin: access_log_path: /dev/null address: socket_address: address: 0.0.0.0 port_value: 19000 static_resources: listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 8080 } filter_chains: - filters: - name: envoy.http_connection_manager config: codec_type: AUTO stat_prefix: ingress_http route_config: name: test virtual_hosts: - name: httpbin.com domains: ["*"] routes: - match: { prefix: "/" } route: cluster: static-cluster auto_host_rewrite: true http_filters: - name: envoy.filters.http.wasm config: config: name: "my_wasm_filter" root_id: "my_wasm_filter" vm_config: runtime: "envoy.wasm.runtime.v8" code: local: filename: "/etc/my_wasm_filter.wasm" allow_precompiled: true - name: envoy.router clusters: - name: static-cluster connect_timeout: 0.25s type: LOGICAL_DNS lb_policy: ROUND_ROBIN dns_lookup_family: V4_ONLY hosts: - socket_address: address: httpbin.org port_value: 80 ipv4_compat: true
通过 envoy.filters.http.wasm
配置项,将我们编写的 my_wasm_filter.wasm
加入到envoy filter中。
为了简单,我们直接基于istio官方proxy镜像打一个新的镜像。Dockerfile如下:
FROM istio/proxyv2:1.7.3 ADD ./target/wasm32-unknown-unknown/release/my_wasm_filter.wasm /etc/my_wasm_filter.wasm ADD ./envoy.yaml /etc/envoy.yaml ENTRYPOINT /usr/local/bin/envoy -c /etc/envoy.yaml -l debug --service-cluster proxy
使用以下命令构建我们新的镜像:
docker build -t iyacontrol/proxyv2:1.7.3 .
运行构建好的镜像:
$ docker run iyacontrol/proxyv2:1.7.3 ... [2020-10-30 02:04:14.174][6][debug][upstream] [external/envoy/source/common/upstream/logical_dns_cluster.cc:153] DNS refresh rate reset for httpbin.org, refresh rate 5000 ms [2020-10-30 02:04:14.283][15][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1009] wasm log my_wasm_filter : It's 2020-10-30 02:04:14.283022 UTC [2020-10-30 02:04:14.294][18][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1009] wasm log my_wasm_filter : It's 2020-10-30 02:04:14.294866 UTC [2020-10-30 02:04:14.311][16][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1009] wasm log my_wasm_filter : It's 2020-10-30 02:04:14.311076 UTC [2020-10-30 02:04:14.318][17][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1009] wasm log my_wasm_filter : It's 2020-10-30 02:04:14.317969 UTC ....
通过打印的日志可以看出,我们的插件已经完美运行。
结论
虽然目前主要用来编写遥测组件,但是后续的发展过程中,我们可以使用我们熟悉的语言,通过wasm实现一些功能插件,从而实现无需修改envoy主体代码,即可扩展我们所需的功能的目的。
Solo.io 推出了一个名为WebAssembly Hub的wasm插件存储服务(使用OCI镜像),让我们可以用来存储和分发wasm 插件。
同时也推出一个名为wasme的cli工具,大大简化了扩展的过程。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK