Skip to main content

LoadBalancerRequest

A LoadBalancerRequest provisions a cloud-native L4 load balancer for a management cluster's control plane endpoint.

API Version​

butler.butlerlabs.dev/v1alpha1

Scope​

Namespaced

Short Name​

lbr

Description​

LoadBalancerRequest is used during cloud bootstrap to create a load balancer that fronts the control plane nodes. The bootstrap controller creates a LoadBalancerRequest, and the appropriate cloud provider controller (GCP, AWS, or Azure) provisions the cloud-native load balancer and reports its endpoint. That endpoint is then written into Talos machine configs as the control plane address before nodes boot.

On-prem deployments do not use LoadBalancerRequest. They use kube-vip for control plane HA instead.

Specification​

Full Example​

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: LoadBalancerRequest
metadata:
name: butler-mgmt-lb
namespace: butler-system
spec:
# Name of the cluster this LB serves. Used as a prefix for cloud resource names.
clusterName: butler-mgmt

# Reference to ProviderConfig with cloud credentials.
providerConfigRef:
name: gcp-prod
namespace: butler-system

# Backend port (default: 6443)
port: 6443

# Health check port (defaults to port value)
healthCheckPort: 6443

# Backend instances, updated incrementally as CP nodes come online.
targets:
- ip: "10.128.0.10"
instanceName: "butler-mgmt-cp-0"
- ip: "10.128.0.11"
instanceName: "butler-mgmt-cp-1"
- ip: "10.128.0.12"
instanceName: "butler-mgmt-cp-2"

Spec Fields​

FieldTypeRequiredDefaultDescription
clusterNamestringYes--DNS-safe name (1-63 chars, ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$). Immutable after creation.
providerConfigRefProviderReferenceYes--References the ProviderConfig with cloud credentials. Immutable after creation.
portint32No6443Backend port on control plane nodes. Range: 1-65535.
healthCheckPortint32NoSame as portPort for LB health checks. Range: 1-65535.
targets[]LoadBalancerTargetNo--Backend instances to register. Updated incrementally by the bootstrap controller.

LoadBalancerTarget​

FieldTypeDescription
ipstringTarget IP address.
instanceIDstringCloud instance identifier. Used by AWS for instance-based NLB target groups.
instanceNamestringCloud instance name. Used by GCP for target pool registration.

Which target fields are populated depends on the cloud provider:

  • GCP: ip and instanceName
  • AWS: ip and instanceID
  • Azure: ip only (NICs are added to the backend pool directly)

Status​

status:
phase: Ready
endpoint: "35.194.52.218"
resourceID: "butler-mgmt-lb-fwd"
registeredTargets: 3
conditions:
- type: Provisioned
status: "True"
lastTransitionTime: "2026-03-10T12:00:00Z"
reason: "LBReady"
message: "Load balancer resources created"
- type: TargetsSynced
status: "True"
lastTransitionTime: "2026-03-10T12:05:00Z"
reason: "AllTargetsRegistered"
message: "3 targets registered"
lastUpdated: "2026-03-10T12:05:00Z"
observedGeneration: 2

Status Fields​

FieldTypeDescription
phaseLoadBalancerPhaseCurrent lifecycle phase.
endpointstringLB IP address or DNS name. Populated when phase reaches Ready.
resourceIDstringCloud resource identifier used for cleanup.
failureReasonstringMachine-readable failure reason.
failureMessagestringHuman-readable failure details.
registeredTargetsint32Number of backends registered with the LB.
conditions[]ConditionStandard Kubernetes conditions (see below).
lastUpdatedTimeTimestamp of the last status update.
observedGenerationint64Last observed spec generation.

Phases​

PhaseDescription
PendingRequest received, not yet processed by the provider controller.
CreatingCloud LB resources are being provisioned.
ReadyLB is provisioned and has an endpoint. Control plane traffic can flow.
FailedProvisioning failed. Check failureReason and failureMessage.
DeletingLB resources are being torn down.

Conditions​

TypeDescription
ProvisionedTrue when all cloud LB resources (IP, health check, forwarding rule) exist.
TargetsSyncedTrue when all spec.targets are registered with the LB backend.

Cloud Resources by Provider​

Each provider controller creates different cloud resources to implement the L4 passthrough load balancer:

ProviderResources Created
GCPRegional static IP, legacy HTTP health check, target pool, forwarding rule
AWSNetwork Load Balancer (NLB), target group (TCP), listener on port 6443
AzurePublic IP, Standard Load Balancer, health probe, load balancing rule, backend pool

All providers use TCP passthrough (not TLS termination). The kube-apiserver handles TLS directly.

Loopback Interface Patch​

Cloud passthrough load balancers deliver packets with the original destination IP (the LB's IP) unchanged. For the kube-apiserver to accept these connections, each control plane node must recognize the LB IP as a local address. The bootstrap controller handles this by adding a Talos config patch that assigns the LB IP to the loopback interface on each control plane node.

Finalizer​

FinalizerPurpose
butler.butlerlabs.dev/loadbalancerrequestEnsures cloud LB resources are deleted before the CR is removed.

kubectl Output​

$ kubectl get lbr -n butler-system
NAME CLUSTER PHASE ENDPOINT TARGETS AGE
butler-mgmt-lb butler-mgmt Ready 35.194.52.218 3 45m

Examples​

GCP​

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: LoadBalancerRequest
metadata:
name: mgmt-lb
namespace: butler-system
spec:
clusterName: mgmt
providerConfigRef:
name: gcp-config
namespace: butler-system
targets:
- ip: "10.128.0.10"
instanceName: "mgmt-cp-0"
- ip: "10.128.0.11"
instanceName: "mgmt-cp-1"
- ip: "10.128.0.12"
instanceName: "mgmt-cp-2"

AWS​

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: LoadBalancerRequest
metadata:
name: mgmt-lb
namespace: butler-system
spec:
clusterName: mgmt
providerConfigRef:
name: aws-config
namespace: butler-system
targets:
- ip: "10.0.1.10"
instanceID: "i-0abcd1234efgh5678"
- ip: "10.0.1.11"
instanceID: "i-0abcd1234efgh9012"
- ip: "10.0.1.12"
instanceID: "i-0abcd1234efgh3456"

Azure​

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: LoadBalancerRequest
metadata:
name: mgmt-lb
namespace: butler-system
spec:
clusterName: mgmt
providerConfigRef:
name: azure-config
namespace: butler-system
targets:
- ip: "10.0.0.4"
- ip: "10.0.0.5"
- ip: "10.0.0.6"

See Also​