tools: build kata-monitor image from shim-v2-go tarball

Build kata-monitor images by extracting the binary from the
shim-v2-go tarball and shipping it on top of
gcr.io/distroless/static-debian13.

Because the binary is built inside an Ubuntu (glibc) toolchain it
cannot run on a pure musl/alpine base — users hit __fprintf_chk /
__vfprintf_chk relocation errors. To get a small, distroless
runtime image we use the same pattern as
tools/packaging/kata-deploy/Dockerfile: copy the glibc libraries
the binary needs (plus the dynamic linker) via ldd from a glibc
base image.

In order to do so, we also added a helper script to build and
publish architecture-specific monitor images from tarball
artifacts.

Reported-by: Steve Linde <stevenlinde@google.com>
Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
Assisted-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Fabiano Fidêncio
2026-05-29 23:55:17 +02:00
committed by Fabiano Fidêncio
parent ddaf450086
commit e04a4326ec
2 changed files with 117 additions and 20 deletions

View File

@@ -1,28 +1,74 @@
# Copyright (c) 2020 Eric Ernst
# Copyright (c) 2026 NVIDIA
# SPDX-License-Identifier: Apache-2.0
ARG GO_VERSION
FROM golang:${GO_VERSION}-alpine AS builder
#
# Build context: extracted kata-static shim-v2-go tarball root.
#
# Expected file in context:
# ./opt/kata/bin/kata-monitor
#
# The kata-monitor binary is built inside an Ubuntu (glibc) toolchain
# as part of the shim-v2-go static build, so it is dynamically linked
# against glibc. We assemble its runtime dependencies via `ldd` from
# a glibc base image and copy them into a distroless/static runtime
# image, matching the same pattern used by
# tools/packaging/kata-deploy/Dockerfile.
RUN apk add --no-cache bash curl git make build-base
WORKDIR /go/src/github.com/kata-containers/kata-containers/src/runtime
# Stage 1: discover and copy the glibc libraries the binary needs.
# hadolint ignore=DL3007
FROM debian:trixie-slim AS runtime-assembler
COPY src/runtime/go.* .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
COPY . /go/src/github.com/kata-containers/kata-containers
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
make SKIP_GO_VERSION_CHECK=true monitor
COPY opt/kata/bin/kata-monitor /tmp/kata-monitor
# run tests
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
cd pkg/kata-monitor/ && go test -c -o /tmp/tests
RUN /tmp/tests
RUN \
set -eux; \
mkdir -p /output/lib /output/lib64; \
echo "Libraries needed by kata-monitor on $(uname -m):"; \
ldd /tmp/kata-monitor || true; \
# Copy each shared library reported by ldd ("=>" lines).
ldd /tmp/kata-monitor 2>/dev/null | grep "=>" | awk '{print $3}' | sort -u | \
while read -r lib; do \
if [ -n "${lib}" ] && [ -f "${lib}" ]; then \
dest_dir="/output$(dirname "${lib}")"; \
mkdir -p "${dest_dir}"; \
cp -Ln "${lib}" "${dest_dir}/" || true; \
echo " Copied lib: ${lib}"; \
fi; \
done; \
# Copy the dynamic linker too: ldd does not include it in the "=>"
# lines. Cover all four target architectures:
# x86_64 -> /lib64/ld-linux-x86-64.so.2
# aarch64 -> /lib/ld-linux-aarch64.so.1
# s390x -> /lib/ld64.so.1
# ppc64le -> /lib64/ld64.so.2
for ld in /lib*/ld-linux-*.so.* /lib*/ld64.so.*; do \
[ -f "${ld}" ] || continue; \
dest_dir="/output$(dirname "${ld}")"; \
mkdir -p "${dest_dir}"; \
cp -Ln "${ld}" "${dest_dir}/" || true; \
echo " Copied linker: ${ld}"; \
done
# Stage 2: final distroless image.
#
# We deliberately track the rolling `latest` tag rather than pinning a
# digest. distroless/static-debian13 publishes no semver tags and is
# rebuilt frequently to pick up base-image CVE fixes, so following
# `latest` keeps the kata-monitor runtime on the newest patched base.
# The image only carries the handful of glibc libraries we copy in plus
# the kata-monitor binary, so the blast radius of an unexpected base
# bump is tiny. hadolint's "pin the version" check is therefore not
# something we want here.
# hadolint ignore=DL3007
FROM gcr.io/distroless/static-debian13:latest
COPY --from=runtime-assembler /output/lib/ /lib/
COPY --from=runtime-assembler /output/lib64/ /lib64/
COPY opt/kata/bin/kata-monitor /usr/bin/kata-monitor
EXPOSE 8090
FROM alpine:3.14
COPY --from=builder /go/src/github.com/kata-containers/kata-containers/src/runtime/kata-monitor /usr/bin/kata-monitor
CMD ["-h"]
ENTRYPOINT ["/usr/bin/kata-monitor"]
CMD ["--help"]

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
#
# Copyright (c) 2026 NVIDIA
#
# SPDX-License-Identifier: Apache-2.0
#
set -o errexit
set -o nounset
set -o pipefail
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root_dir="$(cd "${script_dir}/../../.." && pwd)"
image_ref="${1:?image ref is required (e.g. quay.io/org/repo:tag)}"
shim_tarball="${2:?path to kata-static-shim-v2-go.tar.zst is required}"
push_image="${3:-true}"
case "$(uname -m)" in
x86_64) platform_arch="amd64" ;;
aarch64) platform_arch="arm64" ;;
s390x) platform_arch="s390x" ;;
ppc64le) platform_arch="ppc64le" ;;
*) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;;
esac
tmpdir="$(mktemp -d)"
cleanup() {
rm -rf "${tmpdir}"
}
trap cleanup EXIT
tar --zstd -xf "${shim_tarball}" -C "${tmpdir}"
if [[ ! -x "${tmpdir}/opt/kata/bin/kata-monitor" ]]; then
echo "kata-monitor binary not found in ${shim_tarball}" >&2
exit 1
fi
push_flag=()
if [[ "${push_image}" == "true" ]]; then
push_flag+=(--push)
fi
docker buildx build \
--platform "linux/${platform_arch}" \
--provenance false --sbom false \
-f "${repo_root_dir}/tools/packaging/kata-monitor/Dockerfile" \
--tag "${image_ref}" \
"${push_flag[@]}" \
"${tmpdir}"