Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
64b5f64
add application load balancer controller manager
Mar 17, 2026
d623425
chore: add alb ingress controller docs run-it-locally how-to
Mar 17, 2026
cbf5622
Fix errors in stackit package
fischerman Mar 17, 2026
d7971df
chore: add new Makefile build for alb ingress controller manager
Mar 17, 2026
05be587
Fix errors in ingress package (only non-test files)
fischerman Mar 17, 2026
9440cac
Add mocks for ALB and certificates API
fischerman Mar 17, 2026
cd270f1
Fix syntax errors in test in ingress package
fischerman Mar 17, 2026
cf3d7ac
wip: Add alb-controller-manager deploy files
jamand Mar 17, 2026
bb40d21
Fix main.go
fischerman Mar 17, 2026
c18c393
Add mock generation for ALB and certificates API
fischerman Mar 17, 2026
6bd4ba5
Fix linter issues
fischerman Mar 17, 2026
bd2bf6c
Added waf config to change detection
Mar 17, 2026
4302bb9
Update docs for ALBCM
fischerman Mar 18, 2026
76f737e
Fix ALB unit tests
fischerman Mar 18, 2026
5744c59
feat: read configuration from cloud config
Mar 18, 2026
a4c3eee
chore: add a short description for setIPAddresses function
Mar 18, 2026
76e1f49
Include envtest for controller tests
fischerman Mar 18, 2026
1b1f8da
Undo temporary changes
fischerman Mar 18, 2026
931b420
Fix linter issues
fischerman Mar 18, 2026
a19d91f
Remove license from code
fischerman Mar 18, 2026
261c701
chore: adjust issuer sample
Mar 20, 2026
8eeb62c
chore: clarify isCertValid
Mar 20, 2026
f7d1a76
chore: remove debug messages
Mar 20, 2026
1ff73e6
fix: certificates not created because loadCerts skips all ingress tls…
Mar 21, 2026
838e4c5
fix: certificate deletion logic
Mar 22, 2026
9d6f767
chore: adjsut externalIPAnnotation comment
Mar 22, 2026
98c71c0
Adopt config to config structure
dergeberl Mar 26, 2026
e823347
Move ReadConfig to config package
dergeberl Mar 26, 2026
c66f776
Remove unused webhook
dergeberl Mar 26, 2026
3ec8b81
Remove secure metrics
dergeberl Mar 26, 2026
f9fdf11
Enable LeaderElectionReleaseOnCancel
dergeberl Mar 26, 2026
d8cb339
Make linter happy
dergeberl Mar 26, 2026
693873a
Remove kubebuilder scaffold comments
dergeberl Mar 26, 2026
f4ec638
Remove crd import in envtest; remove getFirstFoundEnvTestBinaryDir as…
dergeberl Mar 26, 2026
85e6a10
Remove dummy comment
dergeberl Mar 26, 2026
87dc2c6
Refactor SetupWithManager
dergeberl Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
BUILD_IMAGES ?= stackit-csi-plugin cloud-controller-manager
BUILD_IMAGES ?= stackit-csi-plugin cloud-controller-manager application-load-balancer-controller-manager
SOURCES := Makefile go.mod go.sum $(shell find $(DEST) -name '*.go' 2>/dev/null)
VERSION ?= $(shell git describe --dirty --tags --match='v*' 2>/dev/null || git rev-parse --short HEAD)
REGISTRY ?= ghcr.io
Expand Down Expand Up @@ -60,7 +60,7 @@ modules: ## Runs go mod to ensure modules are up to date.
go mod tidy

.PHONY: test
test: ## Run tests.
test: $(ENVTEST) ## Run tests.
./hack/test.sh ./cmd/... ./pkg/...

.PHONY: test-cover
Expand Down Expand Up @@ -141,6 +141,9 @@ mocks: $(MOCKGEN)
@$(MOCKGEN) -destination ./pkg/stackit/server_mock.go -package stackit ./pkg/stackit NodeClient
@$(MOCKGEN) -destination ./pkg/stackit/metadata/metadata_mock.go -package metadata ./pkg/stackit/metadata IMetadata
@$(MOCKGEN) -destination ./pkg/csi/util/mount/mount_mock.go -package mount ./pkg/csi/util/mount IMount
@$(MOCKGEN) -destination ./pkg/stackit/applicationloadbalancercertificates_mock.go -package stackit ./pkg/stackit CertificatesClient
@$(MOCKGEN) -destination ./pkg/stackit/applicationloadbalancer_mock.go -package stackit ./pkg/stackit ApplicationLoadBalancerClient


.PHONY: generate
generate: mocks
Expand Down
140 changes: 140 additions & 0 deletions cmd/application-load-balancer-controller-manager/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package main

import (
"flag"
"os"

"github.com/stackitcloud/cloud-provider-stackit/pkg/alb/ingress"
albclient "github.com/stackitcloud/cloud-provider-stackit/pkg/stackit"
stackitconfig "github.com/stackitcloud/cloud-provider-stackit/pkg/stackit/config"
sdkconfig "github.com/stackitcloud/stackit-sdk-go/core/config"
albsdk "github.com/stackitcloud/stackit-sdk-go/services/alb/v2api"
certsdk "github.com/stackitcloud/stackit-sdk-go/services/certificates/v2api"

"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
)

var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
}

// nolint:funlen // TODO: Refactor into smaller functions.
func main() {
var metricsAddr string
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move into a options struct

var enableLeaderElection bool
var leaderElectionNamespace string
var leaderElectionID string
var probeAddr string
var cloudConfig string
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.StringVar(&leaderElectionNamespace, "leader-election-namespace", "default", "The namespace in which the leader "+
"election resource will be created.")
flag.StringVar(&leaderElectionID, "leader-election-id", "d0fbe9c4.stackit.cloud", "The name of the resource that "+
"leader election will use for holding the leader lock.")
flag.StringVar(&cloudConfig, "cloud-config", "cloud.yaml", "The path to the cloud config file.")
opts := zap.Options{
Development: true,
}
opts.BindFlags(flag.CommandLine)
flag.Parse()

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

config, err := stackitconfig.ReadALBConfigFromFile(cloudConfig)
if err != nil {
setupLog.Error(err, "Failed to read cloud config")
os.Exit(1)
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsserver.Options{
BindAddress: metricsAddr,
},
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: leaderElectionID,
LeaderElectionNamespace: leaderElectionNamespace,
LeaderElectionReleaseOnCancel: true,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
albOpts := []sdkconfig.ConfigurationOption{}
if config.Global.APIEndpoints.ApplicationLoadBalancerAPI != "" {
albOpts = append(albOpts, sdkconfig.WithEndpoint(config.Global.APIEndpoints.ApplicationLoadBalancerAPI))
}

certOpts := []sdkconfig.ConfigurationOption{}
if config.Global.APIEndpoints.ApplicationLoadBalancerCertificateAPI != "" {
certOpts = append(certOpts, sdkconfig.WithEndpoint(config.Global.APIEndpoints.ApplicationLoadBalancerCertificateAPI))
}

// Setup ALB API client
sdkClient, err := albsdk.NewAPIClient(albOpts...)
if err != nil {
setupLog.Error(err, "unable to create ALB SDK client", "controller", "IngressClass")
os.Exit(1)
}
albClient, err := albclient.NewApplicationLoadBalancerClient(sdkClient)
if err != nil {
setupLog.Error(err, "unable to create ALB client", "controller", "IngressClass")
os.Exit(1)
}

// Setup Certificates API client
certificateAPI, err := certsdk.NewAPIClient(certOpts...)
if err != nil {
setupLog.Error(err, "unable to create certificate SDK client", "controller", "IngressClass")
os.Exit(1)
}
certificateClient, err := albclient.NewCertClient(certificateAPI)
if err != nil {
setupLog.Error(err, "unable to create Certificates client", "controller", "IngressClass")
os.Exit(1)
}

if err = (&ingress.IngressClassReconciler{
Client: mgr.GetClient(),
ALBClient: albClient,
CertificateClient: certificateClient,
Scheme: mgr.GetScheme(),
ALBConfig: config,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "IngressClass")
os.Exit(1)
}

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up ready check")
os.Exit(1)
}

setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: kube-system
name: stackit-application-load-balancer-contoller-manager
labels:
app: stackit-application-load-balancer-contoller-manager
spec:
replicas: 2
strategy:
type: RollingUpdate
selector:
matchLabels:
app: stackit-application-load-balancer-contoller-manager
template:
metadata:
labels:
app: stackit-application-load-balancer-contoller-manager
spec:
serviceAccountName: stackit-application-load-balancer-contoller-manager
terminationGracePeriodSeconds: 30
containers:
- name: stackit-application-load-balancer-contoller-manager
# TODO(jamand): Adapt image tag
image: ghcr.io/stackitcloud/cloud-provider-stackit/stackit-application-load-balancer-contoller-manager:XXX
args:
- "--authorization-always-allow-paths=/metrics"
- "--leader-elect=true"
- "--leader-elect-resource-name=stackit-application-load-balancer-contoller-manager"
- "--enable-http2"
- "--metrics-bind-address=8080"
- "--secureMetrics=false"
# TODO(jamand): Check webhook cert + enableHTTP2 flag
env:
- name: STACKIT_SERVICE_ACCOUNT_KEY_PATH
value: /etc/serviceaccount/sa_key.json
ports:
- containerPort: 8080
hostPort: 8080
name: metrics
protocol: TCP
- containerPort: 8081
hostPort: 8081
name: probe
protocol: TCP
resources:
limits:
cpu: "0.5"
memory: 500Mi
requests:
cpu: "0.1"
memory: 100Mi
volumeMounts:
- mountPath: /etc/serviceaccount
name: cloud-secret
volumes:
- name: cloud-secret
secret:
secretName: stackit-cloud-secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yaml
- rbac.yaml

60 changes: 60 additions & 0 deletions deploy/application-load-balancer-controller-manager/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: stackit-application-load-balancer-contoller-manager
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: stackit-application-load-balancer-contoller-manager
rules:
# TODO(jamand): Go through rules again
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- apiGroups:
- "networking.k8s.io"
resources:
- ingress
verbs:
- get
- apiGroups:
- "networking.k8s.io"
resources:
- ingress/status
verbs:
- patch
- apiGroups:
- "networking.k8s.io"
resources:
- ingressclass
verbs:
- list
- patch
- update
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: stackit-application-load-balancer-contoller-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: stackit-application-load-balancer-contoller-manager
subjects:
- kind: ServiceAccount
name: stackit-application-load-balancer-contoller-manager
namespace: kube-system
20 changes: 20 additions & 0 deletions deploy/application-load-balancer-controller-manager/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: stackit-application-load-balancer-contoller-manager
namespace: kube-system
name: stackit-application-load-balancer-contoller-manager
spec:
selector:
app: stackit-application-load-balancer-contoller-manager
ports:
- name: probe
port: 8081
targetPort: probe
protocol: TCP
- name: metrics
port: 8080
targetPort: metrics
protocol: TCP
type: ClusterIP
Loading