Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ jobs:
go.work.sum
- run: make build

docker-build-arm64:
runs-on: ubuntu-24.04-arm
timeout-minutes: 120
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version: "1.26.6"
cache: true
cache-dependency-path: |
**/go.sum
go.work.sum
- uses: docker/setup-buildx-action@v4.3.0
Comment thread
lrbison marked this conversation as resolved.

- name: Build arm64 operator image
run: |
make docker-build-operator \
OPERATOR_PLATFORM=linux/arm64 \
DOCKER_BUILD_ARGS="--progress=plain \
--cache-from=type=gha,scope=operator-arm64 \
--cache-to=type=gha,scope=operator-arm64,mode=max,ignore-error=true"

- name: Build arm64 agent image
timeout-minutes: 90
run: |
make docker-build-agent \
AGENT_PLATFORM=linux/arm64 \
DOCKER_BUILD_ARGS="--progress=plain \
--cache-from=type=gha,scope=agent-arm64 \
--cache-to=type=gha,scope=agent-arm64,mode=max,ignore-error=true"
Comment thread
coderabbitai[bot] marked this conversation as resolved.

check:
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/push-artifacts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ jobs:
- name: Build and push operator image
run: |
make docker-build-operator \
OPERATOR_PLATFORM="linux/amd64,linux/arm64" \
Comment thread
lrbison marked this conversation as resolved.
TAGS="${{ needs.version.outputs.tags }}" \
DOCKER_BUILD_ARGS="--push \
--cache-from=type=gha,scope=operator \
Expand Down Expand Up @@ -149,14 +150,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# --platform=linux/amd64: Dockerfile exits 1 on other arches
- name: Build and push agent image
timeout-minutes: 45
run: |
make docker-build-agent \
AGENT_PLATFORM="linux/amd64,linux/arm64" \
TAGS="${{ needs.version.outputs.tags }}" \
DOCKER_BUILD_ARGS="--platform=linux/amd64 \
--push \
DOCKER_BUILD_ARGS="--push \
--cache-from=type=gha,scope=agent \
--cache-to=type=gha,scope=agent,mode=max"

Expand Down
34 changes: 8 additions & 26 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ TAGS ?= $(VERSION)
DOCKER_BUILD_ARGS ?=

# Base image for the agent, read from the Dockerfile so the digest lives in one
# place. capture-base-packages and docker-build-agent must agree on it, or the
# committed package baseline would describe a different image than we build on.
# place.
AGENT_BASE_IMAGE ?= $(shell sed -n 's/^ARG AGENT_BASE_IMAGE=//p' agent/Dockerfile)

# The agent is x86_64-only (cuda-checkpoint ships no other arch) and the package
# baseline is captured for this platform, so pin it rather than inheriting
# whatever the buildx builder defaults to.
AGENT_PLATFORM ?= linux/amd64
# Image platform(s). Build the local host architecture by default; release
# workflows override these with comma-separated multi-platform lists.
AGENT_PLATFORM ?= linux/$(SYSTEM_ARCH)
OPERATOR_PLATFORM ?= linux/$(SYSTEM_ARCH)

.PHONY: tidy generate test build lint verify-generate verify-crds check fmt add-license-headers \
verify-license-headers govulncheck helm-lint docker-build-agent docker-build-operator capture-base-packages verify-base-packages \
verify-license-headers govulncheck helm-lint docker-build-agent docker-build-operator \
linux-build linux-test

CRD_SRC_DIR := api/v1alpha1/crds
Expand Down Expand Up @@ -108,24 +107,7 @@ linux-test:
$(LINUX_GO_IMAGE) \
make -C agent test

# Refresh the agent's base-image package baseline. Run whenever AGENT_BASE_IMAGE
# changes; verify-base-packages fails the agent build if you forget.
capture-base-packages:
@sh hack/capture-base-packages.sh "$(AGENT_BASE_IMAGE)" agent/compliance/base-packages.tsv "$(AGENT_PLATFORM)"
@echo "baseline: $$(grep -vc '^#' agent/compliance/base-packages.tsv) packages"

# The source delta is computed against the committed baseline, so a base-image
# bump without a re-capture would silently skew it: packages the new base added
# would look like ours, and packages it dropped would vanish from the delta. The
# build would still succeed, with wrong compliance content. Fail instead.
verify-base-packages:
@set -e; \
tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \
sh hack/capture-base-packages.sh "$(AGENT_BASE_IMAGE)" "$$tmp" "$(AGENT_PLATFORM)"; \
diff -u agent/compliance/base-packages.tsv "$$tmp" || \
(echo "ERROR: agent/compliance/base-packages.tsv is stale for $(AGENT_BASE_IMAGE) — run 'make capture-base-packages' and commit"; exit 1)

docker-build-agent: verify-base-packages
docker-build-agent:
docker buildx build $(DOCKER_BUILD_ARGS) --platform "$(AGENT_PLATFORM)" -f agent/Dockerfile \
--build-arg "GO_VERSION=$(GO_VERSION)" \
--build-arg "AGENT_BASE_IMAGE=$(AGENT_BASE_IMAGE)" \
Expand All @@ -134,5 +116,5 @@ docker-build-agent: verify-base-packages
$(foreach t,$(TAGS),-t $(REGISTRY)/agent:$(t)) agent/

docker-build-operator:
docker buildx build $(DOCKER_BUILD_ARGS) -f operator/Dockerfile \
docker buildx build $(DOCKER_BUILD_ARGS) --platform "$(OPERATOR_PLATFORM)" -f operator/Dockerfile \
$(foreach t,$(TAGS),-t $(REGISTRY)/operator:$(t)) .
73 changes: 52 additions & 21 deletions agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ ARG BASE_IMAGE=placeholder-requires-base-image-arg
# =============================================================================
FROM ${DOCKER_PROXY}library/golang:${GO_VERSION} AS go-base

ARG TARGETOS=linux
ARG TARGETARCH=amd64
ARG TARGETOS
ARG TARGETARCH
Comment thread
lrbison marked this conversation as resolved.

RUN echo "Building for ${TARGETOS}/${TARGETARCH}"

Expand Down Expand Up @@ -78,19 +78,41 @@ RUN go test ./... -v
# =============================================================================
FROM go-base AS builder

ARG TARGETOS=linux
ARG TARGETARCH=amd64
ARG TARGETOS
ARG TARGETARCH

RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -ldflags="-w -s" -o /snapshot-agent ./cmd/agent
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -ldflags="-w -s" -o /nsrestore ./cmd/nsrestore

# Corresponding source for the Go modules compiled into the binaries above.
RUN mkdir -p /go-src && go mod vendor -o /go-src/vendor

# =============================================================================
# Stage: Agent base - validate target arch and capture package baseline
# =============================================================================
FROM ${AGENT_BASE_IMAGE} AS agent-base

ARG TARGETARCH

RUN case "${TARGETARCH}" in \
amd64|arm64) ;; \
*) echo "ERROR: Snapshot supports amd64 and arm64 agent images, not ${TARGETARCH}" >&2; exit 1 ;; \
esac

RUN set -eu; \
dpkg-query -W -f='${Package}\t${Version}\t${source:Package}\t${source:Version}\n' \
| LC_ALL=C sort > /base-packages.tsv; \
test -s /base-packages.tsv; \
awk -F'\t' \
'NF != 4 || $1 == "" || $2 == "" || $3 == "" || $4 == "" { \
printf "invalid base manifest row %d: %s\n", NR, $0 > "/dev/stderr"; bad = 1 \
} \
END { exit bad ? 1 : 0 }' /base-packages.tsv
Comment thread
coderabbitai[bot] marked this conversation as resolved.

# =============================================================================
# Stage: CUDA checkpoint helper builder
# =============================================================================
FROM ${AGENT_BASE_IMAGE} AS cuda-helper-builder
FROM agent-base AS cuda-helper-builder

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
Expand Down Expand Up @@ -166,13 +188,7 @@ RUN tar -czf /criu-src.tar.gz -C /tmp --exclude-vcs criu
#
# Shared by the agent and sources stages so both see the same package set.
# =============================================================================
FROM ${AGENT_BASE_IMAGE} AS runtime-deps

ARG TARGETARCH=amd64

RUN if [ "${TARGETARCH}" != "amd64" ]; then \
echo "ERROR: Snapshot requires x86_64 (cuda-checkpoint has no ${TARGETARCH} binary)" >&2; exit 1; \
fi
FROM agent-base AS runtime-deps

# Install CRIU runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
Expand All @@ -198,11 +214,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# =============================================================================
FROM runtime-deps AS sources

COPY compliance/base-packages.tsv /tmp/base-packages.tsv
COPY compliance/collect-sources.sh /tmp/collect-sources.sh

# Debian/Ubuntu source for the delta against the NGC base image.
RUN sh /tmp/collect-sources.sh /tmp/base-packages.tsv /sources/dpkg
RUN sh /tmp/collect-sources.sh /base-packages.tsv /sources/dpkg

# CRIU source, at the exact ref this image was built from.
COPY --from=criu-builder /criu-src.tar.gz /sources/criu/criu-src.tar.gz
Expand All @@ -223,8 +238,16 @@ COPY --from=criu-builder /tmp/criu/COPYING /legal/CRIU/COPYING
RUN criu --version

# Copy CUDA checkpoint binaries
COPY --from=criu-builder /tmp/cuda-checkpoint/bin/x86_64_Linux/cuda-checkpoint /usr/local/sbin/cuda-checkpoint
COPY --from=criu-builder /tmp/cuda-checkpoint/LICENSE /legal/cuda-checkpoint/LICENSE
ARG TARGETARCH
COPY --from=criu-builder /tmp/cuda-checkpoint/bin /tmp/cuda-checkpoint-bin
RUN set -eu; \
case "${TARGETARCH}" in \
amd64) cuda_checkpoint_arch=x86_64_Linux ;; \
arm64) cuda_checkpoint_arch=aarch64_Linux ;; \
*) echo "ERROR: Snapshot supports amd64 and arm64 agent images, not ${TARGETARCH}" >&2; exit 1 ;; \
esac; \
install -D -m 0755 "/tmp/cuda-checkpoint-bin/${cuda_checkpoint_arch}/cuda-checkpoint" /usr/local/sbin/cuda-checkpoint; \
install -D -m 0644 "/tmp/cuda-checkpoint-bin/${cuda_checkpoint_arch}/LICENSE" /legal/cuda-checkpoint/LICENSE
COPY --from=cuda-helper-builder /cuda-checkpoint-helper /usr/local/bin/cuda-checkpoint-helper
# nsmount resolves this helper at /usr/local/sbin/ns-bind-mount (see
# agent/internal/nsmount/mount.go defaultBinaryPath).
Expand All @@ -234,6 +257,7 @@ RUN chmod +x /usr/local/sbin/cuda-checkpoint /usr/local/bin/cuda-checkpoint-help

# Copy the built binaries
COPY --from=builder /snapshot-agent /usr/local/bin/snapshot-agent
RUN /usr/local/bin/snapshot-agent -h >/dev/null 2>&1

# Assemble the injection bundle: bind-mounted read-only into the placeholder's
# mount namespace at /tmp/snapshot-binaries during restore (internal/nsmount).
Expand All @@ -244,7 +268,6 @@ RUN mkdir -p /snapshot-binaries/lib /snapshot-binaries/criu-plugins
COPY --from=builder /nsrestore /snapshot-binaries/nsrestore
COPY --from=criu-builder /criu-install/usr/local/sbin/criu /snapshot-binaries/criu
COPY --from=criu-builder /criu-install/usr/local/lib/snapshot/criu-plugins/ /snapshot-binaries/criu-plugins/
COPY --from=criu-builder /tmp/cuda-checkpoint/bin/x86_64_Linux/cuda-checkpoint /snapshot-binaries/cuda-checkpoint
COPY --from=cuda-helper-builder /cuda-checkpoint-helper /snapshot-binaries/cuda-checkpoint-helper

# Network binaries needed during restore:
Expand All @@ -256,10 +279,17 @@ COPY --from=cuda-helper-builder /cuda-checkpoint-helper /snapshot-binaries/cuda-
# for restore specifically.
# All resolve through PATH inside the namespace.
RUN set -eu; \
case "${TARGETARCH}" in \
amd64) cuda_checkpoint_arch=x86_64_Linux ;; \
arm64) cuda_checkpoint_arch=aarch64_Linux ;; \
*) echo "ERROR: Snapshot supports amd64 and arm64 agent images, not ${TARGETARCH}" >&2; exit 1 ;; \
esac; \
cp "/tmp/cuda-checkpoint-bin/${cuda_checkpoint_arch}/cuda-checkpoint" /snapshot-binaries/cuda-checkpoint; \
cp -L "$(command -v ip)" "$(command -v tar)" /snapshot-binaries/; \
chmod +x /snapshot-binaries/criu /snapshot-binaries/nsrestore \
/snapshot-binaries/cuda-checkpoint /snapshot-binaries/cuda-checkpoint-helper \
/snapshot-binaries/ip /snapshot-binaries/tar
RUN /snapshot-binaries/nsrestore -h >/dev/null 2>&1

# Shared-library closure of the bundled binaries and plugins.
#
Expand Down Expand Up @@ -347,14 +377,15 @@ ENTRYPOINT ["/usr/local/bin/snapshot-agent"]
FROM ${BASE_IMAGE} AS placeholder

ARG BASE_IMAGE
ARG TARGETARCH=amd64
ARG TARGETARCH
ENV ORIGINAL_BASE_IMAGE=${BASE_IMAGE}

USER root

RUN if [ "${TARGETARCH}" != "amd64" ]; then \
echo "ERROR: Snapshot requires x86_64" >&2; exit 1; \
fi
RUN case "${TARGETARCH}" in \
amd64|arm64) ;; \
*) echo "ERROR: Snapshot supports amd64 and arm64 placeholder images, not ${TARGETARCH}" >&2; exit 1 ;; \
esac

# Checkpoint volume mount point. This is a storage concern — no restore tooling
# is provisioned here; see the stage comment above.
Expand Down
7 changes: 5 additions & 2 deletions agent/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ include $(REPO_HACK_DIR)/tools.mk

.PHONY: build test tidy lint fmt

GOOS ?= linux
GOARCH ?= $(shell go env GOARCH)

build:
GOOS=linux GOARCH=amd64 go build -o bin/agent ./cmd/agent
GOOS=linux GOARCH=amd64 go build -o bin/nsrestore ./cmd/nsrestore
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o bin/agent ./cmd/agent
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o bin/nsrestore ./cmd/nsrestore

test:
go test ./...
Expand Down
Loading