Skip to content

Infra CR reference

Complete reference for Infra (hostedcluster.densityops.com/v1alpha1, namespaced, short name infra). Fields marked Required are enforced by the API schema or runtime validation; everything else is optional with the listed default.

An Infra contains only shared VLAN and component configuration. Create an InfraClusterAttachment for every hosted cluster that should use the shared stack; without an attachment, no cluster-specific DNS or proxy routes are generated.

spec.networkConfig

Defines the secondary network. Required.

Field Type Default Description
cidr string — (Required) IP range of the secondary network, CIDR notation, e.g. 192.0.2.0/24. Validated pattern.
gateway string — (Required) Default gateway on that network, e.g. 192.0.2.1.
networkAttachmentDefinition string — (Required) Name of the Multus NAD representing the VLAN.
networkAttachmentNamespace string (empty) Namespace of the NAD. When empty, oooi uses the namespace of the Infra resource.
dnsServers []string (empty) Upstream DNS servers used by CoreDNS forwarding. Entries may be IPs or the literal "resolv.conf" to inherit node resolvers.

spec.infraComponents.dhcp

DHCP for worker VMs. enabled defaults to true.

Field Type Default Description
enabled bool true Deploy the DHCPServer child and workload.
serverIP string (empty) Static VLAN address of the DHCP server. Must be inside networkConfig.cidr.
rangeStart / rangeEnd string (empty) Inclusive dynamic pool handed to VMs. Exclude all static addresses and MetalLB ranges.
leaseTime duration 1h Lease duration (Go duration syntax: 30m, 1h, 24h).
image string quay.io/cldmnky/oooi:latest for an Infra-generated child Override the DHCP server image (e.g. mirror registry).

The server is KubeVirt-aware: it inspects VirtualMachineInstance interfaces so re-reconciliation does not churn existing leases.

This Infra default is different from the standalone DHCPServer CRD default, which is ghcr.io/cldmnky/hyperdhcp:latest.

spec.infraComponents.dns

Split-horizon CoreDNS. enabled defaults to true.

Field Type Default Description
enabled bool true Deploy the DNSServer child and workload.
serverIP string (empty) Static VLAN address of CoreDNS.
image string quay.io/cldmnky/oooi:latest Override the image that runs the CoreDNS component.

Static answers generated per view:

The pod-network column applies only when internalProxyService is configured. Without it, static HCP answers, including apps and alias names, are omitted from the default view and queries are forwarded upstream.

For apps ingress, a hostname-only LoadBalancer endpoint can be used by Envoy, but oooi emits the VLAN and pod-network wildcard A records only when externalIP is populated. Use an IP-backed MetalLB endpoint when oooi must provide those static DNS answers.

Name(s) VLAN view answers Pod-network view answers
api.<cluster>.<domain> proxy.serverIP proxy.internalProxyService ClusterIP
api-int.<cluster>.<domain> proxy.serverIP internalProxyService ClusterIP
oauth.*, ignition.*, konnectivity.* proxy.serverIP internalProxyService ClusterIP
*.apps.<cluster>.<domain> (when apps ingress is Ready) MetalLB external IP proxy ClusterIP
kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local (when a KubeVirt worker source range is known) proxy.serverIP proxy.internalProxyService ClusterIP

All other names are forwarded to networkConfig.dnsServers.

spec.infraComponents.proxy

Envoy L4 SNI-passthrough gateway. enabled defaults to true.

Field Type Default Description
enabled bool true Deploy the ProxyServer child and workload.
serverIP string (empty) Static VLAN address of Envoy.
internalProxyService string (empty) DNS name or ClusterIP of the proxy Service used in the pod-network DNS view. Omit to hide HCP names from pods. Example: <infra>-proxy.clusters.svc.cluster.local.
proxyImage string envoyproxy/envoy:v1.36.4 Envoy image.
managerImage string quay.io/cldmnky/oooi:latest xDS manager sidecar image.

Generated control-plane backends use 6443 for API traffic and source-scoped Kubernetes Service aliases, and 443 for OAuth, Ignition, konnectivity, and SNI-based Kubernetes aliases. Apps-ingress backends use the configured HTTP/HTTPS ports. Envoy admin 9901 remains internal (ClusterIP only).

status

Field Description
conditions[] Reconciliation status. Ready=True confirms that oooi provisioned the declared components; it does not confirm Deployment availability.
componentStatus.dhcpReady / .dnsReady Provisioning booleans set when the corresponding component is enabled. Check Deployment status for runtime readiness.
componentStatus.proxyReady True when an enabled proxy has at least one valid aggregated backend; it does not indicate Deployment availability.
attachments.total / .ready Count of InfraClusterAttachment resources targeting this Infra, and how many are Ready.
observedGeneration Generation last reconciled.

Immutability notes

  • spec.services on the HostedCluster (not Infra) is immutable after creation — plan publishing strategies up front.
  • Infra fields are mutable. Setting a component's enabled field to false stops its reconciliation but does not delete an existing child resource; delete that child explicitly when retiring the component.

InfraClusterAttachment reference

InfraClusterAttachment (hostedcluster.densityops.com/v1alpha1, short names infraattachment, ica) attaches one HostedCluster to a shared Infra. Create it in the same namespace as the referenced Infra.

spec

Field Type Default Description
infraRef.name string — (Required) Shared Infra in the same namespace.
hostedClusterRef.name / .namespace string namespace: clusters (Required) HyperShift HostedCluster to attach. One attachment per HostedCluster.
dns.clusterName / dns.baseDomain string — (Required) Build the cluster's FQDNs on the shared DNS and proxy.
controlPlaneNamespace string <hc-namespace>-<hc-name> Management-cluster namespace hosting this control plane. Must exist; HyperShift creates it.
apiServerService string kube-apiserver API Service used when the attachment controller builds a hosted-cluster client for apps ingress. Shared proxy API backends currently target kube-apiserver.
externalService object (empty) Optional per-cluster hosting-cluster LoadBalancer exposing the shared Envoy proxy.
appsIngress object (empty) Per-cluster apps ingress. When enabled, MetalLB ranges must be disjoint across attachments sharing a VLAN.

spec.externalService

Optional hosting-cluster LoadBalancer for this attachment. The generated Service is named <attachment>-proxy-external, selects the shared Envoy pods, and exposes only port 443. Each attachment has an independent Service and MetalLB allocation; the Service is owned and cleaned up by that attachment.

Field Type Default Description
enabled bool false Create/reconcile this attachment's external LoadBalancer Service. Setting false removes it.
addressPoolName string (empty) Set as annotation metallb.universe.tf/address-pool to pin a MetalLB pool. Empty = cluster default allocation.
labels map[string]string (empty) Reconciled onto the Service metadata. Use e.g. your ExternalDNS publish label.
annotations map[string]string (empty) Reconciled onto the Service metadata. Use e.g. external-dns.alpha.kubernetes.io/hostname: oauth.<cluster>.<domain>.

Use this to put the attachment's OAuth and other Route-published endpoints on a dedicated public VIP. See Public DNS and OAuth publishing.

status

Field Description
conditions[] Ready reflects aggregation plus apps-ingress state.
domain Resolved <clusterName>.<baseDomain>.
controlPlaneNamespace Resolved control-plane namespace.
appsIngressStatus.* Apps-ingress phase, endpoint, last-sync, and applied-resource identity fields scoped to this cluster; applied identities let cleanup remove resources after a configuration change or disable.

Source-scoped Kubernetes aliases

For KubeVirt NodePools, the controller watches CAPI Machine objects in the management cluster. CAPK mirrors VMI interface addresses into Machine.status.addresses; oooi retains only addresses inside spec.networkConfig.cidr, deduplicates and sorts them, and emits /32 sourcePrefixRanges on the generated alias backend. NodePool membership is used to associate Machines with the attachment, while Machine updates drive address changes.

The aliases are omitted while a KubeVirt NodePool has no usable in-CIDR Machine address. A duplicate source address claimed by two attachments removes only the ambiguous alias routes and sets the Infra condition to DuplicateSourceIP; the fully qualified attachment routes remain available. Source matching is not anti-spoofing or tenant authentication.

Conflicts are visible rather than resolved silently: duplicate domains or duplicate HostedCluster references exclude both attachments from routing and set the referenced Infra's Ready condition to False. See Multiple hosted clusters on one VLAN.