README
¶
Gantry deployment artifacts
This directory carries the Helm chart and operator-facing rendered manifests needed to roll out the Gantry agent as a Kubernetes DaemonSet.
Files
The Helm chart under chart/ is the source of truth for resources shared by
standalone and operator-managed installations. make gantry-manifests renders
the internal operator profile into deploy/gantry/rendered/; the Unbounded
operator embeds those files and applies its own image, ConfigMap, and Lease
ownership semantics. The target also renders the standalone node configurator
and examples used by development and benchmark tooling.
| Source | Rendered to | Purpose |
|---|---|---|
chart/templates/daemonset.yaml |
rendered/daemonset.yaml |
One-pod-per-node DaemonSet. |
chart/templates/serviceaccount.yaml |
rendered/serviceaccount.yaml |
Namespace + ServiceAccount + Role + PriorityClass. |
chart/templates/configmap.yaml |
rendered/configmap.yaml |
Default config.yaml (mirrors config.NewDefault()). |
chart/templates/rendezvous-leases.yaml |
rendered/rendezvous-leases.yaml |
Fixed chair Lease set. |
chart/templates/node-config.yaml |
Standalone chart only | Continuously reconciles containerd's Gantry mirror route. |
examples/registry-secret.example.yaml.tmpl |
rendered/examples/registry-secret.example.yaml |
Template Secret for upstream-registry credentials. |
examples/networkpolicy.yaml.tmpl |
rendered/examples/networkpolicy.yaml |
Hardening overlay (NOT applied by default). See Hardening overlays below. |
hosts.toml.template |
(not rendered) | containerd registry mirror config; one file per upstream registry under /etc/containerd/certs.d/<host>/hosts.toml. |
Installation paths
- Operator-managed clusters use the manifests embedded in the
unbounded-operatorbinary. The operator never runs Helm. - Clusters without the operator install the released OCI chart. The chart
continuously reconciles its route under
/etc/containerd/certs.don every selected node. Containerd must already be configured to read that directory; the chart does not edit or restart containerd.
The paths are mutually exclusive. PriorityClass/gantry-low records the active
manager, and both installers reject ownership by the other path.
helm upgrade --install gantry oci://ghcr.io/azure/charts/gantry \
--version <release-without-v> \
--namespace gantry-system \
--create-namespace \
--set image.digest=sha256:<gantry-image-digest> \
--set gantry.upstreamRegistries[0].name=registry.example.com \
--set gantry.upstreamRegistries[0].endpoint=https://registry.example.com
The container image is built from images/gantry/Containerfile via
make image-gantry-local (or make image-gantry-push to push).
Chair sizing and upgrades
gantry.chairCount controls the maximum active chair pool and
gantry.chairSeedCount controls the per-digest seed cohort at a full pool.
Both default to 64 chairs and 8 seeds. The counts have no configured maximum,
but both must be positive and the seed count cannot exceed the chair count.
The active pool is also bounded by the Gantry DaemonSet's desired scheduled
pod count because one agent can hold at most one chair.
The previous chair_holder_count, GANTRY_CHAIR_HOLDER_COUNT, and
--chair-holder-count names remain accepted as deprecated aliases.
For example:
helm upgrade gantry oci://ghcr.io/azure/charts/gantry \
--version <release-without-v> \
--namespace gantry-system \
--reuse-values \
--set gantry.chairCount=128 \
--set gantry.chairSeedCount=100
Increasing the chair count preserves every existing Lease and holder. Agents
create and claim the additional numbered Leases through the normal election
path until the new target is reached. Decreasing it makes holders at IDs above
the new count vacate; the empty Lease objects may remain and are ignored.
Chair Leases carry Helm's keep resource policy so a reduction does not delete
coordination state during a rolling update. This also leaves the Leases behind
on uninstall; delete them explicitly only after every Gantry pod has stopped.
Releases that only understand the original 64-chair set reject higher-numbered Lease names. Upgrading from such a release therefore requires two stages:
- Upgrade every Gantry pod to the count-aware image while keeping
gantry.chairCount=64. - After that rollout completes, raise
gantry.chairCountandgantry.chairSeedCount.
Do not combine these stages in one Helm upgrade. A new pod can create a higher-numbered Lease while old pods are still running, which makes the old pods reject their next chair snapshot.
Metrics
Each agent serves Prometheus metrics on port 9095 (/metrics). Set
metricsService.enabled=true to render Service/gantry-metrics, a headless
Service over the agents that also lists NotReady agents. Use
metricsService.annotations for annotation-driven scrapers, for example a
Datadog endpoints check that scrapes every agent from its own node:
metricsService:
enabled: true
annotations:
ad.datadoghq.com/endpoints.checks: |
{"openmetrics": {"init_config": {}, "instances": [{
"openmetrics_endpoint": "http://%%host%%:9095/metrics",
"namespace": "gantry", "metrics": [".*"]}]}}
## Agent rollout
`updateStrategy.rollingUpdate.maxUnavailable` sets the agent DaemonSet's
rolling-update step as a positive count or percentage. The default `50%`
replaces half of the agents at once; lower it on large clusters to bound how
many nodes lose their local mirror during a rollout:
```sh
--set-string updateStrategy.rollingUpdate.maxUnavailable=10%
Peer transfer tuning
gantry.peerFetchTimeout (default 15m) caps one complete peer blob request,
including streaming the body. It is a safety ceiling, not a stall detector:
the HTTP/2 transport separately probes connections after 10s without reads.
A value much lower than a large layer's transfer time makes requesters abandon
progressing transfers and switch providers.
gantry.transferMaxConcurrentServes (default 10) caps concurrent peer blob
serves per agent. Requests over the cap receive 429 so the requester
re-discovers another provider. 0 means unlimited.
Use gantry.config only when a setting has no dedicated value; it replaces
the entire generated configuration.
Operator Profile
# Render the profile embedded by unbounded-operator.
make gantry-manifests
# Validate and package the standalone chart.
make gantry-chart-lint
make gantry-chart-package GANTRY_CHART_VERSION=0.1.0 GANTRY_CHART_APP_VERSION=v0.1.0
Building the image locally
# Single-arch into local container engine:
make image-gantry-local
# Build and push to $(CONTAINER_REGISTRY):
make image-gantry-push CONTAINER_REGISTRY=ghcr.io/your-org
# Explicit tag:
make image-gantry-local VERSION=v0.6.0
Per-node containerd setup
Nodes provisioned by unbounded-agent already have containerd configured to
read /etc/containerd/certs.d and carry the managed default Gantry mirror
entry in /etc/containerd/certs.d/_default/hosts.toml. On those nodes, install
the Gantry DaemonSet normally; the mirror activates when the pod starts
listening on 127.0.0.1:5000.
ACR attachment is separate from deployment and preserves existing authentication by default. For operator-managed AKS Flex clusters, see the ACR attachment guide for commands, managed-auth opt-in, compatible versions, and limitations.
Standalone Helm installations run DaemonSet/gantry-containerd-config. Its
resident reconciler checks its hosts.toml files every five seconds and
atomically restores chart-owned payloads when they are missing or different,
including after a node upgrade resets host configuration. The reconciler saves
the last managed contents under /etc/containerd/certs.d/.gantry-managed/ so
registry removal, renaming, and routing-mode changes can remove stale files
even after a pod restart. Stale-route cleanup and graceful shutdown remove a
file only when it still matches those saved contents; modified and unowned
files are preserved. Routes left by older versions without saved ownership
records are not removed automatically. Set
nodeConfig.enabled=false when another node-management system owns these files.
The default profile owns _default/hosts.toml. Artifact Streaming instead owns
one registry-specific <registry-host>/hosts.toml for each configured upstream,
leaving AKS's _default/hosts.toml unchanged.
Externally managed installations can instead drop a registry-specific
hosts.toml at:
/etc/containerd/certs.d/<registry-host>/hosts.toml
derived from hosts.toml.template (substitute ${REGISTRY_SERVER}
with the registry's https://... URL). containerd reloads certs.d
on its own; no restart needed.
ACR Artifact Streaming
This integration consumes the existing ACR OverlayBD v0.1.0 artifact contract without running the OverlayBD daemon or snapshotter. Enable it on Linux nodes that support NBD, ext4, EROFS when required by the image, and shared mount propagation.
For a standalone Helm installation, enable the Gantry range endpoint and its host configurator together. Point Gantry's OCI upstream at the node-local AKS Artifact Streaming mirror and select only the streaming node pool:
nodeSelector:
gantry-streaming: "true"
gantry:
artifactStreaming:
enabled: true
upstreamRegistries:
- name: <registry>.azurecr.io
endpoint: http://127.0.0.1:8578?ns=<registry>.azurecr.io
overlaybdConfig:
enabled: true
nodeSelector:
gantry-streaming: "true"
In this mode Gantry uses host networking so it can reach the loopback-only AKS
mirror. Containerd resolves through Gantry on port 5000; Gantry forwards OCI
requests to the AKS mirror on port 8578, preserving its ns query. The AKS
mirror returns the OverlayBD manifest, which triggers Gantry's complete-layer
chair pulls. The Gantry snapshotter reads sealed LSMT layers through the same
Gantry listener under /blobs/, where the source order remains local, peer,
then signed ACR origin.
The adapter accepts raw LSMT, raw ZFile, and tar/PAX-wrapped
overlaybd.commit payloads. ZFile metadata and CRC32C checksums are validated
before exposing the image; LZ4 and Zstandard blocks are fetched and decompressed
on demand with bounded, coalesced range reads. Compression dictionaries,
compressed indexes, and other compression algorithms are rejected explicitly.
The adapter does not download or decompress the entire layer to mount it.
Gantry prefetches mount-critical head and tail regions when an ACR streaming manifest is served or committed by a background peer pull. Overlapping callbacks for the same registry, repository, and manifest share one bounded prefetch job. This also warms metadata when containerd reuses an already-cached manifest without requesting its body again. Prefetch completion logs report the manifest, duration, and number of cached regions; incomplete warmups are reported separately.
AKS initially selects the overlaybd snapshotter on these nodes. Gantry keeps
that native plugin registered, adds a distinct gantry-overlaybd proxy, and
switches CRI image unpacking to the new proxy. The adapter uses a private
in-process overlayfs snapshotter under its state directory for ordinary OCI
layers; only layers with the complete ACR OverlayBD contract use NBD.
The fallback must not call back into containerd's snapshot service: the proxy's
garbage collector would otherwise see independently managed host snapshots.
The registry-specific containerd file lists the AKS mirror after Gantry. If Gantry is unavailable, containerd continues through port 8578 with Artifact Streaming but without Gantry peer reuse.
The adapter DaemonSet runs gantry snapshotter beside the host configurator.
The snapshotter owns both its remote metadata and its ordinary-image fallback
state under /var/lib/gantry/snapshotter; it does not mount the host containerd
socket or reuse the host's snapshot metadata.
The adapter DaemonSet uses OnDelete: a Helm or operator image update does not
replace its pods automatically because the snapshotter owns live NBD devices.
For each affected node, cordon and drain all workloads using the Gantry
snapshotter before deleting that node's adapter pod. Bootstrap its replacement
with native overlayfs, verify the new adapter is ready, restore
gantry-overlaybd for CRI image unpacking, and only then uncordon the node. The adapter cannot prepare
its own replacement container through its socket while that adapter is stopped;
pre-pulling the replacement image alone does not remove this dependency.
The configurator waits for /artifact-streaming/readyz on the listener selected
by overlaybdConfig.gantryEndpoint and for the host-visible snapshotter socket,
loads the nbd module, and verifies device capacity. A custom socket filename
must remain directly under the shared /run/gantry-overlaybd directory. It
then snapshots the current containerd configuration under
/var/lib/gantry/snapshotter-config, enables /etc/containerd/conf.d/*.toml
through structured TOML, and writes a last-wins drop-in that registers
proxy_plugins.gantry-overlaybd and selects it for CRI image unpacking.
Containerd restarts when effective configuration changes or when a previous
activation failed. A pending-activation marker survives apply or restore failures;
retries clear it only after a successful restart and service health check.
Unchanged configuration still requires an active containerd service before the
configurator reports readiness. A second writer
is never overwritten: if either managed file differs from the recorded bytes,
apply or rollback preserves it and reports the conflict.
For an operator-managed installation, opt in through every participating
Site using the same selector. This path assumes unbounded-agent or another
node manager already routes containerd through Gantry. Use the standalone Helm
chart on stock AKS nodes so the registry-specific route is installed alongside
the snapshotter configuration.
apiVersion: unbounded-cloud.io/v1alpha3
kind: Site
metadata:
name: <site-name>
spec:
components:
gantry:
enabled: true
artifactStreaming:
enabled: true
nodeSelector:
kubernetes.azure.com/agentpool: <streaming-node-pool>
The operator rejects an empty selector, a Site that enables Artifact Streaming while disabling Gantry, or conflicting selectors across Sites.
Artifact Streaming rollback
Drain workloads using active Gantry snapshotter devices before disabling the operator
setting. The operator issues deletion of
DaemonSet/gantry-overlaybd-config before applying the non-streaming Gantry
DaemonSet, and the configurator's preStop restores the original host
configuration when it still owns the current value. Kubernetes deletion and
pod termination are asynchronous, which is why workloads must be drained
before this transition.
For standalone Helm, keep the Gantry endpoint available during restoration:
helm upgrade gantry oci://ghcr.io/azure/charts/gantry \
--reuse-values \
--set overlaybdConfig.enabled=false \
--set gantry.artifactStreaming.enabled=true \
--wait
kubectl -n gantry-system wait --for=delete \
daemonset/gantry-overlaybd-config --timeout=5m
After the configurator is gone and streaming workloads are drained, disable
gantry.artifactStreaming.enabled. If the host OverlayBD file was changed by
another owner after Gantry configured it, rollback deliberately leaves that
new value in place; inspect the configurator logs and resolve ownership before
removing the saved state.
Artifact Streaming metrics
Labels are bounded: source is local, peer, or origin; outcome is
success or error; reason is range or origin_url.
| Metric | Use |
|---|---|
gantry_streaming_requests_total{source,outcome} |
Which source served each range, and whether it succeeded. |
gantry_streaming_bytes_total{source} |
Bytes per source; origin is ACR data-plane egress. |
gantry_streaming_time_to_first_byte_seconds{source} |
Latency before the range body starts. |
gantry_streaming_request_duration_seconds{source,outcome} |
End-to-end range duration. |
gantry_streaming_rejected_total{reason} |
Requests refused before a source was chosen. |
gantry_streaming_inflight{source} |
Range bodies currently streaming. |
/artifact-streaming/readyz on the node-local mirror port reports endpoint
readiness. It is loopback-only, so probe it from the node rather than Prometheus.
Artifact Streaming alerts
These separate the failure domains that need different responses. Tune the thresholds against a real workload before paging on them.
- alert: GantryStreamingErrors
expr: |
sum by (instance) (rate(gantry_streaming_requests_total{outcome="error"}[5m]))
/ sum by (instance) (rate(gantry_streaming_requests_total[5m])) > 0.05
for: 10m
annotations:
summary: Gantry is failing OverlayBD range requests on {{ $labels.instance }}.
- alert: GantryStreamingOriginFailing
expr: sum(rate(gantry_streaming_requests_total{source="origin",outcome="error"}[5m])) > 0
for: 10m
annotations:
summary: Signed-origin range reads are failing; suspect ACR or the host allowlist.
- alert: GantryStreamingNoPeerReuse
expr: |
sum(rate(gantry_streaming_requests_total{source="peer",outcome="success"}[30m])) == 0
and sum(rate(gantry_streaming_requests_total{source="origin",outcome="success"}[30m])) > 0
for: 30m
annotations:
summary: Every range is coming from ACR; peer reuse is not happening.
- alert: GantryStreamingRejectingOriginURLs
expr: sum(rate(gantry_streaming_rejected_total{reason="origin_url"}[5m])) > 0
for: 5m
annotations:
summary: Gantry refuses the OverlayBD origin URL; check the host suffix allowlist.
Origin reads are capped at 32 in flight per node. A sustained
gantry_streaming_inflight{source="origin"} at that ceiling means ranges are
queueing behind ACR rather than failing.
Artifact Streaming incident response
| Symptom | Likely cause | Action |
|---|---|---|
| Pods on streaming nodes stall on first read | Gantry agent or snapshotter unavailable on that node | Cordon the node, drain streaming workloads, then set overlaybdConfig.enabled=false to restore the previous containerd snapshotter. |
GantryStreamingOriginFailing while peers still serve |
ACR data plane, or an expired SAS | Ranges backed by a complete peer keep working, so do not disable Gantry; it is the only thing still serving. Escalate to ACR. |
GantryStreamingRejectingOriginURLs |
Allowlist does not cover the registry data endpoint | Add it to gantry.artifactStreaming.allowedHostSuffixes and roll the agent. |
Ranges return to source="origin" after a peer had served them |
Provider record outlived the blob (containerd GC or eviction) | Expected. Gantry fails over within the same request and suppresses that provider for 3m. Investigate only if it persists, which points at containerd GC pressure. |
/artifact-streaming/readyz returns 503 |
Agent still starting, or draining | The gate is sticky until startup completes. If it persists, check the containerd socket; containerd is Gantry's only content store. |
| NBD device errors while Gantry is healthy | NBD capacity, kernel module, or mount propagation | Check the adapter DaemonSet and host nbd module state. Drain workloads before disabling overlaybdConfig. |
Artifact Streaming compatibility
Gantry consumes ACR's existing OverlayBD artifact format but owns the runtime reader and snapshotter.
| Component | Requirement | Owner |
|---|---|---|
| Node pool | Created with Artifact Streaming enabled | AKS |
| Registry | Premium ACR serving streaming artifacts | ACR |
| Artifact contract | OverlayBD v0.1.0 annotations and sealed LSMT layers | ACR |
| Kernel backend | nbd, ext4, and EROFS when selected by the image |
Node image |
| Snapshotter selection | CRI selects gantry-overlaybd; AKS's native overlaybd registration remains intact |
Gantry |
| containerd | Reads /etc/containerd/certs.d; Unbounded-managed nodes pin 2.1.8 |
Unbounded / AKS |
| Host config written | import for /etc/containerd/conf.d/*.toml, proxy_plugins.gantry-overlaybd, and the CRI snapshotter selection |
Gantry |
Every other containerd setting is preserved, and rollback restores the original main config and any pre-existing drop-in exactly.
What to verify after rollout
| Check | How |
|---|---|
| Agents are running | kubectl -n unbounded-system get ds gantry |
| Liveness / readiness | /livez, /readyz on 9095 per pod |
| Metrics | curl http://<pod-ip>:9095/metrics or scrape from Prometheus |
| Routing-table grew | p2p_dht_health_score ≥ 0.7 |
| Mirror is being used | p2p_cache_hit_total increments while a workload rolls out (= containerd content-store hits on the mirror endpoint after Phase 8) |
| Storage backend is containerd | gantry_storage_mode_info{mode="containerd"} == 1 |
| Advertiser reconciling | gantry_advertise_reconcile_total increases at the configured cadence |
Leases are being created on please_pull |
gantry_containerd_lease_created_total increments during cold-start rollouts |
| Origin fallback is rare | p2p_origin_fallback_total stays at ~0 |
| Streaming endpoint is ready | /artifact-streaming/readyz returns 200 on port 5000 for enabled target nodes |
| Streaming source transition | gantry_streaming_requests_total{source="origin",outcome="success"} serves cold ranges, then source="peer" increases after complete providers advertise |
See docs/detailed-design.md §7.6 for the full metric catalog.
Hardening overlays
deploy/examples/ carries optional hardening manifests that are
intentionally not part of the default kubectl apply workflow.
Every overlay there contains at least one site-specific value (CIDR,
endpoint, label) that no shipped manifest can guess correctly across
arbitrary clusters, so applying them unedited will fail the cluster
into a state that is hard to debug.
Production guidance: the default install leaves the mirror listener (5000) and transfer listener (5001) reachable from other pods on the cluster network at
<podIP>:port. ThehostIP: 127.0.0.1binding on the DaemonSet's hostPort only restricts host-side reach; the listener inside the pod is still0.0.0.0. Production installs should adoptexamples/networkpolicy.yaml.tmpl(or an equivalent NetworkPolicy in their own overlay) to close that pod-network gap. The overlay is shipped as an example rather than a default because its allow-list depends on the cluster's node-CIDR range, which is site-specific (see the workflow below).
examples/networkpolicy.yaml
Locks transfer (5001), libp2p (4001), mirror (5000), and metrics (9095) to the minimum traffic each port needs. Holds the manifest shape required by §7.5 but defers four CIDR choices to the operator - apiserver endpoint, kubelet probe source, mirror DNAT source, registry egress. See the long "OPERATOR ACTION REQUIRED" block at the top of the file and the Production caveats table below.
Workflow:
- Roll out the DaemonSet without the overlay and verify
kubectl -n unbounded-system rollout status ds/gantry,p2p_cache_hit_total, and a successful workload pull. - Copy the overlay into your own repository (or a Kustomize /
Helm chart), edit every ipBlock marked "OPERATOR ACTION
REQUIRED", and review against your CNI's hostPort SNAT
behavior (
kubectl get nodes -o yaml | grep -A2 podCIDR, etc.). - Apply with
kubectl apply -f your-overlay/networkpolicy.yaml. Watch/readyzand any in-flight mirror pulls for at least one full image pull cycle - a wrong CIDR will surface asdht routing table empty(no peer libp2p traffic) or as containerdconnection refusedon 5000 (wrong mirror source CIDR), not as a NetworkPolicy validation error. - Roll back with
kubectl delete networkpolicy -n unbounded-system gantry-agentif anything regresses.
Future hardening overlays (Pod Security Standards, dedicated
PriorityClass, alternative hostNetwork: true topology) will live
in the same directory and follow the same "deferred to operator,
not in default install" rule.
Production caveats
A few configuration knobs that need operator attention before going to production:
| Item | Where | What to change |
|---|---|---|
| API server egress CIDR | examples/networkpolicy.yaml |
The egress to TCP/443 and TCP/6443 defaults to 0.0.0.0/0 because managed control planes (EKS / GKE / AKS) and self-hosted clusters reach the apiserver at IPs that don't match a namespaceSelector. Replace with the apiserver's actual CIDR - kubectl get endpoints kubernetes -n default -o jsonpath='{.subsets[*].addresses[*].ip}' for self-hosted clusters; the managed-service docs for hosted control planes. |
| Origin registry egress | examples/networkpolicy.yaml |
The egress to TCP/443 for origin pulls also defaults to 0.0.0.0/0. If the cluster only pulls from a known set of registry endpoints (your private registry, ghcr.io, etc.), restrict this rule to those IPs or labels. |
| Kubelet probe source | examples/networkpolicy.yaml |
Metrics ingress on TCP/9095 currently allows 0.0.0.0/0 so kubelet liveness/readiness probes (sourced from the node IP) reach the pod on strict CNIs. Replace with the node CIDR - kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'. |
| Mirror port 5000 source | examples/networkpolicy.yaml |
Ingress on TCP/5000 defaults to a deliberately-narrow 127.0.0.1/32 placeholder. Most CNIs (Calico, Cilium, and managed offerings) SNAT hostPort traffic so the in-pod source-IP after DNAT is the node IP, NOT 127.0.0.1 - the placeholder will then drop containerd's mirror pulls. Replace with the node CIDR (same command as the kubelet probe row). MUST NOT widen to the pod-network CIDR: that bypasses the hostIP: 127.0.0.1 binding's loopback-only intent. |
| containerd socket access | daemonset.yaml |
The pod mounts /run/containerd, rather than the socket file, so reconnects observe the replacement socket after containerd restarts. It runs with non-root UID 65532 and primary GID 0 because many nodes expose containerd.sock as root:root mode 0660. Validate this on your target node pool before production. If your runtime uses a dedicated socket group, patch runAsGroup/fsGroup to that group; if your policy forbids GID 0, adjust node socket ownership or run a site-specific privileged wrapper. Clearing containerd_socket is no longer a valid escape hatch - after plan-final-copilot-v2 §Phase 8 containerd is Gantry's sole storage backend; without socket access the agent has no content store to read from or write to. The storage_mode config value must remain containerd. |
| Kubernetes RBAC scope | serviceaccount.yaml |
The agent's only Kubernetes access is leases (get, list, create, update) on the configured chair Leases in its own namespace and get on its own DaemonSet for capacity. It runs no informer and opens no watch, and it needs no access to Pods or Nodes. Review the Role to confirm scope hasn't drifted; a ClusterRole should not exist. |
HEAD semantics on cache miss
GET /v2/<repo>/blobs/<digest> on a cache miss warms the cache as a
side effect; HEAD on the same URL does NOT. This is intentional
(see the comment block in internal/mirror/mirror.go at the HEAD
return after writeBlobHeaders) - caching a multi-GB blob just
because a client asked for its size would defeat the bandwidth
amplification fix Gantry exists to provide. A subsequent GET for
the same digest follows the cache-miss path normally and warms
the cache then.
If your client emits HEAD-then-GET patterns where you'd prefer to amortize the origin metadata round-trip, raise the issue upstream (containerd's puller, BuildKit's resolver, etc.) - those clients generally have a one-shot resolve-and-pull mode that skips the HEAD entirely.
Documentation
¶
Overview ¶
Package gantry embeds the rendered gantry peer-to-peer OCI distribution manifests so they can be bundled into binaries that need to apply them (e.g. the unbounded-operator). Shared resources are sourced from chart/ and rendered with the operator values profile. Standalone support templates in this directory are added to the same rendered tree by `make gantry-manifests`; the operator filters those resources before applying.
The `all:` prefix in the embed directive plus the tracked rendered/.gitignore placeholder ensures the directive is satisfiable on a fresh clone (before `make gantry-manifests` has run), so Go tooling (`go build`, `go vet`, golangci-lint, gopls, ...) can load this package without requiring the rendering step to have happened first. The placeholder file is harmless at runtime: consumers that materialize the FS only apply *.yaml/*.yml files.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Manifests = mustSub(manifestsRaw, "rendered")
Manifests exposes the rendered manifests as a filesystem rooted at the rendered/ directory, so consumers see the familiar layout (e.g. "daemonset.yaml", "configmap.yaml", "serviceaccount.yaml").
Functions ¶
This section is empty.
Types ¶
This section is empty.