Skip to content

WasmEdge crun部署踩坑记

云微 edited this page Mar 5, 2023 · 1 revision

前置需求

  • Ubuntu20

    • 可能也可以用别的版本,但官方提供的安装脚本只能在Ubuntu20下运行
  • 这台Ubuntu20的机器要能够在不显式对程序指定代理的情况下访问github

    • 可以是网络环境在境外,也可以是全局代理
    • 安装程序运行过程中会从github下载一些文件,下载过程无法轻易通过环境变量/修改代码来设置代理

核心参考

步骤

curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -e all -p /usr/local

安装脚本会从github下载许多文件,所以此步骤需要对github的流畅连接

安装完成后进行简单的小测试:

root@newoj:~# /usr/local/bin/wasmedge opensnoop.wasm

attach ok
PID    COMM              FD ERR PATH
1685033 systemd-udevd     -1   2 /run/udev/queue
1685033 systemd-udevd     14   0 /run/udev/queue
32750  systemd-udevd     15   0 /proc/self/oom_score_adj
32750  systemd-udevd     -1   2 /sys/kernel/slab/:A-0000072/cgroup/eventpoll_pwq(566075:session-16852.scope)/uevent
32750  systemd-udevd     -1   2 /sys/kernel/slab/:A-0000072/cgroup/eventpoll_pwq(566075:session-16852.scope)/uevent
32750  systemd-udevd     -1   2 /run/udev/data/+cgroup:eventpoll_pwq(566075:session-16852.scope)
32750  systemd-udevd      6   0 /
  • 然后构建带有WasmEdge支持的底层运行时crun
sudo apt update
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

git clone https://github.com/containers/crun
cd crun
./autogen.sh
./configure --with-wasmedge
make
sudo make install
  • 注意--with-wasmedge参数,此参数用以指明为crun编译WasmEdge支持。
  • 由于构建过程需要使用WasmEdge的头文件,所以需要在上一步中预先安装好WasmEdge

接下来安装CRI-O。

export OS="xUbuntu_20.04"
export VERSION="1.21"
apt update
apt install -y libseccomp2 || sudo apt update -y libseccomp2
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

apt-get update
apt-get install criu libyajl2
apt-get install cri-o cri-o-runc cri-tools containernetworking-plugins
systemctl start crio

安装完成后创建以下配置文件:

/etc/crio/crio.conf

[crio.runtime]
default_runtime = "crun"

并修改/etc/crio/crio.conf.d/01-crio-runc.conf,增加以下部分

# Add our crunw runtime here
[crio.runtime.runtimes.crun]
runtime_path = "/usr/bin/crun"
runtime_type = "oci"
runtime_root = "/run/crun"

接下来重启CRI-O

systemctl restart crio

测试

运行测试用例

sudo crictl pull docker.io/hydai/wasm-wasi-example:with-wasm-annotation
wget https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/crio/sandbox_config.json
wget https://raw.githubusercontent.com/second-state/wasmedge-containers-examples/main/crio/container_wasi.json

# Create the POD. Output will be different from example.
POD_ID=$(sudo crictl runp sandbox_config.json)

# Create the container instance. Output will be different from example.
CONTAINER_ID=$(sudo crictl create $POD_ID container_wasi.json sandbox_config.json)

sudo crictl start $CONTAINER_ID

sudo crictl logs $CONTAINER_ID

预期输出如下:

Test 1: Print Random Number
Random number: 960251471

Test 2: Print Random Bytes
Random bytes: [50, 222, 62, 128, 120, 26, 64, 42, 210, 137, 176, 90, 60, 24, 183, 56, 150, 35, 209, 211, 141, 146, 2, 61, 215, 167, 194, 1, 15, 44, 156, 27, 179, 23, 241, 138, 71, 32, 173, 159, 180, 21, 198, 197, 247, 80, 35, 75, 245, 31, 6, 246, 23, 54, 9, 192, 3, 103, 72, 186, 39, 182, 248, 80, 146, 70, 244, 28, 166, 197, 17, 42, 109, 245, 83, 35, 106, 130, 233, 143, 90, 78, 155, 29, 230, 34, 58, 49, 234, 230, 145, 119, 83, 44, 111, 57, 164, 82, 120, 183, 194, 201, 133, 106, 3, 73, 164, 155, 224, 218, 73, 31, 54, 28, 124, 2, 38, 253, 114, 222, 217, 202, 59, 138, 155, 71, 178, 113]

Test 3: Call an echo function
Printed from wasi: This is from a main function
This is from a main function

Test 4: Print Environment Variables
The env vars are as follows.
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
TERM: xterm
HOSTNAME: crictl_host
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
The args are as follows.
/var/lib/containers/storage/overlay/006e7cf16e82dc7052994232c436991f429109edea14a8437e74f601b5ee1e83/merged/wasi_example_main.wasm
50000000

Test 5: Create a file `/tmp.txt` with content `This is in a file`

Test 6: Read the content from the previous file
File content is This is in a file

Test 7: Delete the previous file

运行opensnoop

参考上一个测试,但

  • 需要预先运行docker pull docker.io/officeyutong/opensnoop-wasm:latest

  • 修改container_wasi.json的内容为:

{
  "metadata": {
    "name": "opensnoop"
  },
  "image": {
    "image": "officeyutong/opensnoop-wasm:latest"
  },
  "args": [
    "/opensnoop.wasm"
  ],
  "working_dir": "/",
  "envs": [],
  "tier": "backend",
  "annotations": {
    "module.wasm.image/variant": "compat-smart"
  },
  "log_path": "",
  "stdin": false,
  "stdin_once": false,
  "tty": false,
  "linux": {
    "resources": {
      "memory_limit_in_bytes": 209715200,
      "cpu_period": 10000,
      "cpu_quota": 20000,
      "cpu_shares": 512,
      "oom_score_adj": 30,
      "cpuset_cpus": "0",
      "cpuset_mems": "0"
    },
    "security_context": {
      "namespace_options": {
        "pid": 1
      },
      "readonly_rootfs": false,
      "capabilities": {
        "add_capabilities": [
          "sys_admin"
        ]
      }
    }
  }
}

附录 - 在WasmEdge容器中使用WasmEdge插件

由于安全原因,WasmEdge容器不提供插件支持(见https://github.com/WasmEdge/WasmEdge/discussions/2327),但可以通过修改代码方式提供插件支持。

在crun源代码目录下,修改src/libcrun/handlers/wasmedge.c,在libwasmedge_exec函数中,参考上下文插入以下代码:

// 放到开头的一串函数指针声明那里
void (*WasmEdge_PluginLoadWithDefaultPaths) (void); 

// 放到一大堆dlsym那里
WasmEdge_PluginLoadWithDefaultPaths = dlsym(cookie, "WasmEdge_PluginLoadWithDefaultPaths");

// 放到对WasmEdge_ModuleInstanceInitWASI(...)的调用前面
WasmEdge_PluginLoadWithDefaultPaths();

修改完成后,重新从./autogen.sh开始执行编译构建流程即可。

附录 - 容器启动超时

启动容器时经常会出现:

error: timed out waiting for the condition

目前暂时没有找到解决方案。