Skip to main content

ProviderConfig

A ProviderConfig defines connection credentials, infrastructure settings, network configuration, and resource limits for an infrastructure provider.

API Version

butler.butlerlabs.dev/v1alpha1

Scope

Namespaced

Short Name

pc

Note: kubectl get pc resolves to the built-in PriorityClass resource. Use the full name: kubectl get providerconfigs.

Finalizer

butler.butlerlabs.dev/providerconfig

ColumnField
Providerspec.provider
Scopespec.scope.type
Readystatus.ready
Validatedstatus.validated
Agemetadata.creationTimestamp

Description

ProviderConfig stores the credentials, provider-specific settings, network configuration, and resource limits needed to provision tenant cluster infrastructure. Butler supports six provider types: three on-premises providers (Harvester, Nutanix, Proxmox) and three cloud providers (Azure, AWS, GCP). Each provider type has its own configuration section with provider-specific fields.

A ProviderConfig can be scoped to the entire platform or to a specific team, controlling which teams can use it for cluster provisioning. Network configuration supports both cloud-native networking and IPAM-managed address pools with static or elastic allocation modes.

Spec

FieldTypeRequiredDescription
providerProviderTypeYesProvider type. One of: harvester, nutanix, proxmox, azure, aws, gcp
credentialsRefSecretReferenceYesReference to a Secret containing provider credentials
harvesterHarvesterConfigNoHarvester-specific configuration
nutanixNutanixConfigNoNutanix-specific configuration
proxmoxProxmoxConfigNoProxmox-specific configuration
azureAzureConfigNoAzure-specific configuration
awsAWSConfigNoAWS-specific configuration
gcpGCPConfigNoGCP-specific configuration
scopeScopeNoControls which teams can use this provider
networkNetworkConfigNoNetwork and IPAM configuration
limitsLimitsNoResource limits for teams using this provider

SecretReference

FieldTypeRequiredDescription
namestringYesName of the Secret
namespacestringNoNamespace of the Secret. Defaults to the ProviderConfig namespace
keystringNoSpecific key within the Secret data

Provider Configuration

Each provider type requires its own configuration section matching the spec.provider value. Only the section corresponding to the chosen provider type is used; the others are ignored.

HarvesterConfig

Configuration for Harvester HCI clusters.

FieldTypeRequiredDefaultDescription
endpointstringNoHarvester API endpoint URL
namespacestringNo"default"Harvester namespace for VM resources
networkNamestringYesVM network in namespace/name format (e.g., default/vlan40-workloads)
imageNamestringNoVM image name
storageClassNamestringNoStorageClass to use for VM volumes

NutanixConfig

Configuration for Nutanix AHV clusters via Prism Central.

FieldTypeRequiredDefaultDescription
endpointstringYesPrism Central endpoint URL. Must use https:// scheme
portint32No9440Prism Central API port
insecureboolNofalseSkip TLS certificate verification
clusterUUIDstringYesTarget AHV cluster UUID
subnetUUIDstringYesNetwork subnet UUID for VM NICs
imageUUIDstringNoVM image UUID
storageContainerUUIDstringNoStorage container UUID for VM disks

ProxmoxConfig

Configuration for Proxmox VE clusters.

FieldTypeRequiredDefaultDescription
endpointstringYesProxmox API endpoint URL. Must use https:// scheme
insecureboolNofalseSkip TLS certificate verification
nodes[]stringYesTarget Proxmox node names. Minimum 1 entry
storagestringYesStorage identifier for VM disks
templateIDint32NoVM template ID to clone from
vmidRangeVMIDRangeNoRange of VM IDs to allocate

VMIDRange

FieldTypeRequiredDefaultDescription
startint32NoStart of VM ID range. Minimum value: 100
endint32NoEnd of VM ID range. Minimum value: 100

AzureConfig

Configuration for Microsoft Azure.

FieldTypeRequiredDefaultDescription
subscriptionIDstringYesAzure subscription ID
resourceGroupstringYesAzure resource group name
locationstringNoAzure region (e.g., eastus, westeurope)
vnetNamestringNoVirtual network name
subnetNamestringNoSubnet name within the VNet
vmSizestringNoDefault Azure VM size (e.g., Standard_D4s_v3)
imageURNstringNoVM image reference. Supports URN format (publisher:offer:sku:version), managed image resource ID, or shared gallery image version ID

AWSConfig

Configuration for Amazon Web Services.

FieldTypeRequiredDefaultDescription
regionstringYesAWS region (e.g., us-east-1, eu-west-1)
vpcIDstringNoVPC ID. If omitted, the default VPC is used
subnetIDs[]stringNoSubnet IDs for VM placement
securityGroupIDs[]stringNoSecurity group IDs to attach to VMs

GCPConfig

Configuration for Google Cloud Platform.

FieldTypeRequiredDefaultDescription
projectIDstringYesGCP project ID
regionstringYesGCP region (e.g., us-central1, europe-west1)
zonestringNo{region}-aGCP compute zone (e.g., us-central1-a)
networkstringNoVPC network name
subnetworkstringNoSubnetwork name within the VPC
machineTypestringNoDefault GCE machine type (e.g., n2-standard-4)
imageProjectstringNoGCP project containing the source image
imageFamilystringNoImage family to use (e.g., talos-v1-12). Ignored if image is specified
imagestringNoSpecific image name. Takes precedence over imageFamily
serviceAccountstringNoGCE service account email for VM instances
tags[]stringNoNetwork tags applied to VM instances for firewall rules

Provider Scope

The spec.scope field controls which teams can use the ProviderConfig for cluster provisioning.

FieldTypeRequiredDefaultDescription
typestringNo"platform"Scope type. One of: platform, team
teamRefLocalObjectReferenceConditionalReference to the Team. Required when type is team

Platform Scope

When scope.type is platform (or scope is omitted entirely), any team in the Butler platform can reference this ProviderConfig for cluster provisioning. Platform-scoped ProviderConfigs are typically created by platform administrators.

Team Scope

When scope.type is team, only the team referenced by scope.teamRef.name can use this ProviderConfig. Team-scoped ProviderConfigs allow teams to bring their own infrastructure credentials and isolate their provider access from other teams.


Network Configuration

The spec.network section controls IP address management and load balancer allocation for tenant clusters provisioned with this provider.

FieldTypeRequiredDefaultDescription
modestringNo"cloud"Network mode. One of: ipam, cloud
poolRefs[]PoolRefNoReferences to IP address pools. Required when mode is ipam
subnetstringNoSubnet CIDR for node addressing
gatewaystringNoDefault gateway IP address
dnsServers[]stringNoDNS server addresses
loadBalancerLoadBalancerConfigNoLoad balancer IP allocation settings
quotaPerTenantQuotaPerTenantNoPer-tenant IP address quotas

Network Modes

cloud mode (default): Relies on the cloud provider's native networking. IP addresses are assigned by the cloud provider's DHCP or instance metadata service. This is the default mode and is appropriate for AWS, Azure, and GCP providers.

ipam mode: Butler manages IP address allocation from configured address pools. Required for on-premises providers (Harvester, Nutanix, Proxmox) where no cloud DHCP service is available. When ipam mode is selected, poolRefs must reference at least one IP address pool.

warning

IPAM mode (ipam) is required for on-premises providers and is forbidden for cloud providers (azure, aws, gcp). The webhook validates this constraint on create and update.

PoolRef

FieldTypeRequiredDefaultDescription
namestringYesName of the IP address pool resource
priority*int32No0Pool selection priority. Lower values indicate higher priority (0 is tried first)

LoadBalancerConfig

Controls how load balancer IP addresses are allocated to tenant clusters.

FieldTypeRequiredDefaultDescription
defaultPoolSize*int32No8Default number of LB IPs allocated per tenant. Minimum: 1
allocationModestringNo"static"Allocation strategy. One of: static, elastic
initialPoolSize*int32No2Initial pool size when using elastic mode. Minimum: 1
growthIncrement*int32No2Number of IPs to add when the elastic pool grows. Minimum: 1

Static Allocation

In static mode, each tenant cluster receives a fixed block of defaultPoolSize load balancer IPs at provisioning time. The block size does not change during the cluster lifecycle.

Elastic Allocation

In elastic mode, each tenant cluster starts with initialPoolSize load balancer IPs. As demand increases, Butler allocates additional IPs in increments of growthIncrement, up to defaultPoolSize. This conserves IP address space when tenants have variable load balancer requirements.

QuotaPerTenant

FieldTypeRequiredDefaultDescription
maxNodeIPs*int32NoMaximum node IP addresses per tenant. Minimum: 1
maxLoadBalancerIPs*int32NoMaximum load balancer IP addresses per tenant. Minimum: 1

Limits

The spec.limits section constrains resource consumption by teams using this ProviderConfig.

FieldTypeRequiredDefaultDescription
maxClustersPerTeam*int32NoMaximum number of clusters a team can provision. Minimum: 1
maxNodesPerTeam*int32NoMaximum total nodes across all clusters for a team. Minimum: 1

When limits are set, the Butler controller checks them before allowing a TenantCluster to be created or scaled. If a limit is not set, no restriction is enforced for that dimension.


Status

FieldTypeDescription
conditions[]ConditionStandard Kubernetes conditions. Includes Ready, Validated
validatedboolWhether the provider credentials and configuration have been validated
lastValidationTime*TimeTimestamp of the last successful validation
providerVersionstringDetected version of the provider (e.g., Harvester version, Nutanix AOS version)
readyboolWhether the provider is reachable and ready to accept MachineRequests
lastProbeTime*TimeTimestamp of the last health probe
capacityCapacityEstimated available capacity

Capacity

FieldTypeDescription
availableIPsint32Number of IP addresses available in the configured pools
estimatedTenantsint32Estimated number of additional tenant clusters that can be provisioned

Credential Secret Format

Each provider type expects specific keys in the referenced Secret. Create the Secret before creating the ProviderConfig.

Harvester

KeyDescription
kubeconfigHarvester cluster kubeconfig with permissions to manage VMs
apiVersion: v1
kind: Secret
metadata:
name: harvester-credentials
namespace: butler-system
type: Opaque
stringData:
kubeconfig: |
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://harvester.example.com:6443
certificate-authority-data: <base64>
name: harvester
# ...

Nutanix

KeyDescription
usernamePrism Central username
passwordPrism Central password
apiVersion: v1
kind: Secret
metadata:
name: nutanix-credentials
namespace: butler-system
type: Opaque
stringData:
username: admin
password: <prism-central-password>

Proxmox

Proxmox supports either username/password or API token authentication.

KeyDescription
usernameProxmox username (e.g., root@pam)
passwordProxmox password
tokenProxmox API token (alternative to username/password)
apiVersion: v1
kind: Secret
metadata:
name: proxmox-credentials
namespace: butler-system
type: Opaque
stringData:
username: root@pam
password: <proxmox-password>

Azure

KeyDescription
tenantIDAzure Active Directory tenant ID
clientIDService principal application (client) ID
clientSecretService principal client secret
subscriptionIDAzure subscription ID
apiVersion: v1
kind: Secret
metadata:
name: azure-credentials
namespace: butler-system
type: Opaque
stringData:
tenantID: <azure-tenant-id>
clientID: <service-principal-client-id>
clientSecret: <service-principal-secret>
subscriptionID: <azure-subscription-id>

AWS

KeyDescription
accessKeyIDIAM access key ID
secretAccessKeyIAM secret access key
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
namespace: butler-system
type: Opaque
stringData:
accessKeyID: <aws-access-key-id>
secretAccessKey: <aws-secret-access-key>

GCP

KeyDescription
serviceAccountKeyGCP service account key in JSON format
apiVersion: v1
kind: Secret
metadata:
name: gcp-credentials
namespace: butler-system
type: Opaque
stringData:
serviceAccountKey: |
{
"type": "service_account",
"project_id": "my-project",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
"client_email": "[email protected]",
...
}

Webhook Validation

The ProviderConfig admission webhook enforces the following rules.

Create and Update

  • The provider-specific configuration section must be present and valid for the chosen spec.provider type.
  • Provider-specific required fields are validated:
    • Azure: subscriptionID and resourceGroup must be set.
    • AWS: region must be set.
    • GCP: projectID and region must be set.
  • If spec.scope.type is team, spec.scope.teamRef.name must be set.
  • If spec.network.mode is ipam, spec.network.poolRefs must contain at least one entry.
  • IPAM mode is forbidden for cloud providers (azure, aws, gcp).

Delete

  • Deletion is blocked if any TenantCluster references the ProviderConfig via providerConfigRef. Remove or migrate all dependent clusters before deleting.

Examples

On-Premises Harvester with IPAM

A platform-scoped Harvester provider using IPAM for IP address management with static load balancer allocation.

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: ProviderConfig
metadata:
name: harvester-prod
namespace: butler-system
spec:
provider: harvester
credentialsRef:
name: harvester-credentials
namespace: butler-system
harvester:
endpoint: https://harvester.example.com:6443
namespace: default
networkName: default/vlan40-workloads
imageName: default/talos-1.9.0
storageClassName: longhorn
network:
mode: ipam
poolRefs:
- name: prod-ip-pool
priority: 0
- name: overflow-ip-pool
priority: 10
subnet: "10.40.0.0/24"
gateway: "10.40.0.1"
dnsServers:
- "10.40.0.2"
- "10.40.0.3"
loadBalancer:
defaultPoolSize: 8
allocationMode: static
quotaPerTenant:
maxNodeIPs: 20
maxLoadBalancerIPs: 8
limits:
maxClustersPerTeam: 5
maxNodesPerTeam: 50

Nutanix with Static IPAM

A platform-scoped Nutanix provider with IPAM and resource limits.

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: ProviderConfig
metadata:
name: nutanix-datacenter
namespace: butler-system
spec:
provider: nutanix
credentialsRef:
name: nutanix-credentials
nutanix:
endpoint: https://prism.example.com
port: 9440
insecure: false
clusterUUID: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
subnetUUID: "f0e1d2c3-b4a5-6789-0fed-cba987654321"
imageUUID: "11223344-5566-7788-99aa-bbccddeeff00"
storageContainerUUID: "aabbccdd-eeff-0011-2233-445566778899"
network:
mode: ipam
poolRefs:
- name: nutanix-node-pool
priority: 10
subnet: "10.50.0.0/24"
gateway: "10.50.0.1"
dnsServers:
- "10.50.0.10"
loadBalancer:
defaultPoolSize: 4
allocationMode: static
limits:
maxClustersPerTeam: 3
maxNodesPerTeam: 30

Cloud AWS Provider

An AWS provider using cloud-native networking. No IPAM configuration is needed.

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: ProviderConfig
metadata:
name: aws-us-east
namespace: butler-system
spec:
provider: aws
credentialsRef:
name: aws-credentials
aws:
region: us-east-1
vpcID: vpc-0abc123def456789
subnetIDs:
- subnet-0aaa111bbb222ccc
- subnet-0ddd333eee444fff
securityGroupIDs:
- sg-0123456789abcdef0
limits:
maxClustersPerTeam: 10
maxNodesPerTeam: 100

Team-Scoped Azure Provider

An Azure provider scoped to a specific team. Only the platform-team can use this ProviderConfig.

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: ProviderConfig
metadata:
name: azure-platform-team
namespace: team-platform-team
spec:
provider: azure
credentialsRef:
name: azure-credentials
namespace: team-platform-team
azure:
subscriptionID: "12345678-abcd-efgh-ijkl-1234567890ab"
resourceGroup: platform-team-rg
location: eastus
vnetName: platform-vnet
subnetName: tenant-subnet
scope:
type: team
teamRef:
name: platform-team
limits:
maxClustersPerTeam: 5
maxNodesPerTeam: 40

Elastic IPAM Configuration

A Proxmox provider with elastic load balancer IP allocation. Tenant clusters start with a small pool that grows on demand.

apiVersion: butler.butlerlabs.dev/v1alpha1
kind: ProviderConfig
metadata:
name: proxmox-elastic
namespace: butler-system
spec:
provider: proxmox
credentialsRef:
name: proxmox-credentials
proxmox:
endpoint: https://proxmox.example.com:8006
insecure: false
nodes:
- pve-node-01
- pve-node-02
- pve-node-03
storage: local-lvm
templateID: 9000
vmidRange:
start: 200
end: 999
network:
mode: ipam
poolRefs:
- name: proxmox-main-pool
priority: 10
subnet: "192.168.10.0/24"
gateway: "192.168.10.1"
dnsServers:
- "192.168.10.2"
loadBalancer:
defaultPoolSize: 16
allocationMode: elastic
initialPoolSize: 2
growthIncrement: 4
quotaPerTenant:
maxNodeIPs: 10
maxLoadBalancerIPs: 16
limits:
maxClustersPerTeam: 8
maxNodesPerTeam: 40

See Also

  • TenantCluster -- Uses ProviderConfig for infrastructure provisioning
  • Team -- Multi-tenancy unit; team-scoped ProviderConfigs restrict access
  • IPAM Internals -- IPAM, pools, and allocation flows