Files
substrate/hack/install-microvm-deps.sh
T
Zoe Zhao 6d3afdd63b Resolve SandboxConfig from the ActorTemplate instead of the WorkerPool (#1446)
This PR moves sandbox config selection from the WorkerPool to the
ActorTemplate.

The existing behavior is preserved while we are designing the upgrade:
sandbox config still cannot be updated once set (ActorTemplates are
create-only and `sandbox_config` is immutable).

For now the ActorTemplate still *requires* `sandbox_config.config_name`
— there is no resolution of the cluster default (`spec.default`). This
is temporary while we figure out the defaulting design.

- [ ] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-09-03 16:13:07 -07:00

199 lines
8.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Install (or delete) the cluster-wide micro-VM (kata + cloud-hypervisor)
# dependencies. This is opt-in on top of hack/install-ate.sh --deploy-ate-system,
# which only installs the default gVisor SandboxConfig. Used by:
# * hack/run-microvm-demo.sh (before applying the counter-microvm demo)
# * benchmarking/automation/orchestrator.py (before deploying a microvm
# benchmark workload)
#
# On --install: assembles the asset set (assemble.sh; skipped if OUT already
# has them), stages the assets under kata-assets/ to the cluster's object
# store bucket (rustfs on kind, GCS on GKE), and applies the cluster-wide
# `microvm` SandboxConfig referencing those assets. The virtiofsd
# sha256 is computed from the staged binary and injected at apply time (on
# arm64 the v1.14.0 binary is built from source, so its bytes vary per
# toolchain and cannot be pinned in the manifest).
#
# ActorTemplates must reference the SandboxConfig explicitly via
# sandboxConfig.configName: microvm. This avoids a dirty teardown silently
# binding new templates to a stale config.
#
# On --delete: removes the SandboxConfig from the cluster. Bucket contents
# are left alone (they're inert until a SandboxConfig points at them, and
# re-staging is cheap on next install).
#
# Like the other hack scripts, this sources .ate-dev-env.sh for the cluster /
# registry / bucket settings unless NO_DEV_ENV is set.
#
# Env (most come from .ate-dev-env.sh):
# BUCKET_NAME object store bucket for assets/snapshots (default: ate-snapshots).
# KUBECTL_CONTEXT (optional) kube context; threaded into kubectl.
# PROJECT_ID (optional) GCP project for the GCS asset upload (GKE path).
# ARCH target arch (default: from KO_DEFAULTPLATFORMS, else host arch).
# OUT asset dir (default: $PWD/bin/microvm-assets/$ARCH, gitignored).
# ATE_INSTALL_KIND "true" for the kind path (stage assets to rustfs); default
# false uploads assets to GCS.
set -o errexit -o nounset -o pipefail
ROOT="$(git rev-parse --show-toplevel)"
cd "${ROOT}"
# Source the environment (cluster, registry, bucket) like the other hack scripts;
# callers set NO_DEV_ENV to skip this and use kind defaults.
if [[ -r .ate-dev-env.sh ]] && [[ -z "${NO_DEV_ENV:-}" ]]; then
source .ate-dev-env.sh
fi
BUCKET_NAME="${BUCKET_NAME:-ate-snapshots}"
KUBECTL_CONTEXT="${KUBECTL_CONTEXT:-}"
ATE_INSTALL_KIND="${ATE_INSTALL_KIND:-false}"
usage() {
cat <<EOF
Usage: $0 (--install | --delete)
Options:
--install Assemble + stage micro-VM assets and apply the cluster-wide
microvm SandboxConfig.
--delete Remove the microvm SandboxConfig from the cluster.
(Bucket contents are left alone.)
-h, --help Show this message.
EOF
}
action=""
while [[ $# -gt 0 ]]; do
case "$1" in
--install) action="install" ;;
--delete) action="delete" ;;
-h|--help) usage; exit 0 ;;
*) echo "Error: unknown argument $1" >&2; usage; exit 1 ;;
esac
shift
done
if [[ -z "${action}" ]]; then
usage
exit 1
fi
# kubectl falls back to localhost:8080 when neither --context nor a kubeconfig
# current-context is set, which surfaces mid-install as a confusing "connection
# refused" from the apply -- after the assets have already been assembled and
# staged. Resolve the target cluster up front instead.
if [[ -z "${KUBECTL_CONTEXT}" ]] && ! kubectl config current-context >/dev/null 2>&1; then
echo "Error: no kube context to target: KUBECTL_CONTEXT is empty and the" >&2
echo " kubeconfig has no current-context." >&2
echo " Set KUBECTL_CONTEXT (e.g. in .ate-dev-env.sh) or run:" >&2
echo " kubectl config use-context <name>" >&2
exit 1
fi
# ANSI color codes for prettier output (mirrors hack/install-ate.sh).
COLOR_CYAN='\033[1;36m'
COLOR_RESET='\033[0m'
log() {
echo -e "${COLOR_CYAN}[install-microvm-deps]: $*${COLOR_RESET}"
}
run_kubectl() {
kubectl ${KUBECTL_CONTEXT:+--context="${KUBECTL_CONTEXT}"} "$@"
}
MANIFEST_TEMPLATE="manifests/microvm/sandboxconfig-microvm.yaml.tmpl"
if [[ "${action}" == "delete" ]]; then
log "Deleting microvm SandboxConfig..."
# Delete by name rather than by manifest so a missing/edited template file
# doesn't block cleanup on an older cluster.
run_kubectl delete --ignore-not-found sandboxconfig microvm
log "Done. (Bucket assets at gs://${BUCKET_NAME}/kata-assets/ left in place.)"
exit 0
fi
# --- install ----------------------------------------------------------------
# Target arch: match the images' platform (KO_DEFAULTPLATFORMS is set by
# .ate-dev-env.sh on GKE and by the kind wrapper); fall back to the host arch.
if [[ -z "${ARCH:-}" ]]; then
if [[ -n "${KO_DEFAULTPLATFORMS:-}" ]]; then
ARCH="${KO_DEFAULTPLATFORMS##*/}"
else
ARCH="$(go env GOARCH)"
fi
fi
OUT="${OUT:-${ROOT}/bin/microvm-assets/$ARCH}"
# --- 1. assets: assemble (if missing or stale) -----------------------------
need_assemble=false
for f in cloud-hypervisor virtiofsd vmlinux rootfs.img configuration-clh.toml; do
if [[ ! -f "${OUT}/${f}" ]]; then
need_assemble=true
break
fi
done
# Presence alone is not enough. The five filenames don't change when a version pin
# moves, so an asset dir assembled before a bump looks complete while holding the old
# bytes — we'd then stage those against a SandboxConfig pinning the new shas, and the
# mismatch would only surface at runtime as an actor wedged in STATUS_RESUMING while
# atelet rejects the download. Compare the stamp assemble.sh left against the one it
# would write now; a dir predating the stamp, or left by a failed assemble (which clears
# the stamp before overwriting anything), has no file and re-assembles.
if [[ "${need_assemble}" == "false" ]]; then
want_stamp="$(ARCH="${ARCH}" hack/microvm-assets/assemble.sh --print-stamp)"
if [[ "$(cat "${OUT}/.asset-versions" 2>/dev/null)" != "${want_stamp}" ]]; then
log "Asset set in ${OUT} is stale (version stamp mismatch); re-assembling."
need_assemble=true
fi
fi
if [[ "${need_assemble}" == "true" ]]; then
log "Assembling micro-VM assets into ${OUT} (ARCH=${ARCH})..."
ARCH="${ARCH}" OUT="${OUT}" hack/microvm-assets/assemble.sh
else
log "Assets already present in ${OUT}; skipping assemble."
fi
# --- 2. stage assets to rustfs (kind) / GCS (GKE) --------------------------
# Upload the five assets under kata-assets/, where atelet fetches them: the
# in-cluster rustfs (S3 API) on kind, or the GCS bucket on GKE.
if [[ "${ATE_INSTALL_KIND}" == "true" ]]; then
log "Staging assets to in-cluster rustfs bucket ${BUCKET_NAME} (kata-assets/)..."
OUT="${OUT}" BUCKET="${BUCKET_NAME}" KUBECTL_CONTEXT="${KUBECTL_CONTEXT}" hack/microvm-assets/stage-to-rustfs.sh
else
log "Uploading assets to gs://${BUCKET_NAME}/kata-assets/ ..."
OUT="${OUT}" BUCKET="${BUCKET_NAME}" hack/microvm-assets/stage-to-gcs.sh
fi
# --- 3. apply the cluster-wide microvm SandboxConfig -----------------------
# The arm64 virtiofsd is built from source (release tag in assemble.sh), so
# its binary bytes are not reproducible across toolchains and its sha can't
# be a fixed pin in the manifest. Compute it from the freshly-staged binary
# and inject it, so the deployed SandboxConfig always matches whatever was
# staged. The downloaded assets (cloud-hypervisor/kernel/rootfs/config, plus
# virtiofsd on amd64 where upstream publishes a prebuilt) keep their
# committed, reproducible per-arch shas.
log "Applying microvm SandboxConfig from ${MANIFEST_TEMPLATE}..."
VIRTIOFSD_SHA256="$(sha256sum "${OUT}/virtiofsd" | awk '{print $1}')"
sed -e "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" \
-e "s|\${VIRTIOFSD_SHA256}|${VIRTIOFSD_SHA256}|g" \
"${MANIFEST_TEMPLATE}" \
| run_kubectl apply -f -
log "Done. ActorTemplates must reference this SandboxConfig by name (sandboxConfig.configName: microvm)."