Skip to content

Configuration

This page covers the manager's own configuration, the credential model, the add-on selector labels, and the cluster-wide policy knobs. The field-by-field CRD reference is auto-generated — see CRD API; every template variable is in Templates & variables.

Manager instance config

The manager reads two instance-level settings from its environment, sourced from the capvco-credentials Secret in its namespace. They are deliberately independent — do not derive one from the other (they differ on white-label deployments, and there's no fixed console./iam. prefix):

Env var Secret key Meaning Example
VCO_PORTAL_URL portalUrl whitesky.cloud portal base URL (without /api/1) https://<your-whitesky.cloud-portal>
VCO_IAM_REFRESH_URL iamRefreshUrl IAM JWT-refresh endpoint https://<your-iam-host>/v1/oauth/jwt/refresh

Set these in the capvco-credentials Secret at install time. Everything else is per-cluster. The whitesky.cloud HTTP client uses per-request deadlines (300 s default; up to 60 min for a VM-image import, which the platform serves synchronously).

Nothing brand-specific is compiled in — the portal URL, IAM URL, customer id and credentials are all configuration, so one build serves any whitesky.cloud portal. You run one manager instance per portal.

Credential model

CAPVCO mints no credentials. Every VCOCluster references a Secret (spec.credentialSecretRef, in the cluster's namespace) holding a client-supplied whitesky.cloud credential (the Cluster API cluster-identity pattern). The controller uses it for all backend operations for that cluster and injects it into the workload cluster for the add-ons — the manager holds no standing credential.

Expected Secret keys:

Key Required Meaning
jwt yes A self-refreshing whitesky.cloud JWT (carries a refresh_token claim).
customer_id yes The whitesky.cloud customer id.
portal_url no Per-cluster override of VCO_PORTAL_URL.
iam_refresh_url no Per-cluster override of VCO_IAM_REFRESH_URL.

Rotating the Secret is picked up automatically (the client cache invalidates on the Secret's resourceVersion), and the credentials injected into workload clusters are re-pushed on change. The JWT refresh preserves scopes and cannot elevate them, so a narrowly-scoped credential stays narrow.

Scope per cluster

Because one credential drives everything for a cluster (and is readable by that cluster's tenant admin), scope it to just what one cluster needs — see the RBAC caveat.

Operator-privileged operations

A few whitesky.cloud APIs are operator-privileged and return 403 for a per-cluster customer credential. They take a separate operator credential (same Secret shape):

Operation Field
VM-image publishing spec.geo.imagePublishCredentialSecretRef
Registry TLS certificate (air-gapped) spec.registry.certCredentialSecretRef

DNS operations (geo endpoints, ExternalDNS, registry domains) work with the customer credential.

Injected workload Secrets

The controller writes these into the workload cluster as add-ons need them (a ClusterResourceSet can't template per-cluster Secret data, so the controller injects them directly):

Secret (namespace) Keys For
csi-driver-secret (csi-driver) client_jwt, customer_id The CSI driver (→ CSI_DRIVER_JWT, CUSTOMER_ID).
vco-lb-credential (capvco-system) VCO_PORTAL_URL, VCO_IAM_REFRESH_URL, VCO_CUSTOMER_ID, VCO_JWT Service-LB / CCM / ExternalDNS webhook.

An idempotent upsert of these Secrets is the rotation mechanism — when the source credential changes, the injected copies are re-pushed.

Add-on selector labels

Features are delivered as ClusterResourceSet add-ons selected by labels on the core CAPI Cluster object (not the VCOCluster). All use the prefix capvco.infrastructure.cluster.x-k8s.io/.

Label Value Add-on
…/cni calico CNI (Calico; veth_mtu pinned to 1350 so any cluster is geo/VPN-safe)
…/csi vco whitesky.cloud CSI driver + StorageClasses
…/csi-encryption openbao Key-backend config for encrypted volumes
…/ccm enabled Cloud-controller-manager (node init + Service-LB)
…/service-lb vco Standalone Service-LoadBalancer controller
…/external-dns enabled ExternalDNS + the whitesky.cloud DNS webhook
…/apiserver-proxy enabled Per-node internal-API proxy (geo)

ccm and service-lb are mutually exclusive

Both run the Service-LB controller. Enable one, never both — see Load balancing.

The stock templates set the common labels for you; you only add labels to turn on optional add-ons.

Cluster-wide policy on VCOCluster.spec

Besides the per-feature subtrees (geo, backup, storage, registry — each covered in its guide), a few cluster-wide knobs:

Field Default Meaning
controlPlaneExposure loadbalancer How :6443 is published: loadbalancer (HA) or portforward (single-CP).
storage.credentialScope location How the CSI credential is scoped: location (the working default), perDisk, or cloudspace. See the RBAC caveat.
driftPolicy (disabled) Drift detection + orphan GC — see below.

Drift policy

spec.driftPolicy periodically compares actual whitesky.cloud resources against desired and acts by mode:

mode Behaviour
Report (default) Detect + surface drift/orphans (condition, metric, events). Never changes the backend.
Reconcile Additionally re-create/repair drifted resources still needed (detection + reporting today; repair incremental).
GC Additionally delete orphans (resources whose owner is gone), subject to resources opt-in and dryRun.
spec:
  driftPolicy:
    mode: GC
    dryRun: true              # log what GC would do, touch nothing
    resources: ["vms"]        # empty = GC nothing; destructive action is always narrow + explicit

dryRun: true and an empty resources list mean even GC mode does nothing destructive until you opt in per resource type — a deliberate safety design.