Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Cargo / build artifacts
target/
contest-target/
bin/

# Built binaries dropped at repo root by scripts/build.sh
youki
runtimetest
contest

# Test fixtures (not needed for image builds)
bundle.tar.gz
test.log

# Git / CI metadata (not used inside images)
.git/
.github/

# Docs build outputs
docs/book/book/

# IDE / editor / OS noise
.idea/
.vscode/
*.swp
*.swo
.DS_Store

# Misc
node_modules/
*.log
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]
resolver = "2"
members = ["crates/*", "tests/contest/*", "tools/*"]
exclude = ["experiment/seccomp", "experiment/selinux"]
exclude = ["experiment/seccomp", "experiment/selinux", "tools/youki-deploy"]

[workspace.dependencies]
anyhow = "1.0.102"
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [liboci-cli](./user/liboci_cli.md)
- [libseccomp](./user/libseccomp.md)
- [Webassembly](./user/webassembly.md)
- [Kubernetes](./user/kubernetes.md)

---

Expand Down
29 changes: 29 additions & 0 deletions docs/src/developer/e2e/kubernetes_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

This test verifies that youki works correctly as a container runtime in a Kubernetes environment using [Kind](https://kind.sigs.k8s.io/) (Kubernetes in Docker).

## Single Node deploy test

The test builds a custom Kind node image with youki, creates a cluster, and deploys nginx pods using a RuntimeClass that specifies youki as the runtime.

## Local
Expand All @@ -17,3 +19,30 @@ To clean up an existing Kind cluster first:
```console
$ just clean-test-kind
```

## Multi Node deploy test

In addition to the single-node `test-kind` flow above, there is a
multi-node variant that mirrors how youki would be installed on a real
Kubernetes cluster: the cluster nodes themselves stay as vanilla
`kindest/node` images, and a DaemonSet running on every node
installs youki onto the host and registers it with containerd at
runtime.

### Local

```console
$ just test-kind-deploy
```

Or to only stand up the cluster + DaemonSet without the nginx smoke test:

```console
$ just kind-deploy
```

Clean up:

```console
$ just clean-test-kind-deploy
```
1 change: 1 addition & 0 deletions docs/src/user/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ This is divided into following sub-sections :
- liboci-cli
- libseccomp
- Webassembly : This explains how to use webassembly module with youki.
- Kubernetes : This explains how to install youki on a Kubernetes cluster as the OCI runtime via the youki-deploy DaemonSet.
75 changes: 75 additions & 0 deletions docs/src/user/kubernetes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Using youki as a Kubernetes runtime

youki implements the OCI runtime spec, so it can be plugged into any
Kubernetes cluster. Once youki is installed on each node and the
node's container runtime is configured to know about it, individual
Pods can opt in via `runtimeClassName: youki`.

## youki-deploy: ready-to-use installer for kind / containerd

The repository ships a small installer under
[`tools/youki-deploy/`](https://github.com/youki-dev/youki/tree/main/tools/youki-deploy)
which automates install the youki binary on every node, and register
it as a containerd runtime. It is composed of:

- A Docker image that bundles the youki release binary and an
`install-youki.sh` script.
- A Kubernetes DaemonSet manifest that runs that image as a privileged
pod on every node, mounts the host's `/usr/local/bin` and
`/etc/containerd`, copies the binary into place, patches
`/etc/containerd/config.toml`, and restarts containerd.

It is currently exercised against [kind](https://kind.sigs.k8s.io/)
(Kubernetes-in-Docker) but the manifests are Kubernetes
resources and should apply to any containerd-based cluster.

## Try it locally on kind

To stand up the cluster + DaemonSet:

```console
$ just kind-deploy
```

To tear it down:

```console
$ just clean-test-kind-deploy
```

See also
[Developer Documentation > Kubernetes test](../developer/e2e/kubernetes_test.md).

## Using youki for your own Pods

Once the DaemonSet is installed, just add `runtimeClassName: youki` to
the pod spec:

```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-youki
spec:
runtimeClassName: youki
containers:
- name: nginx
image: nginx:1.27-alpine
```

Pods without `runtimeClassName` continue to use whatever the cluster's
default OCI runtime is (typically `runc`), so installing youki-deploy
is non-disruptive for existing workloads.

## Caveats

- The installer modifies `/usr/local/bin/youki` and
`/etc/containerd/config.toml` on the host. It does not currently
uninstall on DaemonSet deletion - removing youki and the containerd
config patch must be done manually.
- The DaemonSet manifest references the installer image as
`youki-installer:latest`, which is loaded into the local kind cluster
by `just kind-deploy`. To deploy on a real cluster, build the image
from `tools/youki-deploy/Dockerfile` and push it to a registry that
your cluster nodes can pull from, then update the image field in
`tools/youki-deploy/youki-deploy.yaml`.
35 changes: 35 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ alias build := youki-release
alias youki := youki-dev

KIND_CLUSTER_NAME := 'youki'
KIND_DEPLOY_CLUSTER_NAME := 'youki-deploy'
YOUKI_INSTALLER_IMAGE := 'youki-installer:latest'

cwd := justfile_directory()

Expand Down Expand Up @@ -115,6 +117,39 @@ bin-kind:
clean-test-kind:
kind delete cluster --name {{ KIND_CLUSTER_NAME }}

[private]
kind-cluster-multi:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it’s not idempotent, it would be better to skip it if the cluster already exists.

#!/usr/bin/env bash
set -euo pipefail

kind create cluster \
--name {{ KIND_DEPLOY_CLUSTER_NAME }} \
--config tools/youki-deploy/kind-config.yaml

[private]
youki-installer-image:
docker buildx build \
-f tools/youki-deploy/Dockerfile \
-t {{ YOUKI_INSTALLER_IMAGE }} \
--load .

# install youki on every node of a multi-node kind cluster
kind-deploy: kind-cluster-multi youki-installer-image
kind load docker-image {{ YOUKI_INSTALLER_IMAGE }} --name {{ KIND_DEPLOY_CLUSTER_NAME }}
kubectl --context=kind-{{ KIND_DEPLOY_CLUSTER_NAME }} apply -f tools/youki-deploy/youki-deploy.yaml
kubectl --context=kind-{{ KIND_DEPLOY_CLUSTER_NAME }} -n youki-system rollout status ds/youki-deploy --timeout=180s

# test youki on the deployed multi-node kind cluster
test-kind-deploy: kind-deploy
kubectl --context=kind-{{ KIND_DEPLOY_CLUSTER_NAME }} apply -f tests/k8s/deploy.yaml
kubectl --context=kind-{{ KIND_DEPLOY_CLUSTER_NAME }} wait deployment nginx-deployment --for condition=Available=True --timeout=120s
kubectl --context=kind-{{ KIND_DEPLOY_CLUSTER_NAME }} get pods -o wide
kubectl --context=kind-{{ KIND_DEPLOY_CLUSTER_NAME }} delete -f tests/k8s/deploy.yaml

# Clean kind cluster
clean-test-kind-deploy:
kind delete cluster --name {{ KIND_DEPLOY_CLUSTER_NAME }}

# misc

# run bpftrace hack
Expand Down
24 changes: 24 additions & 0 deletions tools/youki-deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# syntax=docker/dockerfile:1.4

FROM rust:1-slim-bookworm AS youki-build
RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
libsystemd-dev \
build-essential \
libelf-dev \
libseccomp-dev \
libclang-dev \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /youki
COPY . .
RUN cargo build --release -p youki --features "v2 systemd"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We’d like to enable the build cache as shown below.

Suggested change
RUN cargo build --release -p youki --features "v2 systemd"
RUN --mount=type=cache,target=/root/.cargo/registry \
--mount=type=cache,target=/root/.cargo/git \
--mount=type=cache,target=/youki/target \
cargo build --release -p youki --features "v2 systemd" && \
cp target/release/youki /tmp/youki


FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
util-linux \
&& rm -rf /var/lib/apt/lists/*
COPY --from=youki-build /youki/target/release/youki /opt/youki/bin/youki
COPY tools/youki-deploy/install-youki.sh /opt/youki/bin/install-youki.sh
RUN chmod +x /opt/youki/bin/install-youki.sh /opt/youki/bin/youki
ENTRYPOINT ["/opt/youki/bin/install-youki.sh"]
34 changes: 34 additions & 0 deletions tools/youki-deploy/install-youki.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Install youki onto a kind node and register it with containerd.
# Designed to run inside a privileged DaemonSet pod that mounts the host's
# /usr/local/bin and /etc/containerd as hostPath volumes, with hostPID enabled.
set -euo pipefail

HOST_BIN_DIR=${HOST_BIN_DIR:-/host/usr/local/bin}
HOST_CONTAINERD_CONFIG=${HOST_CONTAINERD_CONFIG:-/host/etc/containerd/config.toml}
RUNTIME_HANDLER=${RUNTIME_HANDLER:-youki}
MARKER="# youki-deploy:${RUNTIME_HANDLER}"

echo "[youki-deploy] Installing youki on $(hostname)"

install -m 0755 -D /opt/youki/bin/youki "${HOST_BIN_DIR}/youki"

if grep -qF "${MARKER}" "${HOST_CONTAINERD_CONFIG}"; then
echo "[youki-deploy] containerd already configured, skipping config patch"
else
echo "[youki-deploy] Patching ${HOST_CONTAINERD_CONFIG}"
cat >>"${HOST_CONTAINERD_CONFIG}" <<EOF

${MARKER}
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${RUNTIME_HANDLER}]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${RUNTIME_HANDLER}.options]
BinaryName = "${HOST_BIN_DIR#/host}/youki"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is written with a dependency on the youki-deploy DaemonSet, I’d like to revise it.
Please configure separate default values for HOST_BIN_DIR and REAL_BIN_DIR.

SystemdCgroup = false
EOF
echo "[youki-deploy] Restarting containerd via host PID 1"
nsenter -t 1 -m -u -i -n -p -- systemctl restart containerd
fi

echo "[youki-deploy] Done. Sleeping to keep DaemonSet pod Ready."
exec sleep infinity
6 changes: 6 additions & 0 deletions tools/youki-deploy/kind-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
70 changes: 70 additions & 0 deletions tools/youki-deploy/youki-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: youki-system
labels:
pod-security.kubernetes.io/enforce: privileged
---
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: youki
handler: youki
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please configure scheduling to avoid failures caused by early scheduling.

---
apiVersion: v1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we’re not configuring RBAC or anything similar, deploying a ServiceAccount probably doesn’t provide much value.

kind: ServiceAccount
metadata:
name: youki-deploy
namespace: youki-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: youki-deploy
namespace: youki-system
labels:
app: youki-deploy
spec:
selector:
matchLabels:
app: youki-deploy
template:
metadata:
labels:
app: youki-deploy
spec:
serviceAccountName: youki-deploy
hostPID: true
tolerations:
- operator: Exists
effect: NoSchedule
- operator: Exists
effect: NoExecute
containers:
- name: installer
image: youki-installer:latest
imagePullPolicy: IfNotPresent
securityContext:
privileged: true
env:
- name: HOST_BIN_DIR
value: /host/usr/local/bin
- name: HOST_CONTAINERD_CONFIG
value: /host/etc/containerd/config.toml
- name: RUNTIME_HANDLER
value: youki
volumeMounts:
- name: host-usr-local-bin
mountPath: /host/usr/local/bin
- name: host-etc-containerd
mountPath: /host/etc/containerd
volumes:
- name: host-usr-local-bin
hostPath:
path: /usr/local/bin
type: Directory
- name: host-etc-containerd
hostPath:
path: /etc/containerd
type: Directory
Loading