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 ALPINE_HOSTNAME=$(ALPINE_HOSTNAME) \ + -e ARCH=$(ARCH) \ + -e BUILD_DATE=$(BUILD_DATE) \ + -e BUILD_GIT=$(BUILD_GIT) \ + -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 ALPINE_HOSTNAME=$(ALPINE_HOSTNAME) \ - -e BUILD_VERSION=$(BUILD_VERSION) \ - -e BUILD_DATE=$(BUILD_DATE) \ - -e BUILD_GIT=$(BUILD_GIT) \ - -e ARCH=$(ARCH) \ + -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; \