기술 자료

shdctl workflows

Run shdctl in your CI pipeline with ArgoCD, or use it for generate-only, air-gapped, or direct Helm deployments
읽는 시간 7분최근 업데이트: 19시간 전

This is the recommended way to run shdctl: in a CI job, with ArgoCD reconciling the rendered charts from a Git repo. It is Mode A of the architecture.

One-time setup

  • Create the deployment namespace (
    configuration.kubernetes.namespace
    ). Nothing in the release creates it, and every step below that touches the cluster needs it.
  • Install ArgoCD so that it reconciles Applications in that namespace. Every application lands there, in ArgoCD's
    default
    project — shdctl applies the top-level one and ArgoCD creates the rest from Git. Install ArgoCD into the deployment namespace, or configure it to watch that namespace (ArgoCD's "Applications in any namespace", which needs the namespace in both its
    application.namespaces
    setting and the
    default
    project's
    sourceNamespaces
    ). Give it read access to the Git repo the pipeline commits the rendered charts to.
  • Point
    deployment.argocd
    in your manifest at that repo
    (the manifest reference).
    repoURL
    and
    destinationServer
    are required;
    targetRevision
    is the branch the pipeline pushes to;
    pathPrefix
    is the directory, relative to the repository root, the charts are committed under. The pipeline below runs at the root of your repository checkout and renders into
    generated-charts/
    , so set
    pathPrefix: generated-charts
    — or change both together.
  • Build
    secrets.import.yaml
    once, with
    --persist
    ,
    so that it carries every value shdctl generates as well as the ones you supply.
    secret generate
    reads the release's secrets schema, so pull the release first:
    shdctl release pull --clean-outputshdctl secret generate --import my-values.yaml --use-defaults --persist secrets.import.yaml
    Check it for
    TBD
    before you store it — a required value missing from
    my-values.yaml
    is saved as that placeholder, and later runs reuse it without warning again. Store that file in your CI secret store, base64-encoded. A value it does not carry is generated afresh on every pipeline run, and deploying a regenerated password over the one a running service holds breaks that service. When an upgrade adds a secret, run
    shdctl secret generate --use-defaults --persist secrets.import.yaml
    against the new release — it reads the file back and generates only the new values — and store the result.
  • Provision a kubeconfig for the CI runner with namespace-scoped RBAC:
    get
    ,
    create
    and
    patch
    on
    Secret
    and on
    argoproj.io/Application
    in the deployment namespace.
    kubectl apply
    reads each object before creating or patching it, which is why
    get
    is needed.
  • Step 0 of the pipeline reads cluster-scoped objects that role cannot. Either grant the CI identity these read-only rules through a ClusterRole, or run
    shdctl cluster check
    yourself before the first deploy and leave it out of the pipeline:
    rules: - apiGroups: [""] resources: ["nodes"] verbs: ["list"] - apiGroups: [""] resources: ["namespaces"] verbs: ["get"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["list"] - apiGroups: ["apiregistration.k8s.io"] resources: ["apiservices"] verbs: ["get"] - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] verbs: ["get"]
    Add
    list
    on
    pods
    for the ArgoCD controller check, which is skipped without it, and
    list
    on
    nodepools
    in
    karpenter.sh
    if Karpenter provides your transformation nodes on demand.
  • Registry credentials for the runner: a Unity registry account for
    release pull
    and, air-gapped, the source side of
    artifact sync
    ; push access to your own registry for its target side.

Pipeline steps

# 0. Validate the manifest, then that the cluster meets the prerequisites (read-only)shdctl manifest validateshdctl cluster check# 1. Pull the release from Unity's registry (read-only)echo "$UNITY_REGISTRY_PASSWORD" | shdctl configure set --username "$UNITY_REGISTRY_USERNAME" --password-stdinshdctl release pull --clean-output# 2. (Air-gapped only) Mirror artifacts to your registry, then confirm the result.# Run `docker login` for Unity's registry and yours first.shdctl artifact sync preflightshdctl artifact sync images --skip-existing --cleanupshdctl artifact sync orasshdctl artifact sync verify# 3. Render ArgoCD app-of-apps charts into generated-charts/, the directory pathPrefix namesshdctl release generate --format argocd --clean-output# 4. Render Kubernetes Secret manifests (secrets.import.yaml decoded from your CI secret store)shdctl secret generate --import secrets.import.yaml --use-defaults --output secrets.yaml# 5. Commit charts to your Git repogit add generated-charts/git commit -m "Deploy release ${RELEASE_VERSION}"git push# 6. Apply Secrets to the cluster (namespace-scoped kubeconfig; every Secret already names its namespace)shdctl secret deploy --file secrets.yaml# 7. Apply the bootstrap Application (namespace-scoped kubeconfig)shdctl release deploy --format argocd# ArgoCD picks up the changes from Git from here on.
For the credentials shdctl reads and the verbs it calls in your cluster, refer to What shdctl touches.

Helm alternative

If you don't run ArgoCD, you can use
--format helm
in the same CI pipeline. Replace steps 3, 5, and 7 with
shdctl release generate --clean-output
and
shdctl release deploy --format helm
; skip the
git push
and the ArgoCD items of the one-time setup. The CI runner then needs a cluster-wide kubeconfig (it runs
helm upgrade --install
directly), which is a weaker trust boundary than the ArgoCD path. ArgoCD is recommended for that reason.
Run
shdctl release deploy --format helm --dry-run
as its own step before the real deploy: it prints every chart's
helm
command, wave by wave, which is the record to read when a deploy stops partway. With
--concurrency
above 1 (or
deployment.helm.concurrency
), it prints the sequential plan, which leaves out the dependency steps a parallel deploy runs.
--retries 1
on the real deploy rides out the first-install race where a chart's CRDs are not yet visible to the next chart.

Other ways to use shdctl

The recommended workflow above (Mode A) is one of several. The required step is always
shdctl release generate
(and usually
shdctl secret generate
alongside it); choose what you do with the output.

Generate-only — bring your own CD (Mode C)

The minimum viable use of shdctl. shdctl renders charts and secrets from your manifest and the extracted release package; your existing CD tooling —
helm
,
kubectl
, Flux, a custom pipeline — handles everything downstream. shdctl never holds a kubeconfig and never touches your cluster.
shdctl release pull --clean-outputshdctl release generate --clean-outputshdctl secret generate --import secrets.import.yaml --use-defaults --output secrets.yaml# Hand off generated-charts/ and secrets.yaml to your existing pipeline.
Refer to the Mode C diagram for the trust boundary.

Air-gapped (Mode B)

Mirror Unity's release artifacts into your registry once from a bastion, then run any of the modes above with no internet access at deploy time — for a Helm deploy, from a host with no Helm chart repository registered (What shdctl touches).
# On the bastion (one-time per release):shdctl release pull --clean-outputshdctl artifact sync preflight # proves the credentialsshdctl artifact sync images --skip-existing --cleanup # only what your features requireshdctl artifact sync orasshdctl artifact sync verify # reports anything still missing# Then continue with generate / deploy from inside your network.
The mirror covers what your manifest's enabled features require, so re-run
shdctl artifact sync images
after changing a feature toggle, or mirror the full set with
--all
.
shdctl artifact sync verify
compares a registry against a manifest and exits non-zero when a required image is absent; run it before every deploy from a mirrored registry. Note the order:
preflight
proves your credentials and
verify
reports content, and a
verify
run against a registry you cannot authenticate to reports everything as missing. Verify the target registry explains how to read a report.
Refer to the Mode B diagram.

Direct Helm deploy

shdctl runs
helm upgrade --install
directly. Suited to operators who already manage Helm releases by hand and have a kubeconfig with cluster-wide deploy rights. No separate architecture diagram — this is a thin wrapper around
helm upgrade --install
; review the Helm flags in Generate and deploy charts.
shdctl release pull --clean-outputshdctl release generate --clean-outputshdctl release deploy --format helm
Pass
--dry-run
first to print every
helm
command, wave by wave, without contacting the cluster. The deploy does not create the namespace: it has to exist first.
For faster deployments, set
--concurrency N
on
shdctl release deploy
(or
deployment.helm.concurrency: N
in your manifest). Charts within the same wave deploy in parallel, largest first; waves themselves remain sequential. Per-chart helm output is buffered and printed when each chart finishes (
==> [chart-name] done in 12.3s
), so line ordering will not match sequential mode. A summary line at the end of every wave and at the end of deploy reports total / succeeded / failed counts and elapsed time. Helm format only. Generate and deploy charts lists every flag.

Minimum requirement

Whichever mode you pick,
shdctl release generate
is the one command that must run. It is what turns your
manifest.yaml
into Helm chart values for the rest of the pipeline.