Skip to content

Commit

Permalink
♻️ Mark distributed mode as experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
Shark committed Aug 12, 2022
1 parent 4a8a84b commit 7563298
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 48 deletions.
48 changes: 5 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,55 +245,17 @@ The `http-request` module can be used in a workflow like so:
- https://httpbin.org
```
### Distributed Mode
### Execution Modes
This plugin has two modes:
The plugin has two modes of how it can execute a Wasm module.
* A `local` Mode.
The `local` mode is the default and recommended mode. It will run Wasm modules within the plugin process. Argo will create one plugin container per workflow instance. This is fine for most use cases that don't need infinite scaling within a workflow. It's also very easy to use because there is nothing to configure: it just works.

This is the default. It will run Wasm modules in the plugin process. This is a single container per workflow instance. This is fine for most use cases that don't need infinite scaling within a workflow. It's also very easy to use because there is nothing to configure: it just works.

* A `distributed` Mode.

This mode is more advanced because it will orchestrate Wasm module invocations in a Kubernetes cluster. Much like Argo itself creates a Pod for each workflow task, the distributed mode will create Pods for Wasm modules.

What makes this possible is [Krustlet](https://docs.krustlet.dev). Krustlet shows up as a new node in your Kubernetes cluster, and it will execute Wasm modules that Kubernetes schedules to this node. I [forked Krustlet](https://github.com/Shark/krustlet) since there are some changes necessary to make Krustlet aware of the particularities of running workflow tasks as Wasm modules (inputs, outputs, parameters, artifacts, etc.).

For the distributed mode, you need to do a bit more:

* Create a service account and proper credentials for this plugin. See [`argo-plugin/rbac.yaml`](argo-plugin/rbac.yaml) for details.
* Inject the service account credentials into the plugin container. For this, there is a special [`plugin-distributed.yaml`](argo-plugin/plugin-distributed.yaml) showing you how.

By default, the plugin will be registered to the `wasm_distributed` key. This allows you to run the plugin in both modes simultaneously.

### :construction: Module Source

There is not a single idea of how Wasm modules can be distributed. There are a lot of practical options because of their comparably small size. In Cloud-Native, OCI/Docker registries are a natural fit since they're required anyway for container images. Other viable options include the [WebAssembly package manager WAPM](https://wapm.io) that already serves WASI-compatible Wasm modules. Moreover, the [Bindle](https://github.com/deislabs/bindle) project is another alternative that provides a modern infrastructure for distributing applications as a bunch of independent bundles with well-defined relationships between each of them.

Currently, this project only supports OCI registries and the format created by the [`wasm-to-oci`](https://github.com/engineerd/wasm-to-oci) tool (see [roadmap](#roadmap)). Other module sources can be represented in the invocation format without issue however:

```yaml
- name: wasm
plugin:
wasm:
module:
# you would use one of these options
oci: ghcr.io/someone/somemodule:latest # already supported
wapm: syrusakbary/[email protected] # on the roadmap
bindle: example.com/stuff/mybindle/v1.2.3 # on the roadmap
```
The :test_tube: `distributed` mode is more advanced. It is provided as a technical prototype. This mode orchestrates Wasm modules in a Kubernetes cluster much like Argo itself. It creates a Pod for each workflow task. The Pod is executed by a virtual Kubernetes node that is provided by Krustlet. [Read more about :test_tube: `distributed` mode](doc/distributed-mode.md).

## Roadmap

- [x] **Distributed Mode**
- [x] Create ready-to-use modules for demo (cowsay), and then image/text processing
- [x] Support input + output artifacts
- [ ] Enable additional capability providers (~~HTTP~~, S3, SQL, etc.)
- [ ] Support authentication for OCI (pull secrets)
- [ ] Support [WAPM](https://wapm.io) as a module source
- [ ] Support [Bindle]() as a module source
- [ ] Implement CLI to invoke modules locally (greatly improves developer experience)

Our roadmap is managed on the [*Developing wasm-workflows-plugin* GitHub project board](https://github.com/users/Shark/projects/1/views/1).

## Contributing

Expand Down
4 changes: 2 additions & 2 deletions crates/workflow-model/src/host/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl ArtifactManager {
))?;
match status_code {
200 => Ok(()),
code => return Err(anyhow!(format!("Unexpected status code {} != 200", code))),
code => Err(anyhow!(format!("Unexpected status code {} != 200", code))),
}
}

Expand Down Expand Up @@ -103,7 +103,7 @@ impl ArtifactManager {
});
Ok(artifact)
}
code => return Err(anyhow!(format!("Unexpected status code {} != 200", code))),
code => Err(anyhow!(format!("Unexpected status code {} != 200", code))),
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions doc/distributed-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# :test_tube: Distributed Mode

This mode is more advanced because it will orchestrate Wasm module invocations in a Kubernetes cluster. Much like Argo itself creates a Pod for each workflow task, the distributed mode will create Pods for Wasm modules.

What makes this possible is [Krustlet](https://docs.krustlet.dev). Krustlet shows up as a new node in your Kubernetes cluster, and it will execute Wasm modules that Kubernetes schedules to this node. I [forked Krustlet](https://github.com/Shark/krustlet) since there are some changes necessary to make Krustlet aware of the particularities of running workflow tasks as Wasm modules (inputs, outputs, parameters, artifacts, etc.).

For the distributed mode, you need to do a bit more:

* Create a service account and proper credentials for this plugin. See [`argo-plugin/rbac.yaml`](/argo-plugin/rbac.yaml) for details.
* Inject the service account credentials into the plugin container. For this, there is a special [`plugin-distributed.yaml`](/argo-plugin/plugin-distributed.yaml) showing you how.
2 changes: 1 addition & 1 deletion src/app/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl FromStr for LogLevel {
}
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Mode {
Local,
Distributed,
Expand Down
1 change: 1 addition & 0 deletions src/app/dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl DependencyProvider for RuntimeDependencyProvider {
Box::new(runner)
}
Mode::Distributed => {
tracing::warn!("Distributed mode is experimental!");
let client = self.client.as_ref().unwrap().clone();
let namespace = self.config.plugin_namespace.to_owned();
let wait_config = DistributedConfig {
Expand Down
2 changes: 1 addition & 1 deletion src/app/wasm/local/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl ModuleCache for FSCache {
let image = FSCache::canonical_name(image);
let path = self.base_dir.join(image);
let f = File::create(&path)?;
let _ = zstd::stream::copy_encode(data, f, 0)?;
zstd::stream::copy_encode(data, f, 0)?;
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/wasm/local/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn setup_module(
working_dir: &WorkingDir,
) -> anyhow::Result<(Linker<ModuleCtx>, Store<ModuleCtx>)> {
let mut linker = Linker::new(engine);
let _ = wasmtime_wasi::add_to_linker(&mut linker, |ctx: &mut ModuleCtx| &mut ctx.wasi)?;
wasmtime_wasi::add_to_linker(&mut linker, |ctx: &mut ModuleCtx| &mut ctx.wasi)?;
let preopen_working_dir =
cap_std::fs::Dir::open_ambient_dir(working_dir.path(), cap_std::ambient_authority())?;
let mut wasi = WasiCtxBuilder::new()
Expand Down

0 comments on commit 7563298

Please sign in to comment.