CLI Reference

Complete reference for the kubectl-unbounded plugin commands.

Overview

kubectl-unbounded is a kubectl plugin that extends kubectl with commands for managing Unbounded sites. Once installed, commands are available as:

kubectl unbounded <command>

The plugin binary can also be invoked directly as kubectl-unbounded.

Installation

Download the plugin binary from the GitHub releases page and place it on your PATH. kubectl automatically discovers plugins named kubectl-<name>.

You can also install via Krew:

kubectl krew install unbounded

Global Behavior

All commands that interact with the cluster accept a --kubeconfig flag. If omitted, the plugin falls back to the KUBECONFIG environment variable. If neither is set, the default kubeconfig location (~/.kube/config) is used.


Commands

kubectl unbounded site

Manage Unbounded sites.

This is a command group with no action of its own. Use one of the subcommands below.


kubectl unbounded install

Bootstrap a cluster with the Unbounded CRDs and unbounded-operator. This command applies the operator manifests and waits for the operator to roll out. The operator itself installs and upgrades the machina and net CRDs at startup, so install no longer applies CRDs directly. It does not deploy component workloads directly; the operator reconciles those from Site.spec.components after Sites are created or updated.

kubectl unbounded install

Optional flags:

FlagTypeDefaultDescription
--kubeconfigstring$KUBECONFIG or defaultPath to kubeconfig file
--namespacestringunbounded-systemNamespace for the operator and default components
--waitbooltrueWait for the operator rollout and CRD establishment
--timeoutduration5m0sTimeout for rollout waits
--api-server-endpointstringauto-discoveredOverride the API server endpoint advertised to provisioned machines; by default the operator discovers it from kube-public/cluster-info, or the KUBERNETES_SERVICE_HOST FQDN on clusters (e.g. AKS) that do not publish cluster-info
--image-registrystringbuild defaultFull image-repository prefix (registry host plus org/namespace) all unbounded images are pulled from
--operator-imagestringbuild defaultunbounded-operator image name and tag, without a registry (e.g. unbounded-operator:v1); the registry comes from --image-registry

Breaking change: the --skip-crds flag has been removed. CRDs are now owned and installed by the operator at startup (operator.BootstrapCRDs), so there is nothing for install to skip. Automation passing --skip-crds must drop it.

--image-registry is the single knob for where all unbounded images come from. It is written to UNBOUNDED_IMAGE_REGISTRY; the operator resolves each component as <registry>/<component>:<operator-version>, and the operator’s own Deployment image is <registry>/<operator-name:tag>. Because both the operator and its components take the registry from this one value, they can never come from different registries. --operator-image overrides only the operator’s name:tag (it must not include a registry); it is rarely needed. The component image tag is always the operator’s compiled version.

Unset, both the registry and the operator name:tag come from the manifests baked into the binary at build time (rendered from CONTAINER_REGISTRY), so fork and mirror builds work without any flag. The registry is applied on every install, not preserved from cluster state, so it cannot drift; upgrading a cluster that stored a pre-change bare ghcr.io rewrites it to the full prefix and install logs the change. A private or air-gapped install sets --image-registry (e.g. --image-registry registry.corp/unbounded); the operator image follows.

install is the only command that bootstraps unbounded-operator (site init requires it to be installed already), so a private or air-gapped setup runs install --image-registry ... first, then site init.

Breaking change: --image-registry is now a full image-repository prefix (registry host plus org/namespace), not a bare host the operator appends /azure/ to. --operator-image is now a name:tag with no registry (the registry comes from --image-registry); a registry-qualified value is rejected. Automation passing a bare ghcr.io to --image-registry, or a fully-qualified image to --operator-image, must update.


kubectl unbounded site init

Initialize a new Unbounded site. This command:

  1. Validates inputs and kubeconfig access.
  2. Verifies unbounded-operator is installed: the cluster must serve the API types site init applies (Site in unbounded-cloud.io/v1alpha3; GatewayPool and SiteGatewayPoolAssignment in net.unbounded-cloud.io/v1alpha1). This is checked via API discovery.
  3. Creates a cluster Site, a remote Site, and related net GatewayPool resources.
  4. Records component choices in Site.spec.components for unbounded-operator.
  5. Creates a bootstrap token for the remote site.

Prerequisite: site init no longer bootstraps unbounded-operator. Run kubectl unbounded install first. If the cluster is not serving the required API types, site init fails with guidance to run install. If those types are served but the operator Deployment is missing or not yet rolled out, site init warns and proceeds (the operator reconciles the Site once ready).

Global components (unbounded-net, machina, and unbounded-storage) are enabled on the cluster Site. metalman is per-site and is enabled on the remote Site when --enable-metalman is set.

Required Flags

FlagTypeDescription
--namestringName of the site
--cluster-node-cidrstringNode CIDR of the control-plane cluster (e.g. 10.224.0.0/16)
--cluster-pod-cidrstringPod CIDR of the control-plane cluster (e.g. 10.244.0.0/16)
--node-cidrstringNode CIDR for the new site (e.g. 10.100.0.0/24)
--pod-cidrstringPod CIDR for the new site (e.g. 10.101.0.0/24)

Optional Flags

FlagTypeDefaultDescription
--kubeconfigstring$KUBECONFIG or defaultPath to kubeconfig file
--manage-cni-pluginbooltrueWhether unbounded-net manages the CNI plugin
--enable-machinabooltrueEnable machina in Site.spec.components
--enable-metalmanboolfalseEnable metalman in Site.spec.components
--enable-storageboolfalseEnable unbounded-storage in Site.spec.components

Breaking change: the --skip-install and --install-timeout flags have been removed. site init no longer installs the operator, so there is nothing to skip or time out. Run kubectl unbounded install first. Automation passing --skip-install must drop it.

Validation

  • All CIDR values must be valid IPv4 CIDR notation.
  • The kubeconfig must be readable.
  • unbounded-operator must be installed (the cluster must serve the required API types).

Example

kubectl unbounded install

kubectl unbounded site init \
  --name my-edge-site \
  --cluster-node-cidr 10.224.0.0/16 \
  --cluster-pod-cidr 10.244.0.0/16 \
  --node-cidr 10.100.0.0/24 \
  --pod-cidr 10.101.0.0/24

With optional components:

kubectl unbounded site init \
  --name dc2 \
  --cluster-node-cidr 10.224.0.0/16 \
  --cluster-pod-cidr 10.244.0.0/16 \
  --node-cidr 10.200.0.0/24 \
  --pod-cidr 10.201.0.0/24 \
  --enable-metalman \
  --enable-storage \
  --kubeconfig ~/.kube/config

kubectl unbounded machine

Manage Unbounded machines.

This is a command group with no action of its own. Use one of the subcommands below.


kubectl unbounded machine register

Register a machine to an existing site. This command:

  1. Creates a Kubernetes Secret containing the SSH private key.
  2. Optionally creates a separate Secret for bastion SSH credentials.
  3. Resolves the bootstrap token created by site init.
  4. Detects the cluster’s Kubernetes version.
  5. Creates a Machine custom resource with SSH and Kubernetes configuration.

Required Flags

FlagTypeDescription
--sitestringName of the site (must match a site created by site init)
--hoststringHost address of the machine, optionally with port (e.g. 10.0.0.5 or 10.0.0.5:2222)
--ssh-usernamestringSSH username for connecting to the machine

Optional Flags

FlagTypeDefaultDescription
--namestringderived from --hostName for the machine (final name is {site}-{name})
--ssh-private-keystring(none)Path to SSH private key file. Required when no bastion flags are set.
--ssh-secret-namestringssh-{site}Name of the Kubernetes Secret for SSH credentials
--bastion-hoststring(none)Host address of the bastion, optionally with port
--bastion-ssh-usernamestringvalue of --ssh-usernameSSH username for the bastion
--bastion-ssh-private-keystringvalue of --ssh-private-keyPath to SSH private key for the bastion
--bastion-ssh-secret-namestringvalue of --ssh-secret-nameName of the Kubernetes Secret for bastion credentials
--kubeconfigstring$KUBECONFIG or defaultPath to kubeconfig file

Default Derivation

  • Machine name: If --name is omitted, it is derived from --host by replacing dots and colons with hyphens, then prefixed with the site name. For example, --site dc1 --host 10.0.0.5:2222 produces the machine name dc1-10-0-0-5-2222.
  • Bastion credentials: Bastion SSH username, key, and secret name all default to the corresponding non-bastion values.

Validation

  • --site, --host, and --ssh-username must be non-empty.
  • --ssh-private-key is required when no bastion flags are specified.
  • Key files (both --ssh-private-key and --bastion-ssh-private-key) must be readable if provided.

Examples

Direct SSH:

kubectl unbounded machine register \
  --site dc1 \
  --host 10.0.0.5 \
  --ssh-username admin \
  --ssh-private-key ~/.ssh/id_ed25519

With explicit machine name:

kubectl unbounded machine register \
  --site dc1 \
  --name worker-1 \
  --host 10.0.0.5 \
  --ssh-username admin \
  --ssh-private-key ~/.ssh/id_ed25519

With bastion (shared credentials):

kubectl unbounded machine register \
  --site dc1 \
  --host 10.0.0.5:2222 \
  --ssh-username admin \
  --ssh-private-key ~/.ssh/id_ed25519 \
  --bastion-host 5.6.7.8

With bastion (separate credentials):

kubectl unbounded machine register \
  --site dc1 \
  --host 10.0.0.5 \
  --ssh-username admin \
  --ssh-private-key ~/.ssh/host_key \
  --bastion-host 5.6.7.8 \
  --bastion-ssh-username bastion-user \
  --bastion-ssh-private-key ~/.ssh/bastion_key \
  --bastion-ssh-secret-name bastion-ssh

kubectl unbounded machine operation

Create and watch MachineOperation resources.

This command group is the resource-oriented surface for day-2 machine operations. It creates the same MachineOperation CRD you can manage directly with kubectl get mop, kubectl describe mop, and kubectl delete mop.


kubectl unbounded machine operation create

Create a MachineOperation.

Required Arguments and Flags

NameTypeDescription
NAMEargumentName of the MachineOperation resource
--kindstringOperation kind: NodeReboot, AgentUpgrade, AgentReset, HostReboot, HostPowerOff, HostPowerOn, or HostReplace
--machine or --selectorstringTarget one Machine by name or select Machines by label selector

AgentUpgrade requires --param downloadURL=<url> and optionally accepts --param sha256=<archive-sha256>.

Optional Flags

FlagTypeDefaultDescription
--paramkey=valuenoneOperation parameter. Repeat for multiple parameters.
--ttlint32unsetSeconds after completion before cleanup. 0 keeps the operation indefinitely.
--waitboolfalseWait until the operation reaches Complete or Failed.
--timeoutduration0Client-side wait timeout. 0 waits indefinitely.
--dry-runstringnonenone, client, or server.
-o, --outputstringnamename, yaml, or json.
--field-managerstringkubectl-unboundedField manager used on create.
--kubeconfigstring$KUBECONFIG or defaultPath to kubeconfig file.

--wait streams progress output and can only be used with the default -o name output.

Examples

Create a host reboot operation:

kubectl unbounded machine operation create reboot-worker-01 \
  --kind HostReboot \
  --machine worker-01

Create and wait for a node reboot operation selected by labels:

kubectl unbounded machine operation create reboot-gpu \
  --kind NodeReboot \
  --selector role=gpu \
  --wait

Generate YAML without creating the operation:

kubectl unbounded machine operation create poweroff-worker-01 \
  --kind HostPowerOff \
  --machine worker-01 \
  --dry-run=client \
  -o yaml

Upgrade the agent:

kubectl unbounded machine operation create upgrade-worker-01 \
  --kind AgentUpgrade \
  --machine worker-01 \
  --param downloadURL=https://example.com/unbounded-agent-linux-amd64.tar.gz \
  --param sha256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

Selector support is implemented at the CRD level. Agent operations support selectors. Metalman bare-metal host operations support selectors when the selector includes unbounded-cloud.io/site=<site>. Cloud VM host operations currently require one operation per Machine.


kubectl unbounded machine operation wait

Wait for an existing MachineOperation to reach Complete or Failed.

kubectl unbounded machine operation wait reboot-worker-01 --timeout 5m

Use native kubectl commands for listing and inspection:

kubectl get mop
kubectl describe mop reboot-worker-01
kubectl get mop reboot-worker-01 -o yaml

Machine Operation Convenience Commands

Convenience commands create a MachineOperation with a generated operation name, default --ttl 300, and --wait=true.

CommandOperation kindNotes
kubectl unbounded machine node-reboot NAMENodeRebootRestarts the nspawn-backed Kubernetes node.
kubectl unbounded machine host-reboot NAMEHostRebootReboots or power-cycles the host through the owning backend.
kubectl unbounded machine power-off NAMEHostPowerOffPowers off the host.
kubectl unbounded machine power-on NAMEHostPowerOnPowers on the host.
kubectl unbounded machine agent-upgrade NAME --download-url URL [--sha256 DIGEST]AgentUpgradeUpgrades the host-side agent binary.
kubectl unbounded machine agent-reset NAME --forceAgentResetRemoves the agent and managed resources from the host. Requires confirmation unless --force is set.
kubectl unbounded machine replace NAME --forceHostReplaceDestructively replaces the host. Requires confirmation unless --force is set.

Common flags:

FlagDefaultDescription
--operation-namegeneratedExplicit MachineOperation name.
--ttl300Seconds after completion before cleanup. 0 keeps indefinitely.
--waittrueWait for terminal operation phase.
--timeout0Client-side wait timeout.
--kubeconfig$KUBECONFIG or defaultPath to kubeconfig file.

Legacy Machine Operation Commands

The older counter-backed commands remain available for compatibility:

CommandMechanism
kubectl unbounded machine reboot NAMEPatches Machine.spec.operations.rebootCounter.
kubectl unbounded machine repave NAMEPatches Machine.spec.operations.repaveCounter and rebootCounter.

These commands do not create MachineOperation resources.


kubectl unbounded overrides

Inspect the component workload overrides the operator reads from the unbounded-component-overrides ConfigMap. See Workload Overrides for the document format and the security model.

CommandDescription
overrides validate [-f FILE]Check syntax, schema, and the allowlist. The checks are offline, so their answer is correct regardless of which operator version is running; they deliberately do not resolve container or volume names, which depend on the workloads the operator renders. With no -f it reads the live ConfigMap, so the default invocation needs a cluster.
overrides listShow the entries the ConfigMap declares, warn about Site names that match no Site, and report any validation failure.
overrides statusShow what the operator actually applied, including any container image drift. Reads persisted state only; performs no rendering or hashing of its own. Exits non-zero when any Site reports overrides Degraded, so it can gate a post-apply check.

Optional Flags

FlagTypeDescription
-f, --filenamestringvalidate only. Document to check, or - for standard input. Repeatable. Accepts a bare overrides document or the ConfigMap manifest you would apply.
--namespacestringNamespace holding the overrides ConfigMap. Defaults to unbounded-system; pass it if the operator is installed elsewhere.
--kubeconfigstringPath to kubeconfig file.
# Check a document before applying it.
kubectl unbounded overrides validate -f overrides.yaml

# Confirm the operator resolved and applied it.
kubectl unbounded overrides status

Environment Variables

VariableDescription
KUBECONFIGFallback kubeconfig path when --kubeconfig is not provided

See Also

  • Getting Started – Walks through site init and machine register step by step.
  • SSH Guide – Detailed SSH provisioning walkthrough with examples.
  • Workload Overrides – Customizing the Deployments and DaemonSets the operator generates.
  • CRD Reference – Full Machine and Image API specification.