diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5de3225..8c64cba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,12 +132,26 @@ jobs: IMAGE_TAG="${GITHUB_SHA}" \ RUNTIME_PROFILE=rrt + - name: Verify systemd container identity in the image + run: | + docker image inspect "akernel-ci/all-in-one:${GITHUB_SHA}" \ + --format '{{json .Config.Env}}' | \ + python -c 'import json, sys; assert "container=oci" in json.load(sys.stdin)' + - name: Start standalone AKernel run: | IMAGE="akernel-ci/all-in-one:${GITHUB_SHA}" \ AKERNEL_NAT_BACKEND=iptables \ ./deploy/standalone/start.sh + - name: Verify PID 1 detects its container + run: | + docker exec akernel-node bash -euo pipefail -c ' + tr "\0" "\n" < /proc/1/environ | grep -x "container=oci" + test "$(cat /run/systemd/container)" = oci + systemd-detect-virt --container + ' + - name: Run SDK end-to-end examples run: | gateway_ip="$(docker inspect \ diff --git a/AGENTS.md b/AGENTS.md index b018765..2c72a0e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -183,6 +183,13 @@ Use [`deploy/README.md`](./deploy/README.md) as the deployment entry point. AKernel supports standalone, existing Kubernetes clusters via Helm, and Terraform-based cloud provisioning. +The all-in-one image and node launchers declare lowercase `container=oci` +for PID 1 systemd. Preserve this in the final image, Helm node environment, +and standalone launcher: without container detection, privileged systemd +shutdown can remount shared host filesystems read-only. See +[`deploy/README.md#systemd-container-identity`](./deploy/README.md#systemd-container-identity) +for deployment implications. + Aliyun's aggregate Pod PID budget is configurable independently of the per-sandbox limit; see `deploy/terraform/aliyun/README.md#pod-pid-budget`. diff --git a/builder/node.Dockerfile b/builder/node.Dockerfile index 16634b0..77ba145 100644 --- a/builder/node.Dockerfile +++ b/builder/node.Dockerfile @@ -233,6 +233,9 @@ COPY ./src/distill-fs/ ./ RUN cargo build --locked --release --bin distill_fs FROM ${AKERNEL_NODE_BASE_IMAGE} +# Let PID 1 systemd avoid remounting shared host filesystems during shutdown. +ENV container=oci + ARG AKERNEL_ENABLE_KATA ARG AKERNEL_ENABLE_RUNC ARG AKERNEL_ENABLE_FIRECRACKER diff --git a/deploy/README.md b/deploy/README.md index 63940e0..6788897 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -71,6 +71,14 @@ The node must support TC eBPF and bpffs. bpfnat does not manage host firewall policy, so custom host-network deployments must allow forwarding to and from the sandbox bridge when their `FORWARD` policy is `DROP`. +### systemd container identity + +The all-in-one image, Helm node template, and standalone launcher set +`container=oci` so PID 1 systemd recognizes the container and does not remount +shared host filesystems read-only during shutdown. Preserve this variable in +custom launchers. Applying the fix requires replacing the node Pod or +standalone container; it does not repair an already read-only filesystem. + ### Network ACLs The bundled standalone, Helm, and Terraform sandboxd configurations enable diff --git a/deploy/akernel/charts/core/templates/node/daemonset.yaml b/deploy/akernel/charts/core/templates/node/daemonset.yaml index 01eb11d..a9e2561 100644 --- a/deploy/akernel/charts/core/templates/node/daemonset.yaml +++ b/deploy/akernel/charts/core/templates/node/daemonset.yaml @@ -76,6 +76,9 @@ spec: resources: {{- toYaml .Values.node.resources | nindent 10 }} env: + # Required for systemd shutdown safety, including with older images. + - name: container + value: "oci" - name: AKERNEL_ROLE value: "node" - name: RUNSC_AKERNEL diff --git a/deploy/standalone/start.sh b/deploy/standalone/start.sh index 8faed46..9d1a20a 100755 --- a/deploy/standalone/start.sh +++ b/deploy/standalone/start.sh @@ -361,6 +361,7 @@ start_node_container() { --privileged \ --net bridge \ --restart always \ + -e container=oci \ -e AKS_LOCAL_MODE="true" \ -e YR_RRT_CONTROL_SOCKET_PATH="/run/akernel" \ -e YR_IMAGE_PROCESS_CONFIG="${YR_IMAGE_PROCESS_CONFIG}" \