기술 자료

shdctl artifact command

Mirror Docker images and ORAS artifacts between registries, and verify the result
읽는 시간 10분최근 업데이트: 2일 전

Before you deploy, sync artifacts from the source registry (
artifactSync.sourceRepository
) to the target registry (
configuration.kubernetes.docker.repository
). Set
artifactSync.sourceRepository
in the manifest:
shdctl manifest schema
lists a default for it, but every sync subcommand — the pull-straight case below included — fails with
source registry is required
when it is left out. Use one of these subcommands for the artifact type:
  • shdctl artifact sync images
    — Docker container images (uses
    docker pull
    /
    tag
    /
    push
    )
  • shdctl artifact sync oras
    — ORAS artifacts (registry-to-registry copy via
    oras-go
    )
The manifest's
docker.namespace
is used to prefix image paths on the target registry when set.
To pull straight from Unity's registry rather than mirror, set
configuration.kubernetes.docker.repository
to the source registry and leave
docker.namespace
out. Every sync subcommand,
verify
included, then logs that there is nothing to mirror and exits 0 without contacting either registry — as it does whenever
--target-registry
names the source. The manifest schema refuses a namespace there — every command that reads the manifest,
manifest validate
,
release generate
and
artifact sync
among them, fails naming the field — because generation prefixes every image reference with it whatever the registry, and nothing mirrors images to that path, so the deploy could not pull them. Keep the
docker
block itself: without it every sync subcommand fails, and generation renders image references with no registry at all.
sync oras
and
sync images
also expand any release manifest the release lists.
sync oras
mirrors the artifacts the manifest names, and
sync images
mirrors the Docker images those artifacts run.
The manifest names those images;
versions.yaml
does not. An app and the image it runs therefore reach your registry together, instead of the app arriving alone and failing the first time it runs. A release whose manifest names no images syncs only what
versions.yaml
lists.
To expand the list, both subcommands read the manifest from the source registry. They contact it even when you pass
--dry-run
.
Two further subcommands check a sync rather than perform one:
shdctl artifact sync preflight
proves your credentials work by syncing one artifact of each kind, and
shdctl artifact sync verify
compares what your target registry holds against what your manifest requires without writing to it.
All four subcommands (
images
,
oras
,
preflight
,
verify
) accept:
  • --skip-version-check
    : Skip shdctl version compatibility check against the release package

Preflight

Verify your Docker and ORAS credentials are working before you run a full sync:
shdctl artifact sync preflight
The command picks one Docker image and one ORAS artifact from the release and attempts to sync them — a real copy into your registry, not a simulation. The image can be any in the release, whether or not your manifest enables the feature that needs it, and its local copy is removed once the push succeeds. A successful run confirms pull/push credentials. On failure, the command prints troubleshooting hints, such as expired tokens or a missing
docker login
.
Options:
  • --target-registry
    : Target registry URL (defaults to manifest value)
  • --extracted-release
    : Path to extracted release (defaults to
    ./extracted-release
    )
preflight
and
verify
answer different questions, and in that order: preflight proves the credentials, verify reports the content. Run preflight first — refer to Verify the target registry for why a verify run against a registry you cannot read is not worth reading.

Sync Docker images

  1. Authenticate to both source and target registries before you sync:
    docker login <source-registry>docker login <target-registry>
  2. Preview the commands that would be executed:
    shdctl artifact sync images --dry-run
  3. Run the sync:
    shdctl artifact sync images
Each image is pulled as
linux/amd64
(
docker pull --platform linux/amd64
), so your registry receives a single-platform amd64 image under each tag, whatever the source holds.

What gets mirrored

The mirror is scoped to your manifest: an image that only a feature you have turned off needs is not copied. Five features gate images this way, each read from one manifest field:

Images

Mirrored when

Istio (istiod, proxy, ztunnel, CNI)
configuration.networking.serviceMesh.istio.enabled: true
Prometheus and Grafana
configuration.monitoring.prometheus.enabled: true
Log collection (Loki, Alloy)
configuration.monitoring.logCollection.enabled: true
Database monitoring (the PMM server)
configuration.monitoring.database.enabled: true
The in-cluster object store (garage and its bootstrap job)
configuration.objectStore.provider
is anything but
s3
— including absent, so this one is mirrored unless you bring your own bucket
Every other image in the release is mirrored on every run — including
percona/pmm-client
, the sidecar both database charts pin whether or not database monitoring is enabled, so expect it in a monitoring-off registry.
A run that skips anything reports what it left out. The summary goes to stderr, so it never lands in the middle of the command list a
--dry-run
writes to stdout. For a manifest with Istio, Prometheus, log collection, and database monitoring off, which keeps the in-cluster object store:
Mirroring 91 of 112 versions.yaml entries. Skipped 21: dbMonitoring 1 istio 4 logCollection 6 logCollection,prometheus 1 prometheus 9Run with --all to mirror every image in the release.
Each row names a feature — or, where an image serves more than one, the set of features of which none is enabled — and counts the entries skipped under it. The header counts
versions.yaml
entries rather than images because two entries can name the same reference; the de-duplicated image count is logged separately. Nothing is printed when nothing was skipped.
Pass
--all
to mirror the release's full image set regardless of what your manifest enables. Use it for a registry shared by deployments with different feature sets, or to keep the option of turning a feature on later without going back to Unity's registry for its images.
Otherwise, turning a feature on means re-running
shdctl artifact sync images
: the images it needs were never mirrored, and a deploy cannot pull what is not there.
shdctl artifact sync verify
reports exactly which images a registry is missing.
Options:
  • --dry-run
    : Show commands without executing (default: false)
  • --all
    : Mirror every image in the release, ignoring which features the manifest enables (default: false)
  • --target-registry
    : Target registry URL (defaults to manifest value)
  • --extracted-release
    : Path to extracted release (defaults to
    ./extracted-release
    )
  • --name
    : Sync only images whose target repository (
    <target-registry>/<namespace>/<path>
    ) contains this string, or whose full target reference — as
    verify
    lists it — equals it. A string that matches nothing syncs nothing and exits 0
  • --cleanup
    : Remove local images (
    docker rmi
    ) after each push (default: false)
  • --skip-existing
    : Skip images already present on the target registry, checked with
    docker manifest inspect
    (default: false)
  • --concurrency
    : Number of images to sync in parallel. When the flag is omitted, the manifest's
    artifactSync.concurrency
    applies if it is set, and
    1
    (sequential) otherwise.
    shdctl manifest schema
    lists a default of
    5
    for that field, but a field you leave out is not filled in — set it to sync in parallel.
Example for CI: skip existing, cleanup disk.
shdctl artifact sync images --skip-existing --cleanup

Sync ORAS artifacts

ORAS artifact sync reads authentication from Docker's credential store (
~/.docker/config.json
) automatically. Run
docker login
for both source and target registries before you sync.
shdctl artifact sync oras --dry-run
This prints each copy as the equivalent
oras copy <source> <target>
command. The real run copies in-process, so the
oras
CLI is not needed.
shdctl artifact sync oras
Options:
  • --dry-run
    : Show commands without executing (default: false)
  • --target-registry
    : Target registry URL (defaults to manifest value)
  • --extracted-release
    : Path to extracted release (defaults to
    ./extracted-release
    )
  • --name
    : Sync only ORAS artifacts whose name or target reference contains this string. A string that matches nothing syncs nothing and exits 0
  • --concurrency
    : Number of artifacts to sync in parallel. When the flag is omitted, the manifest's
    artifactSync.concurrency
    applies if it is set, and
    1
    (sequential) otherwise — as for
    sync images
    , the schema's listed default of
    5
    is not applied.

Verify the target registry

Compare what your target registry holds against what your manifest requires. Authenticate to the target registry first (
docker login <target-registry>
):
shdctl artifact sync verify
It probes the target registry for every image in the release — including the ones the release manifest names, which
sync images
mirrors — and reports:
  • required and present — a count.
  • required and MISSING — listed one per line. A deploy cannot pull these, so the command exits non-zero and a CI pipeline can gate a deploy on it. Mirror them with
    shdctl artifact sync images
    .
  • present but not required by this manifest — listed one per line. Not a failure, and nothing to fix: the residue of an earlier
    --all
    run, of a feature you have since turned off, or of
    preflight
    , which copies one image drawn from the whole release. Sync never deletes, so removing them is a registry-side operation.
  • release manifests this target could not answer for — listed one per line. The images they name went unchecked, so the command exits non-zero rather than call the registry clean. Mirror them with
    shdctl artifact sync oras
    .
It reads those manifests from the target registry, not the source, so this command needs nothing from Unity's registry and works on an air-gapped site. Run it after
shdctl artifact sync oras
, which is what copies them there.
Counts are unique image references after de-duplication rather than
versions.yaml
entries — two entries can name the same image. The command only reads the registry: it writes nothing and deletes nothing.
Options:
  • --target-registry
    : Target registry URL (defaults to manifest value)
  • --extracted-release
    : Path to extracted release (defaults to
    ./extracted-release
    )
  • --concurrency
    : Number of images to probe in parallel. When the flag is omitted, the manifest's
    artifactSync.concurrency
    applies if it is set, as it does for the other sync subcommands, and
    4
    otherwise — higher than
    sync images
    because a probe is a metadata read, costing no disk and no image transfer.
Two things to know before acting on a report:
Everything missing usually means credentials, not an empty registry. The probe is a
docker manifest inspect
, which cannot tell "not found" from "not authorized", so an absent or expired registry credential reads exactly like a registry holding nothing and would send you off to re-mirror images you already have. When every required image comes back missing and nothing extraneous was found,
verify
says so and points at
preflight
. That is the runbook order:
shdctl artifact sync preflight
proves the credentials, then
shdctl artifact sync verify
reports the content.
The "present but not required" list is not a full audit of your registry. It covers only the images this release defines: a probe asks about one reference at a time and cannot enumerate a registry. Tags left behind by earlier releases are not reported, so an empty list means "nothing this release defines is here unnecessarily", not "this registry is clean".

Full sync example with ECR

ECR creates a repository on push only where a repository creation template covers its path. With the AWS baseline example in the release package (
extracted-release/platform/shd/aws-baseline-example/
), set
configuration.kubernetes.docker.namespace
to its
ecr_repository_prefix
output, the prefix its template covers.
# Authenticate to both registries (Docker prompts for the password)aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <account>.dkr.ecr.us-east-1.amazonaws.comdocker login -u <user> uccmpprivatecloud.azurecr.io# Preflight: verify authentication worksshdctl artifact sync preflight# Sync Docker images (only those your manifest's enabled features require)shdctl artifact sync images --skip-existing --cleanup# Sync ORAS artifacts (reads Docker credential store automatically)shdctl artifact sync oras# Confirm the registry now holds every image the manifest requiresshdctl artifact sync verify
In automated environments, pipe the password from a secret store with
--password-stdin
instead of passing
-p <password>
on the command line. The
-p
flag writes the password to your shell history and to the process list (visible to
ps aux
), and Docker prints
WARNING! Using --password via the CLI is insecure
when you use it.