Skip to content

LoadBalancer Service creation fails with 400 Bad Request when Kubernetes node names contain dots (FQDN-style) #994

@markoolfc

Description

@markoolfc

Description

When running cloud-provider-stackit on a self-managed Kubernetes cluster where node names are FQDNs (e.g. worker-0.okd01.example.cloud), creating a type: LoadBalancer Service fails with a 400 Bad Request from the StackIT LoadBalancer API.

The root cause is in pkg/ccm/loadbalancer_spec.go — the lbSpecFromService function passes node.Name directly as the DisplayName for LoadBalancer targets without any sanitization:

targets = append(targets, loadbalancer.Target{
    DisplayName: &node.Name,     // unsanitized — FQDN names contain dots
    Ip:          &address.Address,
})

The StackIT LoadBalancer API validates displayName against [A-Za-z0-9-]{1,63}, which rejects names containing dots (.) and names longer than 63 characters.

This only affects self-managed clusters (OKD, kubeadm, etc.) — StackIT Kubernetes Engine (SKE) clusters use short node names (e.g. pool-worker-0) that comply with the regex.

Steps to reproduce

  1. Deploy cloud-provider-stackit v1.35.2 on a self-managed Kubernetes/OKD cluster where nodes have FQDN names (e.g. worker-0.okd01.example.cloud)
  2. Create a type: LoadBalancer Service:
    apiVersion: v1
    kind: Service
    metadata:
      name: test-lb
    spec:
      type: LoadBalancer
      ports:
        - port: 80
          targetPort: 8080
      selector:
        app: test
  3. Observe the Service stays at EXTERNAL-IP: <pending> indefinitely
  4. Check CCM logs: oc logs -n kube-system deployment/stackit-cloud-controller-manager

Actual behavior

The CCM attempts to create a LoadBalancer via the StackIT API, passing the full FQDN node name (e.g. worker-0.okd01.mer31-dev.stackit.mercury.rbi.cloud) as the target displayName. The StackIT API rejects this with 400 Bad Request because the name contains dots and exceeds 63 characters. The Service remains stuck at <pending> with no external IP assigned.

Expected behavior

The CCM should sanitize node.Name before using it as the LB target displayName to comply with the StackIT API constraint [A-Za-z0-9-]{1,63}. For example, replacing dots with dashes and truncating to 63 characters, or using a hash-based short name.

The same sanitization would need to be applied in compareLBwithSpec to ensure existing LB targets are correctly matched after the name transformation.

Environment

  • Kubernetes version: OKD 4.20 (Kubernetes v1.33)
  • Version of the cloud-provider-stackit: v1.35.2

Additional information

Scope of impact:

  • LoadBalancer Services are completely blocked — no external IPs assigned
  • PVC provisioning (CSI) is NOT affected — works correctly with FQDN node names
  • Affects anyone running cloud-provider-stackit on self-managed clusters with FQDN node names

Suggested fix location: pkg/ccm/loadbalancer_spec.go, in the target-building loop of lbSpecFromService and the comparison logic in compareLBwithSpec.

Workaround: Use Terraform-managed LoadBalancers (stackit_loadbalancer resource) instead of CCM-managed LoadBalancers. This bypasses the CCM LB controller entirely but requires manual IP management.

/kind bug

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions