Skip to content
Merged
12 changes: 12 additions & 0 deletions api/v1alpha1/addon_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const (

RegistryProviderCNCFDistribution = "CNCF Distribution"

IngressProviderAWSLoadBalancerController = "aws-lb-controller"

AddonStrategyClusterResourceSet AddonStrategy = "ClusterResourceSet"
AddonStrategyHelmAddon AddonStrategy = "HelmAddon"

Expand Down Expand Up @@ -65,6 +67,9 @@ type AWSAddons struct {

// +kubebuilder:validation:Optional
CSI *AWSCSI `json:"csi,omitempty"`

// +kubebuilder:validation:Optional
Ingress *Ingress `json:"ingress,omitempty"`
}

type DockerAddons struct {
Expand Down Expand Up @@ -359,3 +364,10 @@ type RegistryAddon struct {
// +kubebuilder:validation:Enum="CNCF Distribution"
Provider string `json:"provider"`
}

type Ingress struct {
// The Ingress provider to deploy.
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum="aws-lb-controller"
Provider string `json:"provider"`
}
10 changes: 10 additions & 0 deletions api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,16 @@ spec:
- defaultStorage
- providers
type: object
ingress:
properties:
provider:
description: The Ingress provider to deploy.
enum:
- aws-lb-controller
type: string
required:
- provider
type: object
nfd:
description: NFD tells us to enable or disable the node feature discovery addon.
properties:
Expand Down
10 changes: 10 additions & 0 deletions api/v1alpha1/crds/caren.nutanix.com_eksclusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ spec:
- defaultStorage
- providers
type: object
ingress:
properties:
provider:
description: The Ingress provider to deploy.
enum:
- aws-lb-controller
type: string
required:
- provider
type: object
nfd:
description: NFD tells us to enable or disable the node feature discovery addon.
properties:
Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions api/variables/aggregate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ type Addons struct {
CSI *CSI `json:"csi,omitempty"`

COSI *COSI `json:"cosi,omitempty"`

Ingress *Ingress `json:"ingress,omitempty"`
}

type CSI struct {
Expand All @@ -77,3 +79,7 @@ type CSI struct {
type COSI struct {
carenv1.GenericCOSI `json:",inline"`
}

type Ingress struct {
carenv1.Ingress `json:",inline"`
}
2 changes: 2 additions & 0 deletions charts/cluster-api-runtime-extensions-nutanix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ A Helm chart for cluster-api-runtime-extensions-nutanix
| hooks.csi.nutanix.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-nutanix-csi-helm-values-template"` | |
| hooks.csi.snapshot-controller.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | |
| hooks.csi.snapshot-controller.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-snapshot-controller-helm-values-template"` | |
| hooks.ingress.awsLoadBalancerController.defaultValueTemplateConfigMap.create | bool | `true` | |
| hooks.ingress.awsLoadBalancerController.defaultValueTemplateConfigMap.name | string | `"default-aws-load-balancer-controller-helm-values-template"` | |
| hooks.nfd.crsStrategy.defaultInstallationConfigMap.name | string | `"node-feature-discovery"` | |
| hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | |
| hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-nfd-helm-values-template"` | |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# The clusterName refers the kubernetes.io/cluster/ tag on AWS resources.
# For EKS clusters, the name will be based on the cluster's namespace + a random suffix.
# For AWS clusters, the name will just be based on the cluster name.
{{- $capiProvider := index .Cluster.metadata.labels "cluster.x-k8s.io/provider" }}
{{- if eq $capiProvider "eks" }}
clusterName: "{{ .ControlPlane.spec.eksClusterName }}"
{{- else }}
clusterName: "{{ .Cluster.metadata.name }}"
{{- end }}
# Set this value to avoid stutter in the resource names.
fullnameOverride: aws-load-balancer-controller
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2025 Nutanix. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

{{- if .Values.hooks.ingress.awsLoadBalancerController.defaultValueTemplateConfigMap.create }}
apiVersion: v1
kind: ConfigMap
metadata:
name: '{{ .Values.hooks.ingress.awsLoadBalancerController.defaultValueTemplateConfigMap.name }}'
data:
values.yaml: |-
{{- .Files.Get "addons/aws-load-balancer-controller/values-template.yaml" | nindent 4 }}
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ data:
ChartName: aws-ebs-csi-driver
ChartVersion: 2.51.0
RepositoryURL: '{{ if .Values.helmRepository.enabled }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://kubernetes-sigs.github.io/aws-ebs-csi-driver{{ end }}'
aws-load-balancer-controller: |
ChartName: aws-load-balancer-controller
ChartVersion: 1.13.4
RepositoryURL: '{{ if .Values.helmRepository.enabled }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://aws.github.io/eks-charts{{ end }}'
cilium: |
ChartName: cilium
ChartVersion: 1.18.2
Expand Down
21 changes: 21 additions & 0 deletions charts/cluster-api-runtime-extensions-nutanix/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,27 @@
}
}
},
"ingress": {
"type": "object",
"properties": {
"awsLoadBalancerController": {
"type": "object",
"properties": {
"defaultValueTemplateConfigMap": {
"type": "object",
"properties": {
"create": {
"type": "boolean"
},
"name": {
"type": "string"
}
}
}
}
}
}
},
"nfd": {
"type": "object",
"properties": {
Expand Down
5 changes: 5 additions & 0 deletions charts/cluster-api-runtime-extensions-nutanix/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ hooks:
defaultValueTemplateConfigMap:
create: true
name: default-registry-syncer-helm-values-template
ingress:
awsLoadBalancerController:
defaultValueTemplateConfigMap:
create: true
name: default-aws-load-balancer-controller-helm-values-template

helmAddonsConfigMap: default-helm-addons-config

Expand Down
90 changes: 90 additions & 0 deletions docs/content/addons/aws-load-balancer-controller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
+++
title = "AWS Load Balancer Controller"
icon = "fa-solid fa-balance-scale"
+++

By leveraging CAPI cluster lifecycle hooks, this handler deploys the [AWS Load Balancer Controller] on the new cluster at the `AfterControlPlaneInitialized` phase.

The AWS Load Balancer Controller manages AWS Application Load Balancers (ALB) and Network Load Balancers (NLB) for Kubernetes services and ingresses.

Deployment of this controller is opt-in via the [provider-specific cluster configuration]({{< ref ".." >}}).

The hook uses the [Cluster API Add-on Provider for Helm] to deploy the AWS Load Balancer Controller resources.

## Prerequisites

- AWS EKS cluster
- IAM role with necessary permissions for the AWS Load Balancer Controller

## Example

To enable deployment of the AWS Load Balancer Controller on a cluster, specify the following values:

```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: <NAME>
spec:
topology:
variables:
- name: clusterConfig
value:
addons:
ingress:
provider: "aws-lb-controller"
```

## IAM Permissions

The AWS Load Balancer Controller requires specific IAM permissions to manage load balancers.
See [AWS Load Balancer IAM Policies] for the full list of permissions.
The provided configuration assumes the permissions will be attached to the Nodes.

If attaching these policies to the non-default instance-profile, you may specify the name in the Cluster using the following configuration:

```yaml
- name: workerConfig
value:
eks:
...
iamInstanceProfile: custom.nodes.cluster-api-provider-aws.sigs.k8s.io
```

## Usage

Once deployed, the AWS Load Balancer Controller can be used to:

1. **Create Application Load Balancers (ALB)** for Kubernetes services using the `service.beta.kubernetes.io/aws-load-balancer-type: nlb` annotation
2. **Create Network Load Balancers (NLB)** for Kubernetes services using the `service.beta.kubernetes.io/aws-load-balancer-type: nlb` annotation
3. **Manage Ingress resources** with the `kubernetes.io/ingress.class: alb` annotation
4. **Configure Target Group Bindings** for advanced load balancer configurations

## Example Service

See [AWS Load Balancer NLB Example]

```yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
type: LoadBalancer
loadBalancerClass: service.k8s.aws/nlb
ports:
- port: 80
targetPort: 8080
selector:
app: my-app
```

See other examples in [AWS Load Balancer Example] docs.

[AWS Load Balancer Controller]: https://kubernetes-sigs.github.io/aws-load-balancer-controller/
[Cluster API Add-on Provider for Helm]: https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm
[AWS Load Balancer IAM Policies]: https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/deploy/installation/#option-b-attach-iam-policies-to-nodes
[AWS Load Balancer NLB Example]: https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/nlb/
[AWS Load Balancer Example]: https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/ingress/annotations/
2 changes: 2 additions & 0 deletions examples/capi-quick-start/eks-cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ spec:
storageClassConfigs:
default: {}
snapshotController: {}
ingress:
provider: aws-lb-controller
nfd: {}
eks:
region: us-west-2
Expand Down
5 changes: 5 additions & 0 deletions hack/addons/helm-chart-bundler/repos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ repositories:
charts:
aws-ebs-csi-driver:
- 2.51.0
aws-load-balancer-controller:
repoURL: https://aws.github.io/eks-charts
charts:
aws-load-balancer-controller:
- 1.13.4
cilium:
repoURL: https://helm.cilium.io/
charts:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2025 Nutanix. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

metadata:
name: aws-load-balancer-controller

helmCharts:
- name: aws-load-balancer-controller
namespace: kube-system
repo: https://aws.github.io/eks-charts
releaseName: aws-load-balancer-controller
version: ${AWS_LOAD_BALANCER_CONTROLLER_CHART_VERSION}
includeCRDs: true
skipTests: true
2 changes: 2 additions & 0 deletions hack/examples/patches/eks/initialize-variables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@
nfd: {}
cni:
provider: Cilium
ingress:
provider: aws-lb-controller
21 changes: 21 additions & 0 deletions hack/tools/fetch-images/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,27 @@ func getValuesFileForChartIfNeeded(chartName, carenChartDirectory string) (strin
return "", fmt.Errorf("failed to execute helm values template %w", err)
}

return tempFile.Name(), nil
case "aws-load-balancer-controller":
f := filepath.Join(carenChartDirectory, "addons", "aws-load-balancer-controller", defaultHelmAddonFilename)
tempFile, err := os.CreateTemp("", "")
if err != nil {
return "", fmt.Errorf("failed to create temp file: %w", err)
}

templateInput := map[string]interface{}{
"InfraCluster": map[string]interface{}{
"spec": map[string]interface{}{
"eksClusterName": "tmplCluster",
},
},
}

err = template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
if err != nil {
return "", fmt.Errorf("failed to execute helm values template %w", err)
}

return tempFile.Name(), nil
default:
return "", nil
Expand Down
2 changes: 2 additions & 0 deletions make/addons.mk
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export AWS_CCM_VERSION_132 := v1.32.3
export AWS_CCM_VERSION_133 := v1.33.0
export AWS_CCM_VERSION_134 := v1.34.0

export AWS_LOAD_BALANCER_CONTROLLER_CHART_VERSION := 1.13.4

export NUTANIX_CCM_CHART_VERSION := 0.5.2

export KUBE_VIP_VERSION := v0.9.2
Expand Down
Loading
Loading