From d8af2be612bd5bca6e12cf165b347100afb6478a Mon Sep 17 00:00:00 2001 From: Dimitri Koshkin Date: Fri, 3 Oct 2025 10:43:46 -0700 Subject: [PATCH 1/3] build: include AWS Load Balancer controller in Helm chart --- .../README.md | 2 ++ .../values-template.yaml | 1 + .../helm-addon-installation.yaml | 12 +++++++++++ .../templates/helm-config.yaml | 4 ++++ .../values.schema.json | 21 +++++++++++++++++++ .../values.yaml | 6 ++++++ hack/addons/helm-chart-bundler/repos.yaml | 5 +++++ .../kustomization.yaml.tmpl | 17 +++++++++++++++ hack/tools/fetch-images/main.go | 21 +++++++++++++++++++ make/addons.mk | 2 ++ 10 files changed, 91 insertions(+) create mode 100644 charts/cluster-api-runtime-extensions-nutanix/addons/aws-load-balancer-controller/values-template.yaml create mode 100644 charts/cluster-api-runtime-extensions-nutanix/templates/addons/aws-load-balancer-controller/helm-addon-installation.yaml create mode 100644 hack/addons/kustomize/aws-load-balancer-controller/kustomization.yaml.tmpl diff --git a/charts/cluster-api-runtime-extensions-nutanix/README.md b/charts/cluster-api-runtime-extensions-nutanix/README.md index 94ddf736c..4ed0f0ead 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/README.md +++ b/charts/cluster-api-runtime-extensions-nutanix/README.md @@ -46,6 +46,8 @@ A Helm chart for cluster-api-runtime-extensions-nutanix | helmRepository.securityContext.fsGroup | int | `65532` | | | helmRepository.securityContext.runAsGroup | int | `65532` | | | helmRepository.securityContext.runAsUser | int | `65532` | | +| hooks.addons.awsLoadBalancerController.defaultValueTemplateConfigMap.create | bool | `true` | | +| hooks.addons.awsLoadBalancerController.defaultValueTemplateConfigMap.name | string | `"default-aws-load-balancer-controller-helm-values-template"` | | | hooks.ccm.aws.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | | | hooks.ccm.aws.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-aws-ccm-helm-values-template"` | | | hooks.ccm.aws.k8sMinorVersionToCCMVersion."1.30" | string | `"v1.30.8"` | | diff --git a/charts/cluster-api-runtime-extensions-nutanix/addons/aws-load-balancer-controller/values-template.yaml b/charts/cluster-api-runtime-extensions-nutanix/addons/aws-load-balancer-controller/values-template.yaml new file mode 100644 index 000000000..0b45a0d35 --- /dev/null +++ b/charts/cluster-api-runtime-extensions-nutanix/addons/aws-load-balancer-controller/values-template.yaml @@ -0,0 +1 @@ +clusterName: "{{ .ControlPlane.spec.eksClusterName }}" diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/addons/aws-load-balancer-controller/helm-addon-installation.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/addons/aws-load-balancer-controller/helm-addon-installation.yaml new file mode 100644 index 000000000..0d7ebfb44 --- /dev/null +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/addons/aws-load-balancer-controller/helm-addon-installation.yaml @@ -0,0 +1,12 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +{{- if .Values.hooks.addons.awsLoadBalancerController.defaultValueTemplateConfigMap.create }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: '{{ .Values.hooks.addons.awsLoadBalancerController.defaultValueTemplateConfigMap.name }}' +data: + values.yaml: |- + {{- .Files.Get "addons/aws-load-balancer-controller/values-template.yaml" | nindent 4 }} +{{- end -}} diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml index 9d668b380..7f7d07d77 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml @@ -15,6 +15,10 @@ data: ChartName: aws-ebs-csi-driver ChartVersion: 2.48.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 diff --git a/charts/cluster-api-runtime-extensions-nutanix/values.schema.json b/charts/cluster-api-runtime-extensions-nutanix/values.schema.json index c59eeba83..b3ccfd6f3 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/values.schema.json +++ b/charts/cluster-api-runtime-extensions-nutanix/values.schema.json @@ -118,6 +118,27 @@ "hooks": { "type": "object", "properties": { + "addons": { + "type": "object", + "properties": { + "awsLoadBalancerController": { + "type": "object", + "properties": { + "defaultValueTemplateConfigMap": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + } + } + } + } + }, "ccm": { "type": "object", "properties": { diff --git a/charts/cluster-api-runtime-extensions-nutanix/values.yaml b/charts/cluster-api-runtime-extensions-nutanix/values.yaml index d08e0eca6..6e4226324 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/values.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/values.yaml @@ -117,6 +117,12 @@ hooks: create: true name: default-registry-syncer-helm-values-template + addons: + awsLoadBalancerController: + defaultValueTemplateConfigMap: + create: true + name: default-aws-load-balancer-controller-helm-values-template + helmAddonsConfigMap: default-helm-addons-config deployDefaultClusterClasses: true diff --git a/hack/addons/helm-chart-bundler/repos.yaml b/hack/addons/helm-chart-bundler/repos.yaml index 159824de0..19a3093ed 100644 --- a/hack/addons/helm-chart-bundler/repos.yaml +++ b/hack/addons/helm-chart-bundler/repos.yaml @@ -16,6 +16,11 @@ repositories: charts: aws-ebs-csi-driver: - 2.48.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: diff --git a/hack/addons/kustomize/aws-load-balancer-controller/kustomization.yaml.tmpl b/hack/addons/kustomize/aws-load-balancer-controller/kustomization.yaml.tmpl new file mode 100644 index 000000000..f40904ee5 --- /dev/null +++ b/hack/addons/kustomize/aws-load-balancer-controller/kustomization.yaml.tmpl @@ -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 diff --git a/hack/tools/fetch-images/main.go b/hack/tools/fetch-images/main.go index dcc84584a..38453a6d2 100644 --- a/hack/tools/fetch-images/main.go +++ b/hack/tools/fetch-images/main.go @@ -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 diff --git a/make/addons.mk b/make/addons.mk index 4bc086fac..54cd7ad78 100644 --- a/make/addons.mk +++ b/make/addons.mk @@ -18,6 +18,8 @@ export AWS_CCM_VERSION_131 := v1.31.5 export AWS_CCM_VERSION_132 := v1.32.1 export AWS_CCM_VERSION_133 := v1.33.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.1 From e92da5291b22881d31f1706f12b62302171c914e Mon Sep 17 00:00:00 2001 From: Dimitri Koshkin Date: Mon, 6 Oct 2025 12:02:55 -0700 Subject: [PATCH 2/3] feat: deploy AWS Load Balancer controller --- .../awsloadbalancercontroller/doc.go | 12 ++ .../awsloadbalancercontroller/handler.go | 157 ++++++++++++++++++ pkg/handlers/lifecycle/config/cm.go | 29 ++-- pkg/handlers/lifecycle/handlers.go | 56 ++++--- 4 files changed, 214 insertions(+), 40 deletions(-) create mode 100644 pkg/handlers/lifecycle/awsloadbalancercontroller/doc.go create mode 100644 pkg/handlers/lifecycle/awsloadbalancercontroller/handler.go diff --git a/pkg/handlers/lifecycle/awsloadbalancercontroller/doc.go b/pkg/handlers/lifecycle/awsloadbalancercontroller/doc.go new file mode 100644 index 000000000..30bb62eba --- /dev/null +++ b/pkg/handlers/lifecycle/awsloadbalancercontroller/doc.go @@ -0,0 +1,12 @@ +// Copyright 2025 Nutanix. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package awsloadbalancercontroller provides lifecycle handlers for deploying the AWS Load Balancer Controller addon. +// +// The AWS Load Balancer Controller manages AWS Application Load Balancers (ALB) and Network Load Balancers (NLB) +// for Kubernetes services and ingresses. This package provides handlers that deploy the controller using +// the Cluster API Add-on Provider for Helm (CAAPH). +// +// The handler automatically installs the AWS Load Balancer Controller during the AfterControlPlaneInitialized +// lifecycle phase, ensuring the controller is available for managing load balancer resources. +package awsloadbalancercontroller diff --git a/pkg/handlers/lifecycle/awsloadbalancercontroller/handler.go b/pkg/handlers/lifecycle/awsloadbalancercontroller/handler.go new file mode 100644 index 000000000..43f3b5ebe --- /dev/null +++ b/pkg/handlers/lifecycle/awsloadbalancercontroller/handler.go @@ -0,0 +1,157 @@ +// Copyright 2025 Nutanix. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package awsloadbalancercontroller + +import ( + "context" + "fmt" + + "github.com/spf13/pflag" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" + ctrl "sigs.k8s.io/controller-runtime" + ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/v1alpha1" + commonhandlers "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/lifecycle" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/utils" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/lifecycle/addons" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/lifecycle/config" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/options" +) + +const ( + // Abbreviate name to be <63 characters with the UUID suffix. + defaultHelmReleaseName = "aws-lb-controller" + defaultHelmReleaseNamespace = "kube-system" +) + +type ControllerConfig struct { + *options.GlobalOptions + + helmAddonConfig *addons.HelmAddonConfig +} + +func NewControllerConfig(globalOptions *options.GlobalOptions) *ControllerConfig { + return &ControllerConfig{ + GlobalOptions: globalOptions, + helmAddonConfig: addons.NewHelmAddonConfig( + "default-aws-load-balancer-controller-helm-values-template", + defaultHelmReleaseNamespace, + defaultHelmReleaseName, + ), + } +} + +func (c *ControllerConfig) AddFlags(prefix string, flags *pflag.FlagSet) { + c.helmAddonConfig.AddFlags(prefix+".helm-addon", flags) +} + +type DefaultAWSLoadBalancerController struct { + client ctrlclient.Client + config *ControllerConfig + helmChartInfoGetter *config.HelmChartGetter + + variableName string // points to the global config variable + variablePath []string // path of this variable on the global config variable +} + +var ( + _ commonhandlers.Named = &DefaultAWSLoadBalancerController{} + _ lifecycle.AfterControlPlaneInitialized = &DefaultAWSLoadBalancerController{} + _ lifecycle.BeforeClusterUpgrade = &DefaultAWSLoadBalancerController{} +) + +func New( + c ctrlclient.Client, + cfg *ControllerConfig, + helmChartInfoGetter *config.HelmChartGetter, +) *DefaultAWSLoadBalancerController { + return &DefaultAWSLoadBalancerController{ + client: c, + config: cfg, + helmChartInfoGetter: helmChartInfoGetter, + variableName: v1alpha1.ClusterConfigVariableName, + variablePath: []string{"addons", "loadBalancerController"}, + } +} + +func (n *DefaultAWSLoadBalancerController) Name() string { + return "AWSLoadBalancerControllerHandler" +} + +func (n *DefaultAWSLoadBalancerController) AfterControlPlaneInitialized( + ctx context.Context, + req *runtimehooksv1.AfterControlPlaneInitializedRequest, + resp *runtimehooksv1.AfterControlPlaneInitializedResponse, +) { + commonResponse := &runtimehooksv1.CommonResponse{} + n.apply(ctx, &req.Cluster, commonResponse) + resp.Status = commonResponse.GetStatus() + resp.Message = commonResponse.GetMessage() +} + +func (n *DefaultAWSLoadBalancerController) BeforeClusterUpgrade( + ctx context.Context, + req *runtimehooksv1.BeforeClusterUpgradeRequest, + resp *runtimehooksv1.BeforeClusterUpgradeResponse, +) { + commonResponse := &runtimehooksv1.CommonResponse{} + n.apply(ctx, &req.Cluster, commonResponse) + resp.Status = commonResponse.GetStatus() + resp.Message = commonResponse.GetMessage() +} + +func (n *DefaultAWSLoadBalancerController) apply( + ctx context.Context, + cluster *clusterv1.Cluster, + resp *runtimehooksv1.CommonResponse, +) { + clusterKey := ctrlclient.ObjectKeyFromObject(cluster) + + log := ctrl.LoggerFrom(ctx).WithValues( + "cluster", + clusterKey, + ) + + // For now, always enable the AWS Load Balancer Controller + // FIXME: Add proper variable checking when APIs are added + if provider := utils.GetProvider(cluster); provider != "eks" { + log.V(5).Info("Skipping AWS Load Balancer Controller handler,not an EKS cluster", provider) + return + } + + log.Info("Installing AWS Load Balancer Controller addon") + + helmChart, err := n.helmChartInfoGetter.For(ctx, log, config.AWSLoadBalancerController) + if err != nil { + log.Error( + err, + "failed to get configmap with helm settings", + ) + resp.SetStatus(runtimehooksv1.ResponseStatusFailure) + resp.SetMessage( + fmt.Sprintf("failed to get configuration to create helm addon: %v", + err, + ), + ) + return + } + + strategy := addons.NewHelmAddonApplier( + n.config.helmAddonConfig, + n.client, + helmChart, + ) + + if err := strategy.Apply(ctx, cluster, n.config.DefaultsNamespace(), log); err != nil { + err = fmt.Errorf("failed to apply AWS Load Balancer Controller addon: %w", err) + resp.SetStatus(runtimehooksv1.ResponseStatusFailure) + resp.SetMessage(err.Error()) + return + } + + resp.SetStatus(runtimehooksv1.ResponseStatusSuccess) +} diff --git a/pkg/handlers/lifecycle/config/cm.go b/pkg/handlers/lifecycle/config/cm.go index d7134fd87..73a714156 100644 --- a/pkg/handlers/lifecycle/config/cm.go +++ b/pkg/handlers/lifecycle/config/cm.go @@ -17,20 +17,21 @@ import ( type Component string const ( - Autoscaler Component = "cluster-autoscaler" - Tigera Component = "tigera-operator" - Cilium Component = "cilium" - NFD Component = "nfd" - NutanixStorageCSI Component = "nutanix-storage-csi" - SnapshotController Component = "snapshot-controller" - NutanixCCM Component = "nutanix-ccm" - MetalLB Component = "metallb" - LocalPathProvisionerCSI Component = "local-path-provisioner-csi" - AWSEBSCSI Component = "aws-ebs-csi" - AWSCCM Component = "aws-ccm" - COSIController Component = "cosi-controller" - CNCFDistributionRegistry Component = "cncf-distribution-registry" - RegistrySyncer Component = "registry-syncer" + Autoscaler Component = "cluster-autoscaler" + Tigera Component = "tigera-operator" + Cilium Component = "cilium" + NFD Component = "nfd" + NutanixStorageCSI Component = "nutanix-storage-csi" + SnapshotController Component = "snapshot-controller" + NutanixCCM Component = "nutanix-ccm" + MetalLB Component = "metallb" + LocalPathProvisionerCSI Component = "local-path-provisioner-csi" + AWSEBSCSI Component = "aws-ebs-csi" + AWSCCM Component = "aws-ccm" + AWSLoadBalancerController Component = "aws-load-balancer-controller" + COSIController Component = "cosi-controller" + CNCFDistributionRegistry Component = "cncf-distribution-registry" + RegistrySyncer Component = "registry-syncer" ) type HelmChartGetter struct { diff --git a/pkg/handlers/lifecycle/handlers.go b/pkg/handlers/lifecycle/handlers.go index 38704c0f4..2d262d879 100644 --- a/pkg/handlers/lifecycle/handlers.go +++ b/pkg/handlers/lifecycle/handlers.go @@ -11,6 +11,7 @@ import ( "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/v1alpha1" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/lifecycle" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/lifecycle/awsloadbalancercontroller" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/lifecycle/ccm" awsccm "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/lifecycle/ccm/aws" nutanixccm "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/lifecycle/ccm/nutanix" @@ -34,20 +35,21 @@ import ( ) type Handlers struct { - globalOptions *options.GlobalOptions - calicoCNIConfig *calico.CNIConfig - ciliumCNIConfig *cilium.CNIConfig - nfdConfig *nfd.Config - clusterAutoscalerConfig *clusterautoscaler.Config - ebsConfig *awsebs.Config - nutanixCSIConfig *nutanixcsi.Config - awsccmConfig *awsccm.AWSCCMConfig - nutanixCCMConfig *nutanixccm.Config - metalLBConfig *metallb.Config - localPathCSIConfig *localpath.Config - snapshotControllerConfig *snapshotcontroller.Config - cosiControllerConfig *cosi.ControllerConfig - distributionConfig *cncfdistribution.Config + globalOptions *options.GlobalOptions + calicoCNIConfig *calico.CNIConfig + ciliumCNIConfig *cilium.CNIConfig + nfdConfig *nfd.Config + clusterAutoscalerConfig *clusterautoscaler.Config + ebsConfig *awsebs.Config + nutanixCSIConfig *nutanixcsi.Config + awsccmConfig *awsccm.AWSCCMConfig + nutanixCCMConfig *nutanixccm.Config + metalLBConfig *metallb.Config + localPathCSIConfig *localpath.Config + snapshotControllerConfig *snapshotcontroller.Config + cosiControllerConfig *cosi.ControllerConfig + awsLoadBalancerControllerConfig *awsloadbalancercontroller.ControllerConfig + distributionConfig *cncfdistribution.Config } func New( @@ -58,18 +60,19 @@ func New( calicoCNIConfig: &calico.CNIConfig{ GlobalOptions: globalOptions, }, - ciliumCNIConfig: &cilium.CNIConfig{GlobalOptions: globalOptions}, - nfdConfig: nfd.NewConfig(globalOptions), - clusterAutoscalerConfig: &clusterautoscaler.Config{GlobalOptions: globalOptions}, - ebsConfig: awsebs.NewConfig(globalOptions), - awsccmConfig: awsccm.NewConfig(globalOptions), - nutanixCSIConfig: nutanixcsi.NewConfig(globalOptions), - nutanixCCMConfig: &nutanixccm.Config{GlobalOptions: globalOptions}, - metalLBConfig: &metallb.Config{GlobalOptions: globalOptions}, - localPathCSIConfig: localpath.NewConfig(globalOptions), - snapshotControllerConfig: snapshotcontroller.NewConfig(globalOptions), - cosiControllerConfig: cosi.NewControllerConfig(globalOptions), - distributionConfig: &cncfdistribution.Config{GlobalOptions: globalOptions}, + ciliumCNIConfig: &cilium.CNIConfig{GlobalOptions: globalOptions}, + nfdConfig: nfd.NewConfig(globalOptions), + clusterAutoscalerConfig: &clusterautoscaler.Config{GlobalOptions: globalOptions}, + ebsConfig: awsebs.NewConfig(globalOptions), + awsccmConfig: awsccm.NewConfig(globalOptions), + awsLoadBalancerControllerConfig: awsloadbalancercontroller.NewControllerConfig(globalOptions), + nutanixCSIConfig: nutanixcsi.NewConfig(globalOptions), + nutanixCCMConfig: &nutanixccm.Config{GlobalOptions: globalOptions}, + metalLBConfig: &metallb.Config{GlobalOptions: globalOptions}, + localPathCSIConfig: localpath.NewConfig(globalOptions), + snapshotControllerConfig: snapshotcontroller.NewConfig(globalOptions), + cosiControllerConfig: cosi.NewControllerConfig(globalOptions), + distributionConfig: &cncfdistribution.Config{GlobalOptions: globalOptions}, } } @@ -127,6 +130,7 @@ func (h *Handlers) AllHandlers(mgr manager.Manager) []handlers.Named { csi.New(mgr.GetClient(), csiHandlers), snapshotcontroller.New(mgr.GetClient(), h.snapshotControllerConfig, helmChartInfoGetter), cosi.New(mgr.GetClient(), h.cosiControllerConfig, helmChartInfoGetter), + awsloadbalancercontroller.New(mgr.GetClient(), h.awsLoadBalancerControllerConfig, helmChartInfoGetter), servicelbgc.New(mgr.GetClient()), registry.New(mgr.GetClient(), registryHandlers), // The order of the handlers in the list is important and are called consecutively. From 0976521468476132ba7254942c27a187e453d8a9 Mon Sep 17 00:00:00 2001 From: Dimitri Koshkin Date: Mon, 6 Oct 2025 12:03:28 -0700 Subject: [PATCH 3/3] docs: add AWS Load Balancer controller docs --- .../addons/aws-load-balancer-controller.md | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/content/addons/aws-load-balancer-controller.md diff --git a/docs/content/addons/aws-load-balancer-controller.md b/docs/content/addons/aws-load-balancer-controller.md new file mode 100644 index 000000000..5a30e7131 --- /dev/null +++ b/docs/content/addons/aws-load-balancer-controller.md @@ -0,0 +1,89 @@ ++++ +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: +spec: + topology: + variables: + - name: clusterConfig + value: + addons: + # TODO: Define an API +``` + +## 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 isntance-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/