crictl can import images but slow
This commit is contained in:
28
README.md
28
README.md
@@ -5,17 +5,16 @@ Kubernetes image for Mono Gateway Development Kit
|
|||||||
https://docs.mono.si/gateway-development-kit/getting-started
|
https://docs.mono.si/gateway-development-kit/getting-started
|
||||||
|
|
||||||
## DISCLAIMER
|
## 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
|
### 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
|
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.
|
* 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`
|
* The actual dts being used is the `mono-gateway-dk-sdk.dts`
|
||||||
|
|
||||||
|
|
||||||
## Build
|
## 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/)
|
* [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/)
|
||||||
* [busybox](https://github.com/mirror/busybox/archive/refs/tags/)
|
* [busybox](https://github.com/mirror/busybox/archive/refs/tags/)
|
||||||
* [CRI-O](https://github.com/cri-o/cri-o/releases)
|
* [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
|
Then run
|
||||||
```
|
```
|
||||||
make download-packages
|
make release
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Making sub stages
|
||||||
```bash
|
```bash
|
||||||
make itb # for out/board.itb (contains the kernel and the initramfs)
|
make build-base # The image the builds kernel and everything
|
||||||
make release # WORK IN PROGRESS
|
make kernel # Builds our kernel from NXP
|
||||||
|
make initramfs
|
||||||
|
make itb # Builds out/board.itb (contains the kernel and the initramfs)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
@@ -66,7 +68,9 @@ setenv serverip 10.0.0.129
|
|||||||
tftp 0x80000000 board.itb
|
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 start
|
||||||
usb tree
|
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"
|
setenv bootargs "console=ttyS0,115200 earlycon=uart8250,mmio,0x21c0500 root=/dev/ram0 rootwait rw"
|
||||||
bootm 0x80000000
|
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)
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
#!/bin/bash
|
#!/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/apk"
|
||||||
|
mkdir -p "$ROOTFS/var/cache/k8s-images"
|
||||||
mkdir -p "$ROOTFS/build"
|
mkdir -p "$ROOTFS/build"
|
||||||
mount --bind /var/cache/apk "$ROOTFS/var/cache/apk"
|
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 /dev "$ROOTFS/dev"
|
||||||
mount --bind /proc "$ROOTFS/proc"
|
mount --bind /proc "$ROOTFS/proc"
|
||||||
mount --bind /sys "$ROOTFS/sys"
|
mount --bind /sys "$ROOTFS/sys"
|
||||||
@@ -11,6 +22,7 @@ mount --bind /run "$ROOTFS/run"
|
|||||||
cp /usr/bin/qemu-aarch64-static "$ROOTFS/usr/bin/"
|
cp /usr/bin/qemu-aarch64-static "$ROOTFS/usr/bin/"
|
||||||
cp /etc/resolv.conf "$ROOTFS/etc/resolv.conf"
|
cp /etc/resolv.conf "$ROOTFS/etc/resolv.conf"
|
||||||
cp /build/crio.tar.gz "$ROOTFS/build/"
|
cp /build/crio.tar.gz "$ROOTFS/build/"
|
||||||
|
cp /build/registry.tar.gz "$ROOTFS/build/"
|
||||||
cp -r /build/rootfs/* "$ROOTFS/"
|
cp -r /build/rootfs/* "$ROOTFS/"
|
||||||
|
|
||||||
chroot "$ROOTFS" /bin/sh -c "ln -s /var/cache/apk /etc/apk/cache"
|
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"
|
rm "$ROOTFS/install-packages.sh"
|
||||||
|
|
||||||
umount "$ROOTFS/var/cache/apk"
|
umount "$ROOTFS/var/cache/apk"
|
||||||
|
umount "$ROOTFS/var/cache/k8s-images"
|
||||||
umount "$ROOTFS/dev"
|
umount "$ROOTFS/dev"
|
||||||
umount "$ROOTFS/proc"
|
umount "$ROOTFS/proc"
|
||||||
umount "$ROOTFS/sys"
|
umount "$ROOTFS/sys"
|
||||||
@@ -28,11 +41,13 @@ umount "$ROOTFS/run"
|
|||||||
|
|
||||||
rm -r "$ROOTFS/build"
|
rm -r "$ROOTFS/build"
|
||||||
|
|
||||||
|
/merge-rootfs.sh "/build/rootfs-extra" "$ROOTFS"
|
||||||
|
|
||||||
### Begin making full disk image for the device
|
### Begin making full disk image for the device
|
||||||
echo "=========================== RootFS "$( du -sh "$ROOTFS/" )
|
echo "=========================== RootFS "$( du -sh "$ROOTFS/" )
|
||||||
|
|
||||||
IMG=output.img
|
IMG=output.img
|
||||||
SIZE=1024MB
|
SIZE=1536MB
|
||||||
|
|
||||||
dd if=/dev/zero of="$IMG" bs=1 count=0 seek=$SIZE
|
dd if=/dev/zero of="$IMG" bs=1 count=0 seek=$SIZE
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,20 @@ rc-update add devfs sysinit
|
|||||||
rc-update add procfs sysinit
|
rc-update add procfs sysinit
|
||||||
rc-update add sysfs sysinit
|
rc-update add sysfs sysinit
|
||||||
rc-update add loopback boot
|
rc-update add loopback boot
|
||||||
|
rc-update add hostname boot
|
||||||
|
rc-update add localmount boot
|
||||||
rc-update add fancontrol default
|
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 '[ -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"
|
echo "##################################################### Installing CRI-O"
|
||||||
|
|
||||||
@@ -30,6 +39,9 @@ if [ $? -ne 0 ]; then
|
|||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mv /etc/cni/net.d/10-crio-bridge.conflist.disabled \
|
||||||
|
/etc/cni/net.d/10-crio-bridge.conflist
|
||||||
|
|
||||||
echo "--------------"
|
echo "--------------"
|
||||||
sed -i "s/default_runtime = \"crun\"/\0\ncgroup_manager = \"cgroupfs\"/g" /etc/crio/crio.conf.d/10-crio.conf
|
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
|
grep cgroup_manager /etc/crio/crio.conf.d/10-crio.conf || exit 1
|
||||||
|
|||||||
194
alpine/merge-rootfs.sh
Executable file
194
alpine/merge-rootfs.sh
Executable file
@@ -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
|
||||||
106
alpine/preload-k8s-images.sh
Executable file
106
alpine/preload-k8s-images.sh
Executable file
@@ -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}"
|
||||||
1
alpine/rootfs-extra/etc/fstab
Normal file
1
alpine/rootfs-extra/etc/fstab
Normal file
@@ -0,0 +1 @@
|
|||||||
|
none /sys/fs/cgroup cgroup2 defaults 0 0
|
||||||
1
alpine/rootfs-extra/etc/hostname.tmpl.override
Normal file
1
alpine/rootfs-extra/etc/hostname.tmpl.override
Normal file
@@ -0,0 +1 @@
|
|||||||
|
${ALPINE_HOSTNAME}
|
||||||
2
alpine/rootfs-extra/etc/inittab
Normal file
2
alpine/rootfs-extra/etc/inittab
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Dev only
|
||||||
|
ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 -n -l /bin/bash
|
||||||
56
alpine/rootfs-extra/opt/scripts/load-images.sh
Executable file
56
alpine/rootfs-extra/opt/scripts/load-images.sh
Executable file
@@ -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
|
||||||
@@ -6,6 +6,10 @@ TAG=dev
|
|||||||
# The Linux kernel, from NXP
|
# The Linux kernel, from NXP
|
||||||
NXP_VERSION=lf-6.18.2-1.0.0
|
NXP_VERSION=lf-6.18.2-1.0.0
|
||||||
CRIO_VERSION=cri-o.arm64.v1.35.1
|
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
|
# Mono's tutorial said fsl-ls1046a-rdb.dtb but our shipped board is not that one
|
||||||
# We need fsl-ls1046a-rdb-sdk.dtb here
|
# We need fsl-ls1046a-rdb-sdk.dtb here
|
||||||
@@ -23,3 +27,6 @@ BUSYBOX_VERSION=1_36_1
|
|||||||
## Alpine Linux
|
## Alpine Linux
|
||||||
ALPINE_VER=3.23.3
|
ALPINE_VER=3.23.3
|
||||||
ALPINE_ARCH=aarch64
|
ALPINE_ARCH=aarch64
|
||||||
|
|
||||||
|
# Only applies to new installations
|
||||||
|
ALPINE_HOSTNAME=monok8s-hostname
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ FROM --platform=$BUILDPLATFORM ${DOCKER_IMAGE_ROOT}/build-base:${TAG} AS build-b
|
|||||||
ARG ALPINE_ARCH
|
ARG ALPINE_ARCH
|
||||||
ARG ALPINE_VER
|
ARG ALPINE_VER
|
||||||
ARG CRIO_VERSION
|
ARG CRIO_VERSION
|
||||||
|
ARG REGISTRY_VERSION
|
||||||
ARG DEVICE_TREE_TARGET
|
ARG DEVICE_TREE_TARGET
|
||||||
|
|
||||||
RUN mkdir -p "/out/rootfs"
|
RUN mkdir -p "/out/rootfs"
|
||||||
|
|
||||||
COPY packages/alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz ./alpine.tar.gz
|
COPY packages/alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz ./alpine.tar.gz
|
||||||
COPY packages/${CRIO_VERSION}.tar.gz ./crio.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/board.itb ./
|
||||||
COPY out/rootfs ./rootfs
|
COPY out/rootfs ./rootfs
|
||||||
COPY out/${DEVICE_TREE_TARGET}.dtb ./
|
COPY out/${DEVICE_TREE_TARGET}.dtb ./
|
||||||
@@ -19,5 +21,9 @@ COPY out/Image.gz ./
|
|||||||
|
|
||||||
RUN tar -xf alpine.tar.gz -C "/out/rootfs"
|
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 /
|
COPY alpine/*.sh /
|
||||||
|
|||||||
@@ -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
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
@@ -10,11 +10,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
bison \
|
bison \
|
||||||
build-essential \
|
build-essential \
|
||||||
cpio \
|
cpio \
|
||||||
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
dosfstools \
|
dosfstools \
|
||||||
file \
|
file \
|
||||||
fdisk \
|
fdisk \
|
||||||
|
fuse-overlayfs \
|
||||||
gdisk \
|
gdisk \
|
||||||
|
e2fsprogs \
|
||||||
flex \
|
flex \
|
||||||
git \
|
git \
|
||||||
gettext-base \
|
gettext-base \
|
||||||
@@ -27,6 +30,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
perl \
|
perl \
|
||||||
python3 \
|
python3 \
|
||||||
qemu-user-static \
|
qemu-user-static \
|
||||||
|
podman \
|
||||||
|
skopeo \
|
||||||
rsync \
|
rsync \
|
||||||
tar \
|
tar \
|
||||||
udev \
|
udev \
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ RUN tar -xf busybox-${BUSYBOX_VERSION}.tar.gz && mv "busybox-${BUSYBOX_VERSION}"
|
|||||||
|
|
||||||
WORKDIR /build/busybox
|
WORKDIR /build/busybox
|
||||||
|
|
||||||
RUN make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} defconfig\
|
RUN make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} defconfig \
|
||||||
&& sed -i 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
|
&& 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} -j"$(nproc)"
|
||||||
RUN make CROSS_COMPILE=${CROSS_COMPILE} CONFIG_PREFIX=/out/initramfs install
|
RUN make CROSS_COMPILE=${CROSS_COMPILE} CONFIG_PREFIX=/out/initramfs install
|
||||||
|
|
||||||
|
|||||||
36
makefile
36
makefile
@@ -10,6 +10,12 @@ BUSYBOX_TAR := $(PACKAGES_DIR)/busybox-$(BUSYBOX_VERSION).tar.gz
|
|||||||
ALPINE_TAR := $(PACKAGES_DIR)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz
|
ALPINE_TAR := $(PACKAGES_DIR)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz
|
||||||
NXP_TAR := $(PACKAGES_DIR)/$(NXP_VERSION).tar.gz
|
NXP_TAR := $(PACKAGES_DIR)/$(NXP_VERSION).tar.gz
|
||||||
CRIO_TAR := $(PACKAGES_DIR)/$(CRIO_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
|
BOARD_ITB := $(OUT_DIR)/board.itb
|
||||||
INITRAMFS := $(OUT_DIR)/initramfs.cpio.gz
|
INITRAMFS := $(OUT_DIR)/initramfs.cpio.gz
|
||||||
@@ -62,6 +68,10 @@ RELEASE_DEPS := \
|
|||||||
$(BOARD_ITB) \
|
$(BOARD_ITB) \
|
||||||
$(ALPINE_TAR) \
|
$(ALPINE_TAR) \
|
||||||
$(CRIO_TAR) \
|
$(CRIO_TAR) \
|
||||||
|
$(KUBELET_BIN) \
|
||||||
|
$(KUBEADM_BIN) \
|
||||||
|
$(KUBECTL_BIN) \
|
||||||
|
$(REGISTRY_TAR) \
|
||||||
docker/alpine.Dockerfile \
|
docker/alpine.Dockerfile \
|
||||||
$(ALPINE_SRCS) \
|
$(ALPINE_SRCS) \
|
||||||
build.env \
|
build.env \
|
||||||
@@ -71,11 +81,23 @@ RELEASE_DEPS := \
|
|||||||
|
|
||||||
$(PACKAGES_DIR):
|
$(PACKAGES_DIR):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
mkdir -p $@/kubernetes
|
||||||
|
|
||||||
$(OUT_DIR):
|
$(OUT_DIR):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
# ---- Package downloads -------------------------------------------------------
|
# ---- 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)
|
$(BUSYBOX_TAR): | $(PACKAGES_DIR)
|
||||||
curl -L -o $@ "https://github.com/mirror/busybox/archive/refs/tags/$(BUSYBOX_VERSION).tar.gz"
|
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)
|
$(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"
|
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)
|
$(NXP_TAR): | $(PACKAGES_DIR)
|
||||||
curl -L -o $@ "https://github.com/nxp-qoriq/linux/archive/refs/tags/$(NXP_VERSION).tar.gz"
|
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_ARCH=$(ALPINE_ARCH) \
|
||||||
--build-arg ALPINE_VER=$(ALPINE_VER) \
|
--build-arg ALPINE_VER=$(ALPINE_VER) \
|
||||||
--build-arg CRIO_VERSION=$(CRIO_VERSION) \
|
--build-arg CRIO_VERSION=$(CRIO_VERSION) \
|
||||||
|
--build-arg REGISTRY_VERSION=$(REGISTRY_VERSION) \
|
||||||
--build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \
|
--build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \
|
||||||
-t $(DOCKER_IMAGE_ROOT)/buildenv-alpine:$(TAG) .
|
-t $(DOCKER_IMAGE_ROOT)/buildenv-alpine:$(TAG) .
|
||||||
|
|
||||||
@cid=$$(docker create \
|
@cid=$$(docker create \
|
||||||
--privileged \
|
--privileged \
|
||||||
|
-v /cache/k8s-images:/var/cache/k8s-images \
|
||||||
-v /cache/apk:/var/cache/apk \
|
-v /cache/apk:/var/cache/apk \
|
||||||
--device=/dev/loop0:/dev/loop0 \
|
--device=/dev/loop0:/dev/loop0 \
|
||||||
-e ROOTFS=/out/rootfs \
|
-e ROOTFS=/out/rootfs \
|
||||||
-e RELEASE_IMAGE=$(RELEASE_IMAGE) \
|
-e RELEASE_IMAGE=$(RELEASE_IMAGE) \
|
||||||
-e DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \
|
-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) \
|
$(DOCKER_IMAGE_ROOT)/buildenv-alpine:$(TAG) \
|
||||||
bash -lc '/build-rootfs.sh'); \
|
bash -lc '/build-rootfs.sh'); \
|
||||||
docker start -a $$cid; \
|
docker start -a $$cid; \
|
||||||
@@ -175,6 +206,9 @@ clean:
|
|||||||
$(RELEASE_IMAGE)
|
$(RELEASE_IMAGE)
|
||||||
|
|
||||||
distclean: clean
|
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
|
.PHONY: release kernel initramfs itb build-base clean distclean
|
||||||
|
|||||||
Reference in New Issue
Block a user