penguin/monok8s

k8s image for Mono Gateway Dev Kit

commit 7c3e096fec5b4c72f614ef2a574cfd216174838d179a25c51874c90dc562ba75

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-03-31T18:03:37Z
subjectShip the control-agent controller for node
commit 7c3e096fec5b4c72f614ef2a574cfd216174838d179a25c51874c90dc562ba75
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-03-31T18:03:37Z

    Ship the control-agent controller for node
---
 alpine/preload-k8s-images.sh | 99 +++++++++++++++++++++++++++++++++++---------
 clitools/Dockerfile          | 12 ++++++
 clitools/makefile            |  6 +++
 makefile                     | 18 ++++----
 4 files changed, 107 insertions(+), 28 deletions(-)

diff --git a/alpine/preload-k8s-images.sh b/alpine/preload-k8s-images.sh
index e209268..c1d3e5f 100755
--- a/alpine/preload-k8s-images.sh
+++ b/alpine/preload-k8s-images.sh
@@ -18,6 +18,17 @@ STORAGE_DRIVER="${STORAGE_DRIVER:-overlay}"
 # Optional. Needed by many overlay-in-container setups.
 FUSE_OVERLAYFS="${FUSE_OVERLAYFS:-/usr/bin/fuse-overlayfs}"
 
+# Optional extra images to include in addition to kubeadm's required images.
+# Example:
+#   EXTRA_IMAGES=(
+#     "docker.io/library/busybox:1.36"
+#     "quay.io/cilium/cilium:v1.17.2"
+#   )
+EXTRA_IMAGES=(
+	"${EXTRA_IMAGES[@]:-}"
+	"docker-daemon:monok8s/control-agent:$TAG"
+)
+
 # Keep archive cache version/arch scoped so downloads do not get mixed.
 ARCHIVE_DIR="${KUBE_IMG_CACHE}/archives/${ARCH}/${KUBE_VERSION}"
 
@@ -70,48 +81,96 @@ fi
 
 export CONTAINERS_STORAGE_CONF="${STORAGE_CONF}"
 
-# Sanity check: list required images using the target kubeadm binary.
-mapfile -t kube_images < <(
+# Get kubeadm-required images.
+mapfile -t kubeadm_images < <(
     qemu-aarch64-static \
         "${ROOTFS}/usr/local/bin/kubeadm" \
         config images list \
         --kubernetes-version "${KUBE_VERSION}"
 )
 
-if [ "${#kube_images[@]}" -eq 0 ]; then
-    echo "No kubeadm images returned"
+if [ "${#kubeadm_images[@]}" -eq 0 ] && [ "${#EXTRA_IMAGES[@]}" -eq 0 ]; then
+    echo "No images to seed"
     exit 1
 fi
 
-for img in "${kube_images[@]}"; do
+# Merge kubeadm images + EXTRA_IMAGES, preserving order and removing duplicates.
+images=()
+declare -A seen=()
+
+for img in "${kubeadm_images[@]}" "${EXTRA_IMAGES[@]}"; do
+    [ -n "${img}" ] || continue
+    if [ -z "${seen[$img]+x}" ]; then
+        images+=("${img}")
+        seen["$img"]=1
+    fi
+done
+
+echo "Images to seed:"
+for img in "${images[@]}"; do
+    echo "  ${img}"
+done
+echo
+
+for img in "${images[@]}"; do
     [ -n "${img}" ] || continue
 
-    safe_name="$(printf '%s' "${img}" | sed 's#/#_#g; s#:#__#g')"
+    case "$img" in
+        docker-daemon:*)
+            SRC="$img"
+            IMG_REF="${img#docker-daemon:}"
+            USE_ARCHIVE=0
+            ;;
+        docker://*)
+            SRC="$img"
+            IMG_REF="${img#docker://}"
+            USE_ARCHIVE=1
+            ;;
+        oci-archive:*)
+            SRC="$img"
+            IMG_REF="${img#oci-archive:}"
+            USE_ARCHIVE=0
+            ;;
+        *)
+            # Default behavior for non-prefixed refs:
+            # treat as remote registry image.
+            SRC="docker://${img}"
+            IMG_REF="$img"
+            USE_ARCHIVE=1
+            ;;
+    esac
+
+    safe_name="$(printf '%s' "${IMG_REF}" | sed 's#/#_#g; s#:#__#g')"
     archive="${ARCHIVE_DIR}/${safe_name}.tar"
 
-    if [ ! -f "${archive}" ]; then
-        echo "Caching archive: ${img}"
-        skopeo copy \
-            --override-os "${OS}" \
-            --override-arch "${ARCH}" \
-            "docker://${img}" \
-            "oci-archive:${archive}"
+    if [ "${USE_ARCHIVE}" = "1" ]; then
+        if [ ! -f "${archive}" ]; then
+            echo "Caching archive: ${IMG_REF}"
+            skopeo copy \
+                --override-os "${OS}" \
+                --override-arch "${ARCH}" \
+                "${SRC}" \
+                "oci-archive:${archive}"
+        else
+            echo "Archive hit: ${IMG_REF}"
+        fi
+        SRC_FINAL="oci-archive:${archive}"
     else
-        echo "Archive hit: ${img}"
+        echo "Using direct source: ${SRC}"
+        SRC_FINAL="${SRC}"
     fi
 
-    # If already present in the target containers/storage, skip.
-    if skopeo inspect "containers-storage:${img}" >/dev/null 2>&1; then
-        echo "Store hit: ${img}"
+    if skopeo inspect "containers-storage:${IMG_REF}" >/dev/null 2>&1; then
+        echo "Store hit: ${IMG_REF}"
         continue
     fi
 
-    echo "Seeding CRI-O store: ${img}"
+    echo "Seeding CRI-O store: ${IMG_REF}"
     skopeo copy \
         --override-os "${OS}" \
         --override-arch "${ARCH}" \
-        "oci-archive:${archive}" \
-        "containers-storage:${img}"
+        "${SRC_FINAL}" \
+        "containers-storage:${IMG_REF}"
 done
 
 echo
diff --git a/clitools/Dockerfile b/clitools/Dockerfile
new file mode 100644
index 0000000..7164d68
--- /dev/null
+++ b/clitools/Dockerfile
@@ -0,0 +1,12 @@
+FROM alpine:latest AS cacerts
+FROM scratch
+
+ARG VERSION
+ENV VERSION=${VERSION}
+
+WORKDIR /
+
+COPY bin/ctl-linux-aarch64-${VERSION} ./ctl
+COPY --from=cacerts /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
+
+CMD [ "/ctl", "agent" ]
diff --git a/clitools/makefile b/clitools/makefile
index 86e32cd..0c0ea31 100644
--- a/clitools/makefile
+++ b/clitools/makefile
@@ -15,6 +15,12 @@ build: $(BUILDINFO_FILE)
 	mkdir -p $(BIN_DIR)
 	GOOS=linux GOARCH=arm64 go build -o $(BIN_DIR)/ctl-linux-aarch64-$(VERSION) ./cmd/ctl/
 
+build-agent:
+	docker build \
+		--platform=linux/arm64 \
+		--build-arg VERSION=$(VERSION) \
+		-t monok8s/control-agent:$(VERSION) .
+
 build-local:
 	go build -o $(BIN_DIR)/ctl-$(VERSION) ./cmd/ctl
 
diff --git a/makefile b/makefile
index a797be8..50539e4 100644
--- a/makefile
+++ b/makefile
@@ -207,19 +207,21 @@ $(RELEASE_IMAGE): $(RELEASE_DEPS) | $(OUT_DIR)
 
 	@cid=$$(docker create \
 		--privileged \
-		-v /cache/k8s-images:/var/cache/k8s-images \
 		-v /cache/apk:/var/cache/apk \
+		-v /cache/k8s-images:/var/cache/k8s-images \
+		-v /var/run/docker.sock:/var/run/docker.sock \
 		--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 BUILD_VERSION=$(BUILD_VERSION) \
+		-e ARCH=$(ARCH) \
 		-e BUILD_DATE=$(BUILD_DATE) \
 		-e BUILD_GIT=$(BUILD_GIT) \
-		-e ARCH=$(ARCH) \
+		-e BUILD_VERSION=$(BUILD_VERSION) \
+		-e DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \
+		-e KUBE_IMG_CACHE=/var/cache/k8s-images \
+		-e KUBE_VERSION=$(KUBE_VERSION) \
+		-e RELEASE_IMAGE=$(RELEASE_IMAGE) \
+		-e ROOTFS=/out/rootfs \
+		-e TAG=$(TAG) \
 		$(DOCKER_IMAGE_ROOT)/buildenv-alpine:$(TAG) \
 		bash -lc '/build-rootfs.sh'); \
 	docker start -a $$cid; \