FireboltInstance reconciler
TheFireboltInstanceReconciler manages the infrastructure that engines depend on: PostgreSQL, the metadata service, and the Envoy gateway proxy. It follows the same level-triggered principles as the engine reconciler.
Architecture
Reconcile steps
EachReconcile call runs through four sequential steps. If any step fails, the reconciler requeues after a short delay and retries from the beginning (earlier steps are idempotent and effectively no-ops when resources already exist).
| Step | Description | Implementation |
|---|---|---|
| 1. Ensure PostgreSQL | Creates Secret (auto-generated credentials), StatefulSet (with volumeClaimTemplate), and headless Service for a postgres:16-alpine instance. The pod runs as the imageβs built-in non-root postgres user (UID 70) with read-only root filesystem, all Linux capabilities dropped, RuntimeDefault seccomp, and emptyDir volumes for /var/run/postgresql and /tmp (the only paths the postgres entrypoint needs to write outside its data PVC). Skipped when spec.metadata.postgres references an external database. | instance_postgres.go |
| 2. Ensure metadata service | Creates ConfigMap (XML config), Deployment (with config and credentials volume mounts), and ClusterIP Service for the metadata service. The Deploymentβs pod template is produced by effectiveMetadataPodTemplate, which merges spec.metadata.template (a user-supplied PodTemplateSpec) with Firebolt Operator-rendered fields. See Component pod templates below. The XML config includes <default_account_id> set to spec.id. The metadata service uses this to provision the account on startup. The pod runs as the metadata imageβs built-in non-root dedicated-pensieve user (UID 1111) with read-only root filesystem, all Linux capabilities dropped, RuntimeDefault seccomp, an emptyDir backing /tmp, and automountServiceAccountToken: false (pensieve does not call the Kubernetes API). All resources use the {instance}-metadata naming convention. | instance_metadata.go |
| 3. Check metadata readiness | Waits for the metadata service Deployment to have at least one ready replica before proceeding. | instance_controller.go |
| 4. Ensure Gateway | Creates ConfigMap (Envoy YAML config), Deployment (with security context, probes, config volume), ClusterIP Service, and PodDisruptionBudget for the Envoy gateway proxy. The Deploymentβs pod template is produced by effectiveGatewayPodTemplate, which merges spec.gateway.template with Firebolt Operator-rendered fields. See Component pod templates below. All resources use the {instance}-gateway naming convention. | instance_gateway.go |
Instance lifecycle phases
Provisioning and transitions to Ready once both the metadata service and gateway have at least one ready replica. If a previously-ready component becomes unhealthy, the phase transitions to Degraded. It returns to Ready once all components recover.
The Failed phase is terminal and indicates a condition that cannot be resolved by re-reconciliation alone. The Firebolt Operator continues to requeue but will not transition out of Failed without manual intervention.
When the metadata service or gateway becomes not-ready, the Firebolt Operator clears the corresponding endpoint from the instance status (metadataEndpoint or gatewayEndpoint). This ensures that dependent engines observe consistent state and block until the instance is fully operational again.
Component pod templates
spec.gateway.template and spec.metadata.template are raw PodTemplateSpec embeds with the same shape as FireboltEngineClass.spec.template. Two effective* helpers live alongside their builders and produce the resolved pod template that the Deployment carries:
effectiveGatewayPodTemplate(...)ininstance_gateway.go.effectiveMetadataPodTemplate(...)ininstance_metadata.go.
| Field | Origin | Notes |
|---|---|---|
| Pod-template labels | User template + Firebolt Operator base labels | Firebolt Operator keys (firebolt.io/instance, firebolt.io/component) win on conflict. User keys outside the reserved prefix pass through. |
| Pod-template annotations | User template + Firebolt Operator-stamped firebolt.io/config-hash | Hash drives the rollout when the rendered config changes. |
nodeSelector / tolerations / affinity / topologySpreadConstraints / priorityClassName | User template | Pass-through. |
serviceAccountName | User template, else Firebolt Operator-built default | Firebolt Operator default for gateway is {instance}-gateway. Metadata has no Firebolt Operator-built default and uses the namespace default service account. |
imagePullSecrets, pod-level securityContext, additional initContainers, additional containers (sidecars) | User template | Pass-through. Metadata adds a non-root floor on top of the userβs PodSecurityContext (RunAsUser/RunAsGroup pinned to the imageβs UID, RuntimeDefault seccomp, RunAsNonRoot true). |
volumes | Firebolt Operator config / tmp / postgres-creds volumes + user volumes | Firebolt Operator volumes prepended. User volumes appended with Firebolt Operator-reserved names filtered as defense-in-depth because the webhook already rejected collisions. |
terminationGracePeriodSeconds, enableServiceLinks | Firebolt Operator-stamped | 15s/false for gateway, 30s/false for metadata. |
Primary container at containers[0] | Firebolt Operator-rendered | Identity, command, args, ports, probes, securityContext, lifecycle, volumeMounts, env, and envFrom all hardcoded. image, imagePullPolicy, and resources taken from the userβs primary-named container when set. |
Replicas, Selector, Strategy) stay on the builder. They arenβt pod-template concerns.
Integration with engine reconciler
EachFireboltEngine declares its parent instance via spec.instanceRef. During reconciliation, the engine controller resolves this reference and reads two fields from the instanceβs status:
metadataEndpoint: The in-cluster address of the metadata gRPC service.spec.id: The instance identifier, used as the metadata account ID.
InstanceReady=False condition on the engineβs status and requeues after 10 seconds. When the instance is healthy, the condition is updated to InstanceReady=True. In both cases the condition update is part of the single updateStatus call at the end of the reconcile. The engine controller performs exactly one status write per reconcile loop, never two.
The engine controller watches FireboltInstance resources via Watches() with a mapper that enqueues all engines referencing the changed instance by name. This means engines react within seconds when their parent instance becomes ready, rather than waiting for error-driven backoff to expire.
The spec.metadataEndpointOverride field on the engine overrides the instance-derived endpoint (but not the instance ID), supporting cross-cluster scenarios where the engine connects to a metadata service via private link.
Instance resource ownership
All resources created by the instance reconciler have:- An
ownerReferencepointing to theFireboltInstanceCR. - A
firebolt.io/instancelabel for listing/filtering. - A
firebolt.io/componentlabel (postgres,metadata, orgateway). - A finalizer on the CR to ensure cleanup of all labelled resources on deletion.