├── examples ├── add │ ├── .gitignore │ ├── src │ │ └── lib.rs │ ├── Cargo.toml │ └── README.md ├── hello │ ├── .gitignore │ ├── src │ │ └── main.rs │ ├── Cargo.toml │ └── README.md └── fib │ └── fibonacci.wat ├── http_server ├── .gitignore ├── Containerfile ├── Cargo.toml ├── k8s-http-server.yaml └── src │ └── main.rs └── k8s ├── scripts ├── install-k8s.sh ├── kubernetes-crio-server.yml ├── http_server_application.sh └── install-crio.sh └── Vagrantfile /examples/add/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | build 5 | node_modules 6 | *.swp 7 | -------------------------------------------------------------------------------- /http_server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | build 5 | node_modules 6 | *.swp 7 | -------------------------------------------------------------------------------- /examples/add/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[no_mangle] 2 | pub fn add(a: i32, b: i32) -> i32 { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /examples/hello/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | build 5 | node_modules 6 | *.swp 7 | -------------------------------------------------------------------------------- /http_server/Containerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD target/wasm32-wasi/release/http_server.wasm / 3 | CMD ["/http_server.wasm"] 4 | -------------------------------------------------------------------------------- /examples/hello/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | fn main() { 4 | println!("hello"); 5 | for argument in env::args().skip(1) { 6 | println!("{}", argument); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello" 3 | version = "0.1.0" 4 | authors = ["ubuntu"] 5 | edition = "2018" 6 | 7 | [[bin]] 8 | name = "hello" 9 | path = "src/main.rs" 10 | 11 | [dependencies] 12 | -------------------------------------------------------------------------------- /examples/add/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "add" 3 | version = "0.1.0" 4 | authors = ["ubuntu"] 5 | edition = "2018" 6 | 7 | [lib] 8 | name = "add" 9 | path = "src/lib.rs" 10 | crate-type =["cdylib"] 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /http_server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http_server" 3 | version = "0.1.0" 4 | authors = ["csh"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | httpcodec = "0.2.3" 11 | bytecodec = "0.4.15" 12 | wasmedge_wasi_socket = { path = "../../../second-state/wasmedge_wasi_socket/" } 13 | #wasmedge_wasi_socket = "0.4.3" 14 | -------------------------------------------------------------------------------- /examples/fib/fibonacci.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32) (result i32))) 3 | (func $fib (type 0) (param $n i32) (result i32) 4 | local.get $n 5 | i32.const 2 6 | i32.lt_s 7 | if ;; label = @1 8 | i32.const 1 9 | return 10 | end 11 | local.get $n 12 | i32.const 2 13 | i32.sub 14 | call $fib 15 | local.get $n 16 | i32.const 1 17 | i32.sub 18 | call $fib 19 | i32.add 20 | return) 21 | (export "fib" (func $fib))) 22 | -------------------------------------------------------------------------------- /examples/add/README.md: -------------------------------------------------------------------------------- 1 | # WASI standalone app 2 | 3 | In this example, we demonstrate how to run a standalone WASM application from the command line. 4 | 5 | ## Prerequisites 6 | 7 | [Install Rust](https://www.rust-lang.org/tools/install) 8 | 9 | Install WasmEdge by downloading and extracting the `wasmedge` binary executable file from [project release package](https://github.com/WasmEdge/WasmEdge/releases/). 10 | 11 | ## Build the WASM bytecode 12 | 13 | ``` 14 | $ cargo build --target wasm32-wasi 15 | ``` 16 | 17 | ## Run the application from command line 18 | 19 | We will use `wasmedge` in reactor mode to run the program. 20 | 21 | ``` 22 | $ wasmedge --reactor target/wasm32-wasi/debug/add.wasm add 2 2 23 | 4 24 | ``` 25 | 26 | -------------------------------------------------------------------------------- /examples/hello/README.md: -------------------------------------------------------------------------------- 1 | # WASI standalone app 2 | 3 | In this example, we demonstrate how to run a standalone WASM application from the command line. 4 | 5 | ## Prerequisites 6 | 7 | [Install Rust](https://www.rust-lang.org/tools/install) 8 | 9 | Install WasmEdge by downloading and extracting the `wasmedge` binary executable file from [project release package](https://github.com/WasmEdge/WasmEdge/releases/). 10 | 11 | ## Build the WASM bytecode 12 | 13 | ``` 14 | $ rustup target add wasm32-wasi 15 | $ cargo build --target wasm32-wasi 16 | ``` 17 | 18 | ## Run the application from command line 19 | 20 | We will use the `wasmedge` command to run the program. 21 | 22 | ``` 23 | $ wasmedge target/wasm32-wasi/debug/hello.wasm second state 24 | hello 25 | second 26 | state 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /http_server/k8s-http-server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: wasm-http-server 5 | annotations: 6 | module.wasm.image/variant: compat 7 | labels: 8 | name: wasm-http-server 9 | spec: 10 | containers: 11 | - name: http-server 12 | image: quay.io/ifont/wasm_http_server:latest 13 | command: [ "/http_server.wasm" ] 14 | ports: 15 | - containerPort: 1234 16 | protocol: TCP 17 | livenessProbe: 18 | tcpSocket: 19 | port: 1234 20 | initialDelaySeconds: 3 21 | periodSeconds: 30 22 | imagePullPolicy: Always 23 | securityContext: 24 | allowPrivilegeEscalation: false 25 | runAsNonRoot: true 26 | runAsUser: 1000 27 | seccompProfile: 28 | type: RuntimeDefault 29 | capabilities: 30 | drop: 31 | - "ALL" 32 | -------------------------------------------------------------------------------- /k8s/scripts/install-k8s.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt-get update 3 | echo -e "Running Wasm in Kubernetes (k8s) ..." 4 | echo -e "Installing Go" 5 | wget https://golang.org/dl/go1.17.3.linux-amd64.tar.gz 6 | sudo rm -rf /usr/local/go 7 | sudo tar -C /usr/local -xzf go1.17.3.linux-amd64.tar.gz 8 | echo -e "\nexport PATH=$PATH:/usr/local/go/bin" | tee -i -a /home/${USER}/.profile 9 | source /home/${USER}/.profile 10 | echo -e "Defaults secure_path=\"/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin\"" | sudo tee -i /etc/sudoers.d/gofile 11 | echo -e "Cloning Kubernetes ..." 12 | git clone https://github.com/kubernetes/kubernetes.git 13 | cd kubernetes/ 14 | git checkout v1.22.2 15 | cd ../ 16 | echo -e "Installing etcd" 17 | sudo apt-get install -y net-tools 18 | sudo CGROUP_DRIVER=systemd CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='unix:///var/run/crio/crio.sock' ./kubernetes/hack/install-etcd.sh 19 | export PATH="/home/${USER}/kubernetes/third_party/etcd:${PATH}" 20 | sudo cp -rp ./kubernetes/third_party/etcd/etcd* /usr/local/bin/ 21 | echo -e "Building and running k8s with CRI-O" 22 | sudo apt-get install -y build-essential 23 | sudo -b CGROUP_DRIVER=systemd CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='unix:///var/run/crio/crio.sock' ./kubernetes/hack/local-up-cluster.sh 24 | -------------------------------------------------------------------------------- /k8s/scripts/kubernetes-crio-server.yml: -------------------------------------------------------------------------------- 1 | name: k8s-crio http server 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | logLevel: 7 | description: 'Log level' 8 | required: true 9 | default: 'info' 10 | push: 11 | branches: [ main ] 12 | pull_request: 13 | branches: [ main ] 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: ubuntu-20.04 19 | 20 | steps: 21 | 22 | - name: Install apt-get packages 23 | run: | 24 | sudo ACCEPT_EULA=Y apt-get update 25 | sudo ACCEPT_EULA=Y apt-get upgrade 26 | sudo ACCEPT_EULA=Y apt-get install git wget 27 | 28 | - name: Install CRI-O and crun 29 | run: | 30 | wget -qO- https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/crio/install.sh | bash 31 | 32 | - name: Installing and starting k8s 33 | run: | 34 | wget -qO- https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/kubernetes_crio/install.sh | bash > k8s.log 2>&1 35 | 36 | - name: Sleep for 1200s 37 | run: sleep 1200s 38 | shell: bash 39 | 40 | - name: Run WasmEdge in k8s 41 | run: | 42 | cat k8s.log 43 | wget -qO- https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/kubernetes_crio/http_server/http_server_application.sh | bash 44 | -------------------------------------------------------------------------------- /k8s/scripts/http_server_application.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export KUBERNETES_PROVIDER=local 4 | 5 | sudo ./kubernetes/cluster/kubectl.sh config set-cluster local --server=https://localhost:6443 --certificate-authority=/var/run/kubernetes/server-ca.crt 6 | sudo ./kubernetes/cluster/kubectl.sh config set-credentials myself --client-key=/var/run/kubernetes/client-admin.key --client-certificate=/var/run/kubernetes/client-admin.crt 7 | sudo ./kubernetes/cluster/kubectl.sh config set-context local --cluster=local --user=myself 8 | sudo ./kubernetes/cluster/kubectl.sh config use-context local 9 | sudo ./kubernetes/cluster/kubectl.sh 10 | 11 | sudo ./kubernetes/cluster/kubectl.sh cluster-info 12 | # sudo ./kubernetes/cluster/kubectl.sh run -i --expose --port=1234 --restart=Never http-server --image=avengermojo/http_server:with-wasm-annotation --annotations="module.wasm.image/variant=compat" --overrides='{"kind":"Pod", "apiVersion":"v1", "spec": {"hostNetwork": true}}' /http_server.wasm 13 | 14 | wget https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/kubernetes_crio/http_server/k8s-http_server.yaml 15 | sudo ./kubernetes/cluster/kubectl.sh apply -f k8s-http_server.yaml 16 | 17 | echo -e "Pulling image from the docker hub..." 18 | sleep 60 19 | 20 | sudo ./kubernetes/cluster/kubectl.sh get pod --all-namespaces -o wide 21 | 22 | echo -e "\n\nTesting\n\n" 23 | curl -d "name=WasmEdge" -X POST http://127.0.0.1:1234 24 | echo -e "\n\nFinished\n\n" 25 | echo -e "Done!" 26 | -------------------------------------------------------------------------------- /http_server/src/main.rs: -------------------------------------------------------------------------------- 1 | use bytecodec::DecodeExt; 2 | use httpcodec::{HttpVersion, ReasonPhrase, Request, RequestDecoder, Response, StatusCode}; 3 | use std::io::{Read, Write}; 4 | use wasmedge_wasi_socket::{Shutdown, TcpListener, TcpStream}; 5 | 6 | fn handle_http(req: Request) -> bytecodec::Result> { 7 | Ok(Response::new( 8 | HttpVersion::V1_0, 9 | StatusCode::new(200)?, 10 | ReasonPhrase::new("")?, 11 | format!("echo: {}\n", req.body()), 12 | )) 13 | } 14 | 15 | fn handle_client(mut stream: TcpStream) -> std::io::Result<()> { 16 | let mut buff = [0u8; 1024]; 17 | let mut data = Vec::new(); 18 | 19 | loop { 20 | let n = stream.read(&mut buff)?; 21 | data.extend_from_slice(&buff[0..n]); 22 | if n < 1024 { 23 | break; 24 | } 25 | } 26 | 27 | let mut decoder = 28 | RequestDecoder::>::default(); 29 | 30 | let req = match decoder.decode_from_bytes(data.as_slice()) { 31 | Ok(req) => handle_http(req), 32 | Err(e) => Err(e), 33 | }; 34 | 35 | let r = match req { 36 | Ok(r) => r, 37 | Err(e) => { 38 | let err = format!("{:?}", e); 39 | Response::new( 40 | HttpVersion::V1_0, 41 | StatusCode::new(500).unwrap(), 42 | ReasonPhrase::new(err.as_str()).unwrap(), 43 | err.clone(), 44 | ) 45 | } 46 | }; 47 | 48 | let write_buf = r.to_string(); 49 | stream.write(write_buf.as_bytes())?; 50 | stream.shutdown(Shutdown::Both)?; 51 | Ok(()) 52 | } 53 | 54 | fn main() -> std::io::Result<()> { 55 | let port = std::env::var("PORT").unwrap_or("1234".to_string()); 56 | println!("new connection at {}", port); 57 | let listener = TcpListener::bind(format!("0.0.0.0:{}", port), false)?; 58 | loop { 59 | let _ = handle_client(listener.accept(false)?.0); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /k8s/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure("2") do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://vagrantcloud.com/search. 15 | config.vm.box = "generic/ubuntu2004" 16 | 17 | # Disable automatic box update checking. If you disable this, then 18 | # boxes will only be checked for updates when the user runs 19 | # `vagrant box outdated`. This is not recommended. 20 | # config.vm.box_check_update = false 21 | 22 | # Create a forwarded port mapping which allows access to a specific port 23 | # within the machine from a port on the host machine. In the example below, 24 | # accessing "localhost:8080" will access port 80 on the guest machine. 25 | # NOTE: This will enable public access to the opened port 26 | # config.vm.network "forwarded_port", guest: 80, host: 8080 27 | 28 | # Create a forwarded port mapping which allows access to a specific port 29 | # within the machine from a port on the host machine and only allow access 30 | # via 127.0.0.1 to disable public access 31 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 32 | 33 | # Create a private network, which allows host-only access to the machine 34 | # using a specific IP. 35 | # config.vm.network "private_network", ip: "192.168.33.10" 36 | 37 | # Create a public network, which generally matched to bridged network. 38 | # Bridged networks make the machine appear as another physical device on 39 | # your network. 40 | # config.vm.network "public_network" 41 | 42 | # Share an additional folder to the guest VM. The first argument is 43 | # the path on the host to the actual folder. The second argument is 44 | # the path on the guest to mount the folder. And the optional third 45 | # argument is a set of non-required options. 46 | # config.vm.synced_folder "./", "/vagrant_data" 47 | 48 | # Provider-specific configuration so you can fine-tune various 49 | # backing providers for Vagrant. These expose provider-specific options. 50 | # Example for VirtualBox: 51 | # 52 | # config.vm.provider "virtualbox" do |vb| 53 | # # Display the VirtualBox GUI when booting the machine 54 | # vb.gui = true 55 | # 56 | # # Customize the amount of memory on the VM: 57 | # vb.memory = "1024" 58 | # end 59 | config.vm.provider "libvirt" do |vb| 60 | # Customize the amount of memory on the VM: 61 | vb.memory = "8192" 62 | vb.cpus = "4" 63 | end 64 | # 65 | # View the documentation for the provider you are using for more 66 | # information on available options. 67 | 68 | # Enable provisioning with a shell script. Additional provisioners such as 69 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 70 | # documentation for more information about their specific syntax and use. 71 | # config.vm.provision "shell", inline: <<-SHELL 72 | # apt-get update 73 | # apt-get install -y apache2 74 | # SHELL 75 | end 76 | -------------------------------------------------------------------------------- /k8s/scripts/install-crio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo -e "Starting installation ..." 3 | sudo apt update 4 | export OS="xUbuntu_20.04" 5 | export VERSION="1.21" 6 | echo -e "OS: $OS" 7 | echo -e "Version: $VERSION" 8 | echo -e "Installing libseccomp2 ..." 9 | sudo apt install -y libseccomp2 10 | # Set download URL that we are adding to sources.list.d 11 | export ADD1="deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" 12 | export DEST1="/etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list" 13 | echo -e "Adding \n$ADD1 \nto \n$DEST1" 14 | export ADD2="deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" 15 | export DEST2="/etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list" 16 | echo -e "Adding \n$ADD2 \nto \n$DEST2" 17 | sudo rm -rf "$DEST1" 18 | sudo rm -rf "$DEST2" 19 | sudo touch "$DEST1" 20 | sudo touch "$DEST2" 21 | if [ -f "$DEST1" ] 22 | then 23 | echo "$ADD1" | sudo tee -i "$DEST1" 24 | echo "Success writing to $DEST1" 25 | else 26 | echo "Error writing to $DEST1" 27 | exit 2 28 | fi 29 | 30 | if [ -f "$DEST2" ] 31 | then 32 | echo "$ADD2" | sudo tee -i "$DEST2" 33 | echo "Success writing to $DEST2" 34 | else 35 | echo "Error writing to $DEST2" 36 | exit 2 37 | fi 38 | echo -e "Installing wget" 39 | sudo apt install -y wget 40 | if [ -f Release.key ] 41 | then 42 | rm -rf Release.key 43 | fi 44 | echo -e "Fetching Release.key" 45 | wget "https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key" 46 | echo -e "Adding Release.key" 47 | sudo apt-key add Release.key 48 | echo -e "Deleting Release.key" 49 | rm -rf Release.key 50 | echo -e "Fetching Release.key" 51 | wget "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key" 52 | echo -e "Adding Release.key" 53 | sudo apt-key add Release.key 54 | echo -e "Removing Release.key" 55 | rm -rf Release.key 56 | sudo apt update 57 | sudo apt install -y criu 58 | sudo apt install -y libyajl2 59 | sudo apt install -y cri-o 60 | sudo apt install -y cri-o-runc 61 | sudo apt install -y cri-tools 62 | sudo apt install -y containernetworking-plugins 63 | echo -e "Installing WasmEdge" 64 | if [ -f install.sh ] 65 | then 66 | rm -rf install.sh 67 | fi 68 | wget -q https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh 69 | sudo chmod a+x install.sh 70 | sudo ./install.sh --path="/usr/local" 71 | rm -rf install.sh 72 | echo -e "Building and installing crun" 73 | sudo apt install -y make git gcc build-essential pkgconf libtool libsystemd-dev libprotobuf-c-dev libcap-dev libseccomp-dev libyajl-dev go-md2man libtool autoconf python3 automake 74 | git clone https://github.com/containers/crun 75 | cd crun 76 | ./autogen.sh 77 | ./configure --with-wasmedge 78 | make 79 | sudo make install 80 | # sudo cp -f crun /usr/lib/cri-o-runc/sbin/runc 81 | 82 | # wget https://github.com/second-state/crunw/releases/download/1.0-wasmedge/crunw_1.0-wasmedge+dfsg-1_amd64.deb 83 | # sudo dpkg -i --force-overwrite crunw_1.0-wasmedge+dfsg-1_amd64.deb 84 | # rm -rf crunw_1.0-wasmedge+dfsg-1_amd64.deb 85 | # Write config 86 | echo -e "[crio.runtime]\ndefault_runtime = \"crun\"\n" | sudo tee -i /etc/crio/crio.conf 87 | echo -e "\n# Add crun runtime here\n[crio.runtime.runtimes.crun]\nruntime_path = \"/usr/local/bin/crun\"\nruntime_type = \"oci\"\nruntime_root = \"/run/crun\"\n" | sudo tee -i -a /etc/crio/crio.conf.d/01-crio-runc.conf 88 | 89 | sudo systemctl restart crio 90 | echo -e "Finished" 91 | --------------------------------------------------------------------------------