commit 81d192d577261de600e03a12779e0ca1f6110870832750441c33ad247f030478
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-03-24T13:16:21Z |
| subject | Now we properly preloaded the images without load at boot |
commit 81d192d577261de600e03a12779e0ca1f6110870832750441c33ad247f030478
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-03-24T13:16:21Z
Now we properly preloaded the images without load at boot
---
alpine/preload-k8s-images.sh | 138 ++++++++++++++-----------
alpine/rootfs-extra/opt/scripts/load-images.sh | 56 ----------
alpine/rootfs-extra/opt/scripts/test-crio.sh | 65 ++++++++++++
3 files changed, 141 insertions(+), 118 deletions(-)
diff --git a/alpine/preload-k8s-images.sh b/alpine/preload-k8s-images.sh
index 22388dd..a1aa0f8 100755
--- a/alpine/preload-k8s-images.sh
+++ b/alpine/preload-k8s-images.sh
@@ -4,103 +4,117 @@ set -euo pipefail
: "${KUBE_IMG_CACHE:?KUBE_IMG_CACHE is required}"
: "${KUBE_VERSION:?KUBE_VERSION is required}"
: "${ARCH:?ARCH is required}"
+: "${ROOTFS:?ROOTFS is required}"
OS=linux
-REGISTRY_PORT=5000
-# Keep everything version/arch scoped so caches do not get mixed.
-ARCHIVE_DIR="${KUBE_IMG_CACHE}/archives/${ARCH}/${KUBE_VERSION}"
-REGISTRY_DATA_DIR="${KUBE_IMG_CACHE}/registry-data/${ARCH}/${KUBE_VERSION}"
-REGISTRY_TAR="${KUBE_IMG_CACHE}/registry.tar"
-REGISTRY_IMAGE="docker.io/library/registry:2"
+# IMPORTANT:
+# This must match what the target system will use at runtime.
+# If your target CRI-O uses overlay, leave this as overlay.
+# If overlay seeding fails in your build environment, fix the build env;
+# do not silently switch to vfs unless the target will also use vfs.
+STORAGE_DRIVER="${STORAGE_DRIVER:-overlay}"
-if podman image exists "${REGISTRY_IMAGE}"; then
- echo "Registry image already present: ${REGISTRY_IMAGE}"
+# Optional. Needed by many overlay-in-container setups.
+FUSE_OVERLAYFS="${FUSE_OVERLAYFS:-/usr/bin/fuse-overlayfs}"
-elif [ -f "${REGISTRY_TAR}" ]; then
- echo "Loading registry image from cache: ${REGISTRY_TAR}"
- podman load -i "${REGISTRY_TAR}"
+# Keep archive cache version/arch scoped so downloads do not get mixed.
+ARCHIVE_DIR="${KUBE_IMG_CACHE}/archives/${ARCH}/${KUBE_VERSION}"
-else
- echo "Cache miss → pulling and saving registry image"
+# Seed directly into the target rootfs image store.
+TARGET_GRAPHROOT="${ROOTFS}/var/lib/containers/storage"
- podman pull "${REGISTRY_IMAGE}"
- podman save -o "${REGISTRY_TAR}" "${REGISTRY_IMAGE}"
-fi
+# Build-host temporary runtime state for containers/storage.
+TMPDIR="$(mktemp -d)"
+RUNROOT="${TMPDIR}/runroot"
+STORAGE_CONF="${TMPDIR}/storage.conf"
+
+cleanup() {
+ rm -rf "${TMPDIR}"
+}
+trap cleanup EXIT
mkdir -p "${ARCHIVE_DIR}"
-rm -rf "${REGISTRY_DATA_DIR}"
-mkdir -p "${REGISTRY_DATA_DIR}"
+mkdir -p "${TARGET_GRAPHROOT}"
+mkdir -p "${RUNROOT}"
echo "============================================================"
-echo "Preparing Kubernetes image cache"
+echo "Preparing Kubernetes CRI-O image store"
echo " KUBE_VERSION = ${KUBE_VERSION}"
echo " ARCH = ${ARCH}"
echo " ARCHIVE_DIR = ${ARCHIVE_DIR}"
-echo " REGISTRY_DATA_DIR = ${REGISTRY_DATA_DIR}"
+echo " TARGET_GRAPHROOT = ${TARGET_GRAPHROOT}"
+echo " STORAGE_DRIVER = ${STORAGE_DRIVER}"
echo "============================================================"
-# Start a temporary local registry backed by REGISTRY_DATA_DIR.
-# We use host network here to avoid messing with nested networking.
-podman rm -f temp-registry >/dev/null 2>&1 || true
-
-podman run -d \
- --name temp-registry \
- --network host \
- --cgroups=disabled \
- -v "${REGISTRY_DATA_DIR}:/var/lib/registry" \
- docker.io/library/registry:2
+# Build a temporary containers/storage config that writes directly into
+# the target rootfs image store.
+if [ "${STORAGE_DRIVER}" = "overlay" ]; then
+ cat > "${STORAGE_CONF}" <<EOF
+[storage]
+driver = "overlay"
+runroot = "${RUNROOT}"
+graphroot = "${TARGET_GRAPHROOT}"
+
+[storage.options]
+mount_program = "${FUSE_OVERLAYFS}"
+EOF
+else
+ cat > "${STORAGE_CONF}" <<EOF
+[storage]
+driver = "${STORAGE_DRIVER}"
+runroot = "${RUNROOT}"
+graphroot = "${TARGET_GRAPHROOT}"
+EOF
+fi
-cleanup() {
- podman rm -f temp-registry >/dev/null 2>&1 || true
-}
-trap cleanup EXIT
+export CONTAINERS_STORAGE_CONF="${STORAGE_CONF}"
-# Wait for registry to answer.
-for _ in $(seq 1 30); do
- if curl -fsS "http://127.0.0.1:${REGISTRY_PORT}/v2/" >/dev/null; then
- break
- fi
- sleep 1
-done
+# Sanity check: list required images using the target kubeadm binary.
+mapfile -t kube_images < <(
+ qemu-aarch64-static \
+ "${ROOTFS}/usr/local/bin/kubeadm" \
+ config images list \
+ --kubernetes-version "${KUBE_VERSION}"
+)
-if ! curl -fsS "http://127.0.0.1:${REGISTRY_PORT}/v2/" >/dev/null; then
- echo "Temporary registry did not start"
+if [ "${#kube_images[@]}" -eq 0 ]; then
+ echo "No kubeadm images returned"
exit 1
fi
-# Cache and seed all kubeadm-required images.
-while read -r img; do
- [ -n "$img" ] || continue
+for img in "${kube_images[@]}"; do
+ [ -n "${img}" ] || continue
- safe_name=$(printf '%s' "$img" | sed 's#/#_#g; s#:#__#g')
+ safe_name="$(printf '%s' "${img}" | sed 's#/#_#g; s#:#__#g')"
archive="${ARCHIVE_DIR}/${safe_name}.tar"
- ref="${img#registry.k8s.io/}"
- if [ ! -f "$archive" ]; then
- echo "Caching: $img"
+ if [ ! -f "${archive}" ]; then
+ echo "Caching archive: ${img}"
skopeo copy \
--override-os "${OS}" \
--override-arch "${ARCH}" \
- "docker://$img" \
- "oci-archive:$archive"
+ "docker://${img}" \
+ "oci-archive:${archive}"
else
- echo "Cache hit: $img"
+ echo "Archive hit: ${img}"
fi
- if skopeo inspect --tls-verify=false "docker://127.0.0.1:${REGISTRY_PORT}/${ref}" >/dev/null 2>&1; then
- echo "Registry hit: 127.0.0.1:${REGISTRY_PORT}/${ref}"
+ # If already present in the target containers/storage, skip.
+ if skopeo inspect "containers-storage:${img}" >/dev/null 2>&1; then
+ echo "Store hit: ${img}"
continue
fi
- echo "Seeding registry: $ref"
+ echo "Seeding CRI-O store: ${img}"
skopeo copy \
- --dest-tls-verify=false \
- "oci-archive:$archive" \
- "docker://127.0.0.1:${REGISTRY_PORT}/${ref}"
-done < <(qemu-aarch64-static "$ROOTFS/usr/local/bin/kubeadm" config images list --kubernetes-version "${KUBE_VERSION}")
+ --override-os "${OS}" \
+ --override-arch "${ARCH}" \
+ "oci-archive:${archive}" \
+ "containers-storage:${img}"
+done
echo
echo "Done."
-echo "Archives: ${ARCHIVE_DIR}"
-echo "Registry data: ${REGISTRY_DATA_DIR}"
+echo "Archives: ${ARCHIVE_DIR}"
+echo "CRI-O storage: ${TARGET_GRAPHROOT}"
\ No newline at end of file
diff --git a/alpine/rootfs-extra/opt/scripts/load-images.sh b/alpine/rootfs-extra/opt/scripts/load-images.sh
deleted file mode 100755
index 8700097..0000000
--- a/alpine/rootfs-extra/opt/scripts/load-images.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-set -eu
-
-KUBE_VERSION="${KUBE_VERSION:-v1.35.3}"
-REGISTRY_ADDR="${REGISTRY_ADDR:-127.0.0.1:5000}"
-
-mkdir -p /opt/registry
-cat >/opt/registry/config.yml <<EOF
-version: 0.1
-log:
- level: info
-storage:
- filesystem:
- rootdirectory: /var/lib/registry
-http:
- addr: ${REGISTRY_ADDR}
-EOF
-
-cat >/opt/crictl.yaml <<'EOF'
-runtime-endpoint: unix:///var/run/crio/crio.sock
-image-endpoint: unix:///var/run/crio/crio.sock
-timeout: 10
-debug: false
-EOF
-
-registry serve /opt/registry/config.yml >/var/log/registry.log 2>&1 &
-REG_PID=$!
-
-cleanup() {
- kill "$REG_PID" 2>/dev/null || true
-}
-trap cleanup EXIT INT TERM
-
-for _ in $(seq 1 30); do
- if curl -fsS "http://${REGISTRY_ADDR}/v2/_catalog" >/dev/null; then
- break
- fi
- sleep 1
-done
-
-curl -fsS "http://${REGISTRY_ADDR}/v2/_catalog" >/dev/null
-
-for img in $(kubeadm config images list --kubernetes-version "${KUBE_VERSION}"); do
- name="${img#registry.k8s.io/}"
- echo "Importing ${img} from ${REGISTRY_ADDR}/${name}"
- skopeo copy --src-tls-verify=false \
- "docker://${REGISTRY_ADDR}/${name}" \
- "containers-storage:${img}"
-done
-
-echo "Imported images now visible to CRI-O:"
-crictl images
-
-kill "$REG_PID" 2>/dev/null || true
-wait "$REG_PID" 2>/dev/null || true
-trap - EXIT INT TERM
diff --git a/alpine/rootfs-extra/opt/scripts/test-crio.sh b/alpine/rootfs-extra/opt/scripts/test-crio.sh
new file mode 100755
index 0000000..eb11fec
--- /dev/null
+++ b/alpine/rootfs-extra/opt/scripts/test-crio.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+set -euo pipefail
+
+RUNTIME_ENDPOINT="${RUNTIME_ENDPOINT:-unix:///var/run/crio/crio.sock}"
+
+# 1. Get pause image
+PAUSE_IMAGE="$(kubeadm config images list | grep pause)"
+
+echo "Using pause image: $PAUSE_IMAGE"
+
+# 2. Create pod sandbox config
+cat > pod.json <<EOF
+{
+ "metadata": {
+ "name": "pause-test",
+ "namespace": "default",
+ "attempt": 1
+ },
+ "log_directory": "/tmp",
+ "linux": {}
+}
+EOF
+
+# 3. Create container config
+cat > container.json <<EOF
+{
+ "metadata": {
+ "name": "pause-container"
+ },
+ "image": {
+ "image": "$PAUSE_IMAGE"
+ },
+ "log_path": "pause.log",
+ "linux": {}
+}
+EOF
+
+# 4. Run pod sandbox
+POD_ID=$(crictl --runtime-endpoint "$RUNTIME_ENDPOINT" runp pod.json)
+echo "Pod ID: $POD_ID"
+
+# 5. Create container
+CONTAINER_ID=$(crictl --runtime-endpoint "$RUNTIME_ENDPOINT" create "$POD_ID" container.json pod.json)
+echo "Container ID: $CONTAINER_ID"
+
+# 6. Start container
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" start "$CONTAINER_ID"
+
+# 7. Verify
+echo "=== Pods ==="
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" pods
+
+echo "=== Containers ==="
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" ps
+
+# 8. Cleanup
+echo "Cleaning up..."
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" stop "$CONTAINER_ID" || true
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" rm "$CONTAINER_ID" || true
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" stopp "$POD_ID" || true
+crictl --runtime-endpoint "$RUNTIME_ENDPOINT" rmp "$POD_ID" || true
+
+rm -f pod.json container.json
+
+echo "Done."
\ No newline at end of file