Skip to content

Commit 755ae9f

Browse files
committed
📝 Make README more readable
1 parent 95419b8 commit 755ae9f

File tree

5 files changed

+201
-159
lines changed

5 files changed

+201
-159
lines changed

README.md

Lines changed: 34 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<h3 align="center">wasm-workflows-plugin</h3>
77

88
<p align="center">
9-
An <a href="https://github.com/argoproj/argo-workflows/blob/master/docs/executor_plugins.md">Executor Plugin</a> for <a href="https://argoproj.github.io/argo-workflows/">Argo Workflows</a> that runs WebAssembly modules! 🚀
9+
Runs WebAssembly in your Argo Workflows! 🚀
1010
<br />
1111
<a href="https://github.com/Shark/wasm-workflows-plugin/#about-the-project"><strong>Find out why that's awesome »</strong></a>
1212
<!--
@@ -47,108 +47,61 @@
4747

4848
## About The Project
4949

50-
This is a tool that allows you run WebAssembly modules instead of containers for your steps in [Argo Workflows](https://argoproj.github.io/argo-workflows/). You might rightfully ask yourself what problem this solves for you.
50+
This is an <a href="https://github.com/argoproj/argo-workflows/blob/master/docs/executor_plugins.md">Executor Plugin</a> for <a href="https://argoproj.github.io/argo-workflows/">Argo Workflows</a> that runs WebAssembly modules!
5151

52-
The two most important aspects are security and performance:
52+
These are the benefits of using Wasm instead of Docker containers in your workflows:
5353

54-
* :lock: **Security**
54+
* :airplane: **Portability**
5555

56-
The [list of things to do](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html) when you want to run containers securely is long and the topic is more complex than even ambitious users care about. Containers are [vulnerable in many ways](https://ieeexplore.ieee.org/document/8693491) because of their denylist approach to security: they're allowed to do many things by default.
56+
You must build Docker containers individually for every CPU architecture. Working on a Mac with Apple Silicon, but your Kubernetes nodes run on Intel CPUs? You'll cross-compile your container images all day.
5757

58-
WebAssembly's security model is the opposite. As with smartphone apps, they must be given permission for potentially infringing tasks. For example, you might want to give a module the permission to read and write files but not communicate over the internet.
58+
Wasm modules are architecture-independent by design. Build once, run everywhere.
5959

60-
Container images from third parties you don't know are usually a security nightmare. With WebAssembly, you can run code you don't fully trust with more confidence. Say you have a workflow step that renders Markdown. When the author of your Markdown parser container image decides to deliver a crypto miner instead, most Kubernetes setups will happily run it. If you were using this project and a WebAssembly module: zero chance, since it's easy for you to know that the step doesn't need the network but only takes an input parameter and produces some output. [This example is not made up](https://www.trendmicro.com/vinfo/fr/security/news/virtualization-and-cloud/malicious-docker-hub-container-images-cryptocurrency-mining).
60+
* :runner: **Performance**
6161

62-
<details>
63-
<summary>More about the difference between containers and Wasm modules</summary>
64-
<img src="doc/container-vs-wasm.png" style="max-width: 700px">
65-
<p>Linux processes use more than 300 system calls for any task that involves sharing data with outside of a process. Containers are a combination of different Linux Kernel technologies (namespaces, cgroups etc.) that segment one computer into many seemlingly independent containers. But this very much depends on a) the secure implementation of all syscalls not to leak anything and b) trust in the application inside the container to do what the user intends it to.</p>
66-
<p>Wasm modules are very restricted by default. We use application-level capabilities to allow them to access external resources like the network, S3 object stores, or the filesystem. The modules are the capability consumers, the Wasm runtime is the capability provider. The capability provider translates the requests from the Wasm module and acts as a secure proxy to the outside.</p>
67-
</details>
62+
It takes a while for Kubernetes to spin up a container and run your code. The process has quite a few steps: pulling a container image, often 100s of megabytes in size, creating namespaces and virtual network interfaces. Starting the runtime for interpreted languages takes a while, too.
6863

69-
* :runner: **Performance**
64+
Wasm does not emulate a complete operating system as containers do. They are a much simpler abstraction. This means that a module executes in a matter of milliseconds.
65+
66+
* :lock: **Security**
7067

71-
Containers have some overhead: for each workflow step, Argo creates new Kubernetes Pod. This Pod has several containers to enable all the Argo features, your code is just one of them. All the containers must execute, then results are gathered and sent back to Argo. This all takes time: container images are often towards 100s of megabytes, they may rely on interpreted languages like Python or have huge dependencies leading to a slow start time. You may know the [Cold Start issue](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/) with Function-as-a-Service. In Argo, every workflow step is a cold start.
68+
Securing a container runtime [is a challenge](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html) because [containers are vulnerable in many ways](https://ieeexplore.ieee.org/document/8693491). Containers are powerful by design.
7269

73-
Because WebAssembly modules don't have to bring a whole operating system, they're much smaller. And there is less setup work to do, even for interpreted languages. This means that a module can be run in a matter of milliseconds rather than tens of seconds.
70+
Wasm is a minimal runtime that is just powerful enough to run a program. Rather than allowing everything by default, its security works more like on a smartphone, where you give apps permissions explicitly.
7471

75-
WebAssembly is a new technology in the browser and even more so in the Cloud-Native ecosystem. But there are several ways to ease the transition:
72+
[Read more about the benefits here.](doc/benefits.md)
7673

77-
* Containers and Wasm modules play together just fine in the same workflow. Existing container setups don't have to be migrated just because they could. Use Wasm for the tasks for which is a good fit and leave the rest to containers.
74+
Even though Wasm is a new technology in Cloud Native, incorporating Wasm into your workflow is seamless:
7875

79-
* You can find ready-to-use templates for popular programming languages in the [`wasm-modules/templates/`](wasm-modules/templates/) folder.
76+
* Containers and Wasm modules co-exist in the same workflow. You can pass artifacts and parameters between them.
8077

81-
* We will provide pre-made modules for popular use cases such as image and text processing, API connectors, etc.
78+
* We have included [ready-to-use templates](wasm-modules/templates/), [examples](wasm-modules/examples/), and even [some useful modules for running off-the-shelf](wasm-modules/contrib/).
8279

8380
### Built with
8481

85-
Open Source software stands on the shoulders of giants. It wouldn't have been possible to build this tool with very little extra work without the authors of these lovely projects below.
82+
Open Source software stands on the shoulders of giants. It wouldn't have been possible to build this tool without the authors of these projects:
8683

8784
* [Rust](https://rust-lang.org) is used to implement the Argo Executor Plugin API, pull and execute Wasm modules
8885
* [Axum](https://github.com/tokio-rs/axum) is the Rust web framework to handle RPC calls
89-
* [Wasmtime](https://github.com/bytecodealliance/wasmtime) is the WebAssembly Virtual Machine ([WASI](https://wasi.dev) is [supported](https://crates.io/crates/wasmtime-wasi), too)
90-
* [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen) provides the interface between this project as the Wasm host and the Wasm modules
86+
* [Wasmtime](https://github.com/bytecodealliance/wasmtime) is the WebAssembly Virtual Machine with [WASI support](https://wasi.dev)
9187
* [oci-distribution](https://crates.io/crates/oci-distribution) allows the tool to pull Wasm modules from OCI registries
9288
* [Best README Template](https://github.com/othneildrew/Best-README-Template)
9389

9490
## Getting Started
9591

96-
### Prerequisites
97-
98-
* This guide assumes you have a working Argo Workflows installation with v3.3.0 or newer.
99-
* You will need to install the [Argo CLI](https://argoproj.github.io/argo-workflows/cli/) with v3.3.0 or newer.
100-
* `kubectl` must be available and configured to access the Kubernetes cluster where Argo Workflows is installed.
101-
102-
### Installation
103-
104-
1. Clone the repository and change to the [`argo-plugin/`](argo-plugin/) directory:
105-
106-
```shell
107-
git clone https://github.com/Shark/wasm-workflows-plugin
108-
cd wasm-workflows-plugin/argo-plugin
109-
```
92+
You must install Argo Workflows (v3.3.0 or newer) and the [`argo` CLI](https://argoproj.github.io/argo-workflows/cli/). `kubectl` needs access to your cluster.
11093

111-
1. Build the plugin ConfigMap:
94+
**Install the plugin:**
11295

113-
```shell
114-
argo executor-plugin build .
115-
```
96+
Go to the [Releases page](https://github.com/Shark/wasm-workflows-plugin.git) and follow the descriptions for installing the plugin through the ConfigMap.
11697

117-
1. Register the plugin with Argo in your cluster:
98+
**Submit your first Wasm workflow:**
11899

119-
Ensure to specify `--namespace` if you didn't install Argo in the default namespace.
100+
Run `argo submit --watch https://raw.githubusercontent.com/Shark/wasm-workflows-plugin/main/wasm-modules/examples/ferris-says/workflow.yaml`.
120101

121-
```shell
122-
kubectl apply -f wasm-executor-plugin-configmap.yaml
123-
```
102+
Add `--namespace XYZ` if your Argo installation is not running in the default namespace.
124103

125-
## Usage
126-
127-
Now that the plugin is registered in Argo, you can run workflow steps as Wasm modules by simply calling the `wasm` plugin:
128-
129-
```yaml
130-
apiVersion: argoproj.io/v1alpha1
131-
kind: Workflow
132-
metadata:
133-
generateName: wasm-
134-
spec:
135-
entrypoint: wasm
136-
arguments:
137-
parameters:
138-
- name: text
139-
value: Hello World from WebAssembly
140-
templates:
141-
- name: wasm
142-
inputs:
143-
parameters:
144-
- name: text
145-
plugin:
146-
wasm:
147-
module:
148-
oci: ghcr.io/shark/wasm-workflows-plugin-example-ferris-says:latest
149-
```
150-
151-
The `wasm` template will produce an output parameter `text` with an awesome message:
104+
The workflow produces an output parameter `text` with a cool message:
152105

153106
```
154107
___________________
@@ -163,103 +116,27 @@ The `wasm` template will produce an output parameter `text` with an awesome mess
163116
/ '-----' \
164117
```
165118

166-
Input and output parameters between workflow steps work just like you'd expect. Other features like artifacts may still be on the [roadmap](#roadmap) though, which is advised to check for your use case.
167-
168119
### Module Development
169120

170-
Creating a new Wasm module is easy and works with every language.
171-
172-
There are ready-to-use templates for:
173-
174-
* [AssemblyScript](wasm-modules/templates/assemblyscript/)
175-
* [Rust](wasm-modules/templates/rust/)
176-
* [TinyGo](wasm-modules/templates/tinygo/)
177-
178-
You implement a [WASI](https://wasi.dev) module. WASI is a modular system interface for Wasm. The principle is easy: the module is given its input in a file at `/work/input.json`. It is expected to write its results to a file at `/work/result.json` and exit.
179-
180-
We created an easy-to-use wrapper for Rust. The wrapper abstracts all the file handling magic and lets you implement a function with a signature like this:
121+
Creating a new Wasm module for use with Argo Workflows is described in the [Module Development Guide](doc/module-development.md).
181122

182-
```rust
183-
fn run(invocation: PluginInvocation) -> anyhow::Result<PluginResult> {
184-
// This is where your code goes
185-
186-
PluginResult {
187-
phase: Phase::Succeeded,
188-
message: "Done".to_string(),
189-
outputs: Default::default(),
190-
}
191-
}
192-
```
193-
194-
For any other language you can easily parse the JSON yourself:
195-
196-
* PluginInvocation: [Example](crates/workflow-model/doc/plugin-invocation.example.json), [Schema](crates/workflow-model/doc/plugin-invocation.schema.json)
197-
* PluginResult: [Example](crates/workflow-model/doc/plugin-result.example.json), [Schema](crates/workflow-model/doc/plugin-result.schema.json)
198-
199-
### Capabilities
200-
201-
Capabilities expand what modules can do. Out of the box, modules can take input parameters and artifacts and produce some output. Take a look at the [capabilities for wasmCloud](https://wasmcloud.dev/reference/host-runtime/capabilities/) for a more complete list of useful capabilities. The capabilities that this plugin offers will be extended in the future.
202-
203-
#### HTTP Capability
204-
205-
The HTTP capability provider allows you to make HTTP requests from your Wasm module. The capability is available in every module mode. Please refer to the [`wasi-experimental-http`](https://github.com/deislabs/wasi-experimental-http) repository for complete information of how to access the HTTP capability from your module. There you will find examples for both Rust and AssemblyScript.
206-
207-
When using the HTTP capability, you need to whitelist the hosts that the module is allowed to connect to. This illustrates the ease-of-use that WebAssembly's capability-oriented security model offers: for you, it's very easy to tell if a module should be able to connect outside – and now securing your code got easy.
208-
209-
You can find a full-featured module at [`wasm-modules/contrib/http-request`](wasm-modules/contrib/http-request/).
210-
211-
The module supports the following input parameters:
212-
213-
* `url`: the URL that you want to call
214-
* `method`: HTTP request method (e.g. `GET`, `POST`, etc.) – optional, defaults to `GET`
215-
* `body`: HTTP request body as a string – optional
216-
* `content_type`: HTTP request body content type (e.g. `application/json`) – optional
217-
218-
As a result, you get the following output parameters:
219-
220-
* `status_code`: HTTP response status code as a number (e.g. `200`)
221-
* `body`: HTTP response body as a string
222-
* `content_type`: HTTP response body content type (e.g. `text/plain`)
223-
224-
The `http-request` module can be used in a workflow like so:
225-
226-
```yaml
227-
- name: wasm
228-
inputs:
229-
parameters:
230-
- name: url
231-
value: https://httpbin.org/post
232-
- name: method
233-
value: POST
234-
- name: body
235-
value: Hello World
236-
- name: content_type
237-
value: text/plain
238-
plugin:
239-
wasm:
240-
module:
241-
oci: ghcr.io/shark/wasm-workflows-plugin-http-request:latest
242-
permissions:
243-
http:
244-
allowed_hosts:
245-
- https://httpbin.org
246-
```
123+
### Advanced Features
247124

248-
### Execution Modes
125+
* **Distributed Execution**
249126

250-
The plugin has two modes of how it can execute a Wasm module.
127+
The plugin will run Wasm modules within the plugin process by default. This is the recommended mode because it's easy to set up and is powerful enough for most scenarios.
251128

252-
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.
129+
The distributed mode creates pods for Wasm modules in a workflow task, much like Argo does for Docker containers.
253130

254-
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).
131+
[Read more in the Distributed Execution Guide.](doc/distributed-mode.md)
255132

256133
## Roadmap
257134

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

260137
## Contributing
261138

262-
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
139+
Contributions make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
263140

264141
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
265142
Don't forget to give the project a star! Thanks again!

doc/benefits.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Benefits
2+
3+
* :lock: **Security**
4+
5+
The [list of things to do](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html) when you want to run containers securely is long and the topic is more complex than even ambitious users care about. Containers are [vulnerable in many ways](https://ieeexplore.ieee.org/document/8693491) because of their denylist approach to security: they're allowed to do many things by default.
6+
7+
WebAssembly's security model is the opposite. As with smartphone apps, they must be given permission for potentially infringing tasks. For example, you might want to give a module the permission to read and write files but not communicate over the internet.
8+
9+
Container images from third parties you don't know are usually a security nightmare. With WebAssembly, you can run code you don't fully trust with more confidence. Say you have a workflow step that renders Markdown. When the author of your Markdown parser container image decides to deliver a crypto miner instead, most Kubernetes setups will happily run it. If you were using this project and a WebAssembly module: zero chance, since it's easy for you to know that the step doesn't need the network but only takes an input parameter and produces some output. [This example is not made up](https://www.trendmicro.com/vinfo/fr/security/news/virtualization-and-cloud/malicious-docker-hub-container-images-cryptocurrency-mining).
10+
11+
<details>
12+
<summary>More about the difference between containers and Wasm modules</summary>
13+
<img src="doc/container-vs-wasm.png" style="max-width: 700px">
14+
<p>Linux processes use more than 300 system calls for any task that involves sharing data with outside of a process. Containers are a combination of different Linux Kernel technologies (namespaces, cgroups etc.) that segment one computer into many seemlingly independent containers. But this very much depends on a) the secure implementation of all syscalls not to leak anything and b) trust in the application inside the container to do what the user intends it to.</p>
15+
<p>Wasm modules are very restricted by default. We use application-level capabilities to allow them to access external resources like the network, S3 object stores, or the filesystem. The modules are the capability consumers, the Wasm runtime is the capability provider. The capability provider translates the requests from the Wasm module and acts as a secure proxy to the outside.</p>
16+
</details>
17+
18+
* :runner: **Performance**
19+
20+
Containers have some overhead: for each workflow step, Argo creates new Kubernetes Pod. This Pod has several containers to enable all the Argo features, your code is just one of them. All the containers must execute, then results are gathered and sent back to Argo. This all takes time: container images are often towards 100s of megabytes, they may rely on interpreted languages like Python or have huge dependencies leading to a slow start time. You may know the [Cold Start issue](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/) with Function-as-a-Service. In Argo, every workflow step is a cold start.
21+
22+
Because WebAssembly modules don't have to bring a whole operating system, they're much smaller. And there is less setup work to do, even for interpreted languages. This means that a module can be run in a matter of milliseconds rather than tens of seconds.

0 commit comments

Comments
 (0)