commit 58da0aada60a54190580b9929be8cfcfd94190eb6b47a1e58f8d6bca40b9951f
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-03-24T12:52:17Z |
| subject | crictl can import images but slow |
commit 58da0aada60a54190580b9929be8cfcfd94190eb6b47a1e58f8d6bca40b9951f
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-03-24T12:52:17Z
crictl can import images but slow
---
README.md | 28 +++-
alpine/build-rootfs.sh | 17 ++-
alpine/install-packages.sh | 16 +-
alpine/merge-rootfs.sh | 194 +++++++++++++++++++++++++
alpine/preload-k8s-images.sh | 106 ++++++++++++++
alpine/{ => rootfs-extra}/etc/fancontrol | 0
alpine/rootfs-extra/etc/fstab | 1 +
alpine/rootfs-extra/etc/hostname.tmpl.override | 1 +
alpine/rootfs-extra/etc/inittab | 2 +
alpine/rootfs-extra/opt/scripts/load-images.sh | 56 +++++++
build.env | 7 +
docker/alpine.Dockerfile | 8 +-
docker/build-base.Dockerfile | 7 +-
docker/initramfs.Dockerfile | 6 +-
makefile | 44 +++++-
15 files changed, 474 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
index f964891..6d43a77 100644
--- a/README.md
+++ b/README.md
@@ -5,17 +5,16 @@ Kubernetes image for Mono Gateway Development Kit
https://docs.mono.si/gateway-development-kit/getting-started
## DISCLAIMER
-I leverage ChatGPT heavily for this. I also tested them thoroughly enough that until I am confident that's what we need.
+USE AT YOUR OWN RISKS. I leverage ChatGPT heavily for this. I am testing them all by myself right now.
### The device's dts files are located at here
https://github.com/we-are-mono/OpenWRT-ASK/tree/mono-25.12.0-rc3/target/linux/layerscape/files/arch/arm64/boot/dts/freescale
* We need both `mono-gateway-dk-sdk.dts` and `mono-gateway-dk.dts` since the sdk one includes the non-sdk one.
* The actual dts being used is the `mono-gateway-dk-sdk.dts`
-
## Build
-To avoid frequent downloading on rebuild. Find the latest packages and update build.env
+Find the latest package versions and update build.env
* [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/)
* [busybox](https://github.com/mirror/busybox/archive/refs/tags/)
* [CRI-O](https://github.com/cri-o/cri-o/releases)
@@ -23,12 +22,15 @@ To avoid frequent downloading on rebuild. Find the latest packages and update bu
Then run
```
-make download-packages
+make release
```
+### Making sub stages
```bash
-make itb # for out/board.itb (contains the kernel and the initramfs)
-make release # WORK IN PROGRESS
+make build-base # The image the builds kernel and everything
+make kernel # Builds our kernel from NXP
+make initramfs
+make itb # Builds out/board.itb (contains the kernel and the initramfs)
```
## Architecture
@@ -66,7 +68,9 @@ setenv serverip 10.0.0.129
tftp 0x80000000 board.itb
```
-## USB
+## USB Flashing
+1. Copy board.itb into an SDCard
+2. Copy `[RELEASE_NAME].img.gz` into an SDCard
```
usb start
usb tree
@@ -77,3 +81,13 @@ fatload usb 0 0x80000000 board.itb
setenv bootargs "console=ttyS0,115200 earlycon=uart8250,mmio,0x21c0500 root=/dev/ram0 rootwait rw"
bootm 0x80000000
```
+
+3. Inside initramfs
+```
+mount /dev/sda /mnt
+gunzip -c /mnt/[RELEASE_IMAGE].img.gz | dd of=/dev/mmcblk0
+reboot -f
+```
+
+4. If it boots, create the A/B deployment scheme
+ - (WORK IN PROGRESS)
diff --git a/alpine/build-rootfs.sh b/alpine/build-rootfs.sh
index be3074f..fe65074 100755
--- a/alpine/build-rootfs.sh
+++ b/alpine/build-rootfs.sh
@@ -1,8 +1,19 @@
#!/bin/bash
+/preload-k8s-images.sh || exit 1
+
+REGISTRY_DATA_DIR="${KUBE_IMG_CACHE}/registry-data/${ARCH}/${KUBE_VERSION}"
+
+mkdir -p "${ROOTFS}/var/lib/registry"
+
+echo "Copying registry data into rootfs..."
+cp -a "${REGISTRY_DATA_DIR}/." "${ROOTFS}/var/lib/registry/"
+
mkdir -p "$ROOTFS/var/cache/apk"
+mkdir -p "$ROOTFS/var/cache/k8s-images"
mkdir -p "$ROOTFS/build"
mount --bind /var/cache/apk "$ROOTFS/var/cache/apk"
+mount --bind /var/cache/k8s-images "$ROOTFS/var/cache/k8s-images"
mount --bind /dev "$ROOTFS/dev"
mount --bind /proc "$ROOTFS/proc"
mount --bind /sys "$ROOTFS/sys"
@@ -11,6 +22,7 @@ mount --bind /run "$ROOTFS/run"
cp /usr/bin/qemu-aarch64-static "$ROOTFS/usr/bin/"
cp /etc/resolv.conf "$ROOTFS/etc/resolv.conf"
cp /build/crio.tar.gz "$ROOTFS/build/"
+cp /build/registry.tar.gz "$ROOTFS/build/"
cp -r /build/rootfs/* "$ROOTFS/"
chroot "$ROOTFS" /bin/sh -c "ln -s /var/cache/apk /etc/apk/cache"
@@ -21,6 +33,7 @@ chroot "$ROOTFS" /bin/bash /install-packages.sh || exit 1
rm "$ROOTFS/install-packages.sh"
umount "$ROOTFS/var/cache/apk"
+umount "$ROOTFS/var/cache/k8s-images"
umount "$ROOTFS/dev"
umount "$ROOTFS/proc"
umount "$ROOTFS/sys"
@@ -28,11 +41,13 @@ umount "$ROOTFS/run"
rm -r "$ROOTFS/build"
+/merge-rootfs.sh "/build/rootfs-extra" "$ROOTFS"
+
### Begin making full disk image for the device
echo "=========================== RootFS "$( du -sh "$ROOTFS/" )
IMG=output.img
-SIZE=1024MB
+SIZE=1536MB
dd if=/dev/zero of="$IMG" bs=1 count=0 seek=$SIZE
diff --git a/alpine/install-packages.sh b/alpine/install-packages.sh
index 9d6f248..5510301 100755
--- a/alpine/install-packages.sh
+++ b/alpine/install-packages.sh
@@ -10,11 +10,20 @@ rc-update add devfs sysinit
rc-update add procfs sysinit
rc-update add sysfs sysinit
rc-update add loopback boot
+rc-update add hostname boot
+rc-update add localmount boot
rc-update add fancontrol default
-echo "ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 -n -l /bin/sh" >> "/etc/inittab"
echo '[ -x /bin/bash ] && exec /bin/bash -l' >> "/root/.profile"
-echo "export PATH=\"/usr/local/bin:$PATH\"" >> "/etc/profile.d/settings.sh"
+# We need this to ship k8s components. (coredns, kube-apiserver, etc)
+echo "##################################################### Install Local Registry"
+mkdir -p /usr/local/bin
+
+apk add skopeo
+
+tar zxf registry.tar.gz
+mv registry /usr/local/bin/registry
+/usr/local/bin/registry --version
echo "##################################################### Installing CRI-O"
@@ -30,6 +39,9 @@ if [ $? -ne 0 ]; then
exit $?
fi
+mv /etc/cni/net.d/10-crio-bridge.conflist.disabled \
+ /etc/cni/net.d/10-crio-bridge.conflist
+
echo "--------------"
sed -i "s/default_runtime = \"crun\"/\0\ncgroup_manager = \"cgroupfs\"/g" /etc/crio/crio.conf.d/10-crio.conf
grep cgroup_manager /etc/crio/crio.conf.d/10-crio.conf || exit 1
diff --git a/alpine/merge-rootfs.sh b/alpine/merge-rootfs.sh
new file mode 100755
index 0000000..4dd0aae
--- /dev/null
+++ b/alpine/merge-rootfs.sh
@@ -0,0 +1,194 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Usage:
+# export HOSTNAME=mybox
+# ./merge-rootfs.sh rootfs-extra /out/rootfs
+#
+# Naming rules:
+# foo -> normal file
+# foo.tmpl -> render with envsubst, then normal handling
+# foo.override -> replace target directly
+# foo.tmpl.override -> render with envsubst, then replace target directly
+#
+# Default handling:
+# etc/* -> merge missing lines
+# opt/scripts/* -> replace
+# everything else -> copy only if missing
+
+SRC_ROOT="${1:?source rootfs path required}"
+DST_ROOT="${2:?target rootfs path required}"
+
+if [[ ! -d "$SRC_ROOT" ]]; then
+ echo "Source rootfs does not exist or is not a directory: $SRC_ROOT" >&2
+ exit 1
+fi
+
+if [[ ! -d "$DST_ROOT" ]]; then
+ echo "Target rootfs does not exist or is not a directory: $DST_ROOT" >&2
+ exit 1
+fi
+
+if ! command -v envsubst >/dev/null 2>&1; then
+ echo "envsubst not found. Install gettext or gettext-envsubst." >&2
+ exit 1
+fi
+
+TMP_DIR="$(mktemp -d)"
+trap 'rm -rf "$TMP_DIR"' EXIT
+
+append_missing_lines() {
+ local src="$1"
+ local dst="$2"
+ local changed=1
+ local line
+
+ while IFS= read -r line || [[ -n "$line" ]]; do
+ if ! grep -Fqx -- "$line" "$dst"; then
+ printf '%s\n' "$line" >> "$dst"
+ changed=0
+ fi
+ done < "$src"
+
+ return "$changed"
+}
+
+check_template_vars() {
+ local src="$1"
+ local missing=0
+ local vars var
+
+ vars="$(
+ grep -oE '\$\{[A-Za-z_][A-Za-z0-9_]*\}|\$[A-Za-z_][A-Za-z0-9_]*' "$src" \
+ | sed -E 's/^\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?$/\1/' \
+ | sort -u || true
+ )"
+
+ while IFS= read -r var; do
+ [[ -z "$var" ]] && continue
+ if [[ -z "${!var+x}" ]]; then
+ echo "Missing required env var: $var (used in $src)" >&2
+ missing=1
+ fi
+ done <<< "$vars"
+
+ [[ "$missing" -eq 0 ]]
+}
+
+render_template() {
+ local src="$1"
+ local out="$2"
+
+ mkdir -p "$(dirname "$out")"
+ check_template_vars "$src"
+ envsubst < "$src" > "$out"
+}
+
+replace_file() {
+ local src="$1"
+ local dst="$2"
+
+ mkdir -p "$(dirname "$dst")"
+ cp -a "$src" "$dst"
+ echo "Replaced file: $dst"
+}
+
+merge_or_copy_file() {
+ local src="$1"
+ local dst="$2"
+ local rel="$3"
+
+ mkdir -p "$(dirname "$dst")"
+
+ # scripts: replace
+ if [[ "$rel" == opt/scripts/* ]]; then
+ cp -a "$src" "$dst"
+ echo "Replaced script: $dst"
+ return
+ fi
+
+ # /etc: merge missing lines
+ if [[ "$rel" == etc/* ]]; then
+ if [[ ! -e "$dst" ]]; then
+ cp -a "$src" "$dst"
+ echo "Copied new config: $dst"
+ return
+ fi
+
+ if [[ ! -f "$dst" ]]; then
+ echo "Skipping existing non-regular path: $dst" >&2
+ return
+ fi
+
+ if append_missing_lines "$src" "$dst"; then
+ echo "Appended missing lines: $dst"
+ else
+ echo "No changes needed: $dst"
+ fi
+ return
+ fi
+
+ # default: copy only if missing
+ if [[ ! -e "$dst" ]]; then
+ cp -a "$src" "$dst"
+ echo "Copied new file: $dst"
+ else
+ echo "Skipped existing file: $dst"
+ fi
+}
+
+find "$SRC_ROOT" -mindepth 1 | while IFS= read -r src_path; do
+ rel_path="${src_path#"$SRC_ROOT"/}"
+
+ if [[ -d "$src_path" ]]; then
+ mkdir -p "$DST_ROOT/$rel_path"
+ continue
+ fi
+
+ if [[ -L "$src_path" ]]; then
+ dst_path="$DST_ROOT/$rel_path"
+ if [[ -e "$dst_path" || -L "$dst_path" ]]; then
+ echo "Symlink exists, skipping: $dst_path"
+ else
+ mkdir -p "$(dirname "$dst_path")"
+ ln -s "$(readlink "$src_path")" "$dst_path"
+ echo "Created symlink: $dst_path"
+ fi
+ continue
+ fi
+
+ if [[ ! -f "$src_path" ]]; then
+ echo "Skipping unsupported file type: $src_path" >&2
+ continue
+ fi
+
+ src_for_merge="$src_path"
+ rel_for_target="$rel_path"
+ mode="default"
+
+ if [[ "$rel_for_target" == *.tmpl.override ]]; then
+ mode="override"
+ rel_for_target="${rel_for_target%.tmpl.override}"
+ rendered="$TMP_DIR/$rel_for_target"
+ render_template "$src_path" "$rendered"
+ src_for_merge="$rendered"
+
+ elif [[ "$rel_for_target" == *.override ]]; then
+ mode="override"
+ rel_for_target="${rel_for_target%.override}"
+
+ elif [[ "$rel_for_target" == *.tmpl ]]; then
+ rel_for_target="${rel_for_target%.tmpl}"
+ rendered="$TMP_DIR/$rel_for_target"
+ render_template "$src_path" "$rendered"
+ src_for_merge="$rendered"
+ fi
+
+ dst_path="$DST_ROOT/$rel_for_target"
+
+ if [[ "$mode" == "override" ]]; then
+ replace_file "$src_for_merge" "$dst_path"
+ else
+ merge_or_copy_file "$src_for_merge" "$dst_path" "$rel_for_target"
+ fi
+done
diff --git a/alpine/preload-k8s-images.sh b/alpine/preload-k8s-images.sh
new file mode 100755
index 0000000..22388dd
--- /dev/null
+++ b/alpine/preload-k8s-images.sh
@@ -0,0 +1,106 @@
+#!/bin/bash
+set -euo pipefail
+
+: "${KUBE_IMG_CACHE:?KUBE_IMG_CACHE is required}"
+: "${KUBE_VERSION:?KUBE_VERSION is required}"
+: "${ARCH:?ARCH 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"
+
+if podman image exists "${REGISTRY_IMAGE}"; then
+ echo "Registry image already present: ${REGISTRY_IMAGE}"
+
+elif [ -f "${REGISTRY_TAR}" ]; then
+ echo "Loading registry image from cache: ${REGISTRY_TAR}"
+ podman load -i "${REGISTRY_TAR}"
+
+else
+ echo "Cache miss → pulling and saving registry image"
+
+ podman pull "${REGISTRY_IMAGE}"
+ podman save -o "${REGISTRY_TAR}" "${REGISTRY_IMAGE}"
+fi
+
+mkdir -p "${ARCHIVE_DIR}"
+rm -rf "${REGISTRY_DATA_DIR}"
+mkdir -p "${REGISTRY_DATA_DIR}"
+
+echo "============================================================"
+echo "Preparing Kubernetes image cache"
+echo " KUBE_VERSION = ${KUBE_VERSION}"
+echo " ARCH = ${ARCH}"
+echo " ARCHIVE_DIR = ${ARCHIVE_DIR}"
+echo " REGISTRY_DATA_DIR = ${REGISTRY_DATA_DIR}"
+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
+
+cleanup() {
+ podman rm -f temp-registry >/dev/null 2>&1 || true
+}
+trap cleanup EXIT
+
+# 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
+
+if ! curl -fsS "http://127.0.0.1:${REGISTRY_PORT}/v2/" >/dev/null; then
+ echo "Temporary registry did not start"
+ exit 1
+fi
+
+# Cache and seed all kubeadm-required images.
+while read -r img; do
+ [ -n "$img" ] || continue
+
+ 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"
+ skopeo copy \
+ --override-os "${OS}" \
+ --override-arch "${ARCH}" \
+ "docker://$img" \
+ "oci-archive:$archive"
+ else
+ echo "Cache 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}"
+ continue
+ fi
+
+ echo "Seeding registry: $ref"
+ 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}")
+
+echo
+echo "Done."
+echo "Archives: ${ARCHIVE_DIR}"
+echo "Registry data: ${REGISTRY_DATA_DIR}"
diff --git a/alpine/etc/fancontrol b/alpine/rootfs-extra/etc/fancontrol
similarity index 100%
rename from alpine/etc/fancontrol
rename to alpine/rootfs-extra/etc/fancontrol
diff --git a/alpine/rootfs-extra/etc/fstab b/alpine/rootfs-extra/etc/fstab
new file mode 100644
index 0000000..8217562
--- /dev/null
+++ b/alpine/rootfs-extra/etc/fstab
@@ -0,0 +1 @@
+none /sys/fs/cgroup cgroup2 defaults 0 0
diff --git a/alpine/rootfs-extra/etc/hostname.tmpl.override b/alpine/rootfs-extra/etc/hostname.tmpl.override
new file mode 100644
index 0000000..1cdcb69
--- /dev/null
+++ b/alpine/rootfs-extra/etc/hostname.tmpl.override
@@ -0,0 +1 @@
+${ALPINE_HOSTNAME}
diff --git a/alpine/rootfs-extra/etc/inittab b/alpine/rootfs-extra/etc/inittab
new file mode 100644
index 0000000..55e1fb0
--- /dev/null
+++ b/alpine/rootfs-extra/etc/inittab
@@ -0,0 +1,2 @@
+# Dev only
+ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 -n -l /bin/bash
diff --git a/alpine/rootfs-extra/opt/scripts/load-images.sh b/alpine/rootfs-extra/opt/scripts/load-images.sh
new file mode 100755
index 0000000..8700097
--- /dev/null
+++ b/alpine/rootfs-extra/opt/scripts/load-images.sh
@@ -0,0 +1,56 @@
+#!/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/build.env b/build.env
index 26b7c50..769dd46 100644
--- a/build.env
+++ b/build.env
@@ -6,6 +6,10 @@ TAG=dev
# The Linux kernel, from NXP
NXP_VERSION=lf-6.18.2-1.0.0
CRIO_VERSION=cri-o.arm64.v1.35.1
+KUBE_VERSION=v1.35.3
+
+# Local registry for exporting k8s images
+REGISTRY_VERSION=2.8.3
# Mono's tutorial said fsl-ls1046a-rdb.dtb but our shipped board is not that one
# We need fsl-ls1046a-rdb-sdk.dtb here
@@ -23,3 +27,6 @@ BUSYBOX_VERSION=1_36_1
## Alpine Linux
ALPINE_VER=3.23.3
ALPINE_ARCH=aarch64
+
+# Only applies to new installations
+ALPINE_HOSTNAME=monok8s-hostname
diff --git a/docker/alpine.Dockerfile b/docker/alpine.Dockerfile
index 0d86c9f..9d5a594 100644
--- a/docker/alpine.Dockerfile
+++ b/docker/alpine.Dockerfile
@@ -6,12 +6,14 @@ FROM --platform=$BUILDPLATFORM ${DOCKER_IMAGE_ROOT}/build-base:${TAG} AS build-b
ARG ALPINE_ARCH
ARG ALPINE_VER
ARG CRIO_VERSION
+ARG REGISTRY_VERSION
ARG DEVICE_TREE_TARGET
RUN mkdir -p "/out/rootfs"
COPY packages/alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz ./alpine.tar.gz
COPY packages/${CRIO_VERSION}.tar.gz ./crio.tar.gz
+COPY packages/registry-${REGISTRY_VERSION}.tar.gz ./registry.tar.gz
COPY out/board.itb ./
COPY out/rootfs ./rootfs
COPY out/${DEVICE_TREE_TARGET}.dtb ./
@@ -19,5 +21,9 @@ COPY out/Image.gz ./
RUN tar -xf alpine.tar.gz -C "/out/rootfs"
-COPY alpine/etc ./rootfs/etc
+RUN mkdir -p /out/rootfs/usr/local/bin/
+COPY packages/kubernetes/* /out/rootfs/usr/local/bin/
+RUN chmod +x /out/rootfs/usr/local/bin/*
+
+COPY alpine/rootfs-extra ./rootfs-extra
COPY alpine/*.sh /
diff --git a/docker/build-base.Dockerfile b/docker/build-base.Dockerfile
index 9a2119c..7d4e361 100644
--- a/docker/build-base.Dockerfile
+++ b/docker/build-base.Dockerfile
@@ -1,4 +1,4 @@
-FROM --platform=$BUILDPLATFORM debian:bookworm-slim AS kernel-build
+FROM --platform=$BUILDPLATFORM debian:trixie-slim AS kernel-build
ENV DEBIAN_FRONTEND=noninteractive
@@ -10,11 +10,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
bison \
build-essential \
cpio \
+ ca-certificates \
curl \
dosfstools \
file \
fdisk \
+ fuse-overlayfs \
gdisk \
+ e2fsprogs \
flex \
git \
gettext-base \
@@ -27,6 +30,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
perl \
python3 \
qemu-user-static \
+ podman \
+ skopeo \
rsync \
tar \
udev \
diff --git a/docker/initramfs.Dockerfile b/docker/initramfs.Dockerfile
index c23a89e..ff73516 100644
--- a/docker/initramfs.Dockerfile
+++ b/docker/initramfs.Dockerfile
@@ -18,8 +18,10 @@ RUN tar -xf busybox-${BUSYBOX_VERSION}.tar.gz && mv "busybox-${BUSYBOX_VERSION}"
WORKDIR /build/busybox
-RUN make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} defconfig\
- && sed -i 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
+RUN make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} defconfig \
+ && sed -i \
+ -e 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' \
+ -e 's/^CONFIG_TC=.*/# CONFIG_TC is not set/' .config
RUN make CROSS_COMPILE=${CROSS_COMPILE} -j"$(nproc)"
RUN make CROSS_COMPILE=${CROSS_COMPILE} CONFIG_PREFIX=/out/initramfs install
diff --git a/makefile b/makefile
index 7c08b8a..04c5a8b 100644
--- a/makefile
+++ b/makefile
@@ -6,10 +6,16 @@ TAG ?= dev
PACKAGES_DIR := packages
OUT_DIR := out
-BUSYBOX_TAR := $(PACKAGES_DIR)/busybox-$(BUSYBOX_VERSION).tar.gz
-ALPINE_TAR := $(PACKAGES_DIR)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz
-NXP_TAR := $(PACKAGES_DIR)/$(NXP_VERSION).tar.gz
-CRIO_TAR := $(PACKAGES_DIR)/$(CRIO_VERSION).tar.gz
+BUSYBOX_TAR := $(PACKAGES_DIR)/busybox-$(BUSYBOX_VERSION).tar.gz
+ALPINE_TAR := $(PACKAGES_DIR)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz
+NXP_TAR := $(PACKAGES_DIR)/$(NXP_VERSION).tar.gz
+CRIO_TAR := $(PACKAGES_DIR)/$(CRIO_VERSION).tar.gz
+REGISTRY_TAR := $(PACKAGES_DIR)/registry-$(REGISTRY_VERSION).tar.gz
+
+# Kubernetes components
+KUBELET_BIN := $(PACKAGES_DIR)/kubernetes/kubelet
+KUBEADM_BIN := $(PACKAGES_DIR)/kubernetes/kubeadm
+KUBECTL_BIN := $(PACKAGES_DIR)/kubernetes/kubectl
BOARD_ITB := $(OUT_DIR)/board.itb
INITRAMFS := $(OUT_DIR)/initramfs.cpio.gz
@@ -62,6 +68,10 @@ RELEASE_DEPS := \
$(BOARD_ITB) \
$(ALPINE_TAR) \
$(CRIO_TAR) \
+ $(KUBELET_BIN) \
+ $(KUBEADM_BIN) \
+ $(KUBECTL_BIN) \
+ $(REGISTRY_TAR) \
docker/alpine.Dockerfile \
$(ALPINE_SRCS) \
build.env \
@@ -71,11 +81,23 @@ RELEASE_DEPS := \
$(PACKAGES_DIR):
mkdir -p $@
+ mkdir -p $@/kubernetes
$(OUT_DIR):
mkdir -p $@
# ---- Package downloads -------------------------------------------------------
+$(KUBELET_BIN): | $(PACKAGES_DIR)
+ curl -L -o $@ "https://dl.k8s.io/$(KUBE_VERSION)/bin/linux/$(ARCH)/kubelet"
+
+$(KUBEADM_BIN): | $(PACKAGES_DIR)
+ curl -L -o $@ "https://dl.k8s.io/$(KUBE_VERSION)/bin/linux/$(ARCH)/kubeadm"
+
+$(KUBECTL_BIN): | $(PACKAGES_DIR)
+ curl -L -o $@ "https://dl.k8s.io/$(KUBE_VERSION)/bin/linux/$(ARCH)/kubectl"
+
+$(KUBEADM_BIN): | $(PACKAGES_DIR)
+ curl -L -o $@ "https://dl.k8s.io/$(KUBE_VERSION)/bin/linux/$(ARCH)/kubeadm"
$(BUSYBOX_TAR): | $(PACKAGES_DIR)
curl -L -o $@ "https://github.com/mirror/busybox/archive/refs/tags/$(BUSYBOX_VERSION).tar.gz"
@@ -83,6 +105,9 @@ $(BUSYBOX_TAR): | $(PACKAGES_DIR)
$(ALPINE_TAR): | $(PACKAGES_DIR)
curl -L -o $@ "https://dl-cdn.alpinelinux.org/alpine/v$(ALPINE_SERIES)/releases/$(ALPINE_ARCH)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz"
+$(REGISTRY_TAR): | $(PACKAGES_DIR)
+ curl -L -o $@ "https://github.com/distribution/distribution/releases/download/v$(REGISTRY_VERSION)/registry_$(REGISTRY_VERSION)_linux_$(ARCH).tar.gz"
+
$(NXP_TAR): | $(PACKAGES_DIR)
curl -L -o $@ "https://github.com/nxp-qoriq/linux/archive/refs/tags/$(NXP_VERSION).tar.gz"
@@ -139,16 +164,22 @@ $(RELEASE_IMAGE): $(RELEASE_DEPS) | $(OUT_DIR)
--build-arg ALPINE_ARCH=$(ALPINE_ARCH) \
--build-arg ALPINE_VER=$(ALPINE_VER) \
--build-arg CRIO_VERSION=$(CRIO_VERSION) \
+ --build-arg REGISTRY_VERSION=$(REGISTRY_VERSION) \
--build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \
-t $(DOCKER_IMAGE_ROOT)/buildenv-alpine:$(TAG) .
@cid=$$(docker create \
--privileged \
+ -v /cache/k8s-images:/var/cache/k8s-images \
-v /cache/apk:/var/cache/apk \
--device=/dev/loop0:/dev/loop0 \
-e ROOTFS=/out/rootfs \
-e RELEASE_IMAGE=$(RELEASE_IMAGE) \
-e DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \
+ -e KUBE_IMG_CACHE=/var/cache/k8s-images \
+ -e KUBE_VERSION=$(KUBE_VERSION) \
+ -e ALPINE_HOSTNAME=$(ALPINE_HOSTNAME) \
+ -e ARCH=$(ARCH) \
$(DOCKER_IMAGE_ROOT)/buildenv-alpine:$(TAG) \
bash -lc '/build-rootfs.sh'); \
docker start -a $$cid; \
@@ -175,6 +206,9 @@ clean:
$(RELEASE_IMAGE)
distclean: clean
- rm -rf $(OUT_DIR) $(PACKAGES_DIR)
+ rm -rf $(OUT_DIR)
+
+pkgclean:
+ rm -rf $(PACKAGES_DIR)
.PHONY: release kernel initramfs itb build-base clean distclean