Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions cmd/cloud-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var (
func main() {
ccmOptions, err := options.NewCloudControllerManagerOptions()
if err != nil {
klog.Fatalf("unable to initialize command options: %v", err)
klog.Fatalf("Unable to initialize command options: %v", err)
}

fmt.Println("starting Controller")
Expand Down Expand Up @@ -91,7 +91,7 @@ func cloudInitializer(ctx context.Context) func(config *cloudcontrollerconfig.Co

if !cloud.HasClusterID() {
if config.ComponentConfig.KubeCloudShared.AllowUntaggedCloud {
klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues")
klog.Warning("Detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues")
} else {
klog.Fatalf(
"no ClusterID found. A ClusterID is required for the cloud provider to function properly. " +
Expand Down
2 changes: 1 addition & 1 deletion deploy/csi-plugin/controllerplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ spec:
- name: CSI_ENDPOINT
value: unix://csi/csi.sock
- name: CLOUD_CONFIG
value: /etc/config/cloud.conf
value: /etc/config/cloud.yaml
- name: CLUSTER_NAME
value: kubernetes
- name: STACKIT_SERVICE_ACCOUNT_KEY_PATH
Expand Down
2 changes: 1 addition & 1 deletion deploy/csi-plugin/nodeplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ spec:
- name: CSI_ENDPOINT
value: unix://csi/csi.sock
- name: CLOUD_CONFIG
value: /etc/config/cloud.conf
value: /etc/config/cloud.yaml
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 9808
Expand Down
97 changes: 97 additions & 0 deletions docs/migration/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Migration Guide: CCM and CSI Configuration to Unified YAML Format

## Introduction

This guide provides step-by-step instructions for migrating from the legacy Cloud Controller Manager (CCM) and Container Storage Interface (CSI) configurations to the new unified YAML-based configuration format.

## Overview

The migration involves:

- Updating CCM and CSI configurations to use the new unified YAML format
- Mapping legacy configuration keys to new schema
- Ensuring compatibility with the latest version of the STACKIT Kubernetes integration

**Note**: While the new format uses a unified structure, CCM and CSI configurations remain in separate files but follow the same YAML schema.

## Removed Configuration Options

The following configuration options have been removed in the new format:

### CCM

- `nonStackitClassNames` - No longer supported

### CSI

- `node-volume-attach-limit` - No longer configurable

## Old Configuration Reference

### CCM Configuration

```yaml
# cloudprovider.yaml
projectId: my-stackit-project-id
networkId: my-stackit-network-id
region: eu01
nonStackitClassNames: my-non-stackit-class
extraLabels:
key1: value1
key2: value2
metadata:
searchOrder: "configDrive,metadataService"
requestTimeout: "5s"
loadBalancerApi:
url: https://loadbalancer.example.com
```
### CSI Configuration
```ini
# cloudprovider.conf
[Global]
project-id = "my-stackit-project-id"
iaas-api-url = "https://iaas.example.com"
[Metadata]
search-order = "configDrive,metadataService"
request-timeout = "5s"
[BlockStorage]
node-volume-attach-limit = 20
rescan-on-resize = true
```

## New Configuration Reference

### CCM Configuration

```yaml
# cloudprovider.yaml
global:
projectId: my-stackit-project-id
region: eu01
metadata:
searchOrder: "configDrive,metadataService"
requestTimeout: "5s"
loadBalancer:
api:
url: https://loadbalancer.example.com
networkId: my-stackit-network-id
extraLabels:
key1: value1
key2: value2
```
### CSI Configuration
```yaml
# cloudprovider.conf
global:
projectId: my-stackit-project-id
iaasApi: https://iaas.example.com
metadata:
searchOrder: "configDrive,metadataService"
requestTimeout: "5s"
blockStorage:
rescanOnResize: true
```
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.3.0
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.6.2
go.uber.org/mock v0.6.0
go.yaml.in/yaml/v2 v2.4.3
golang.org/x/sync v0.19.0
golang.org/x/sys v0.39.0
google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.11
gopkg.in/gcfg.v1 v1.2.3
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.34.3
k8s.io/apimachinery v0.34.3
Expand Down Expand Up @@ -114,7 +114,6 @@ require (
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
Expand All @@ -130,7 +129,6 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiserver v0.34.2 // indirect
k8s.io/component-helpers v0.34.2 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,10 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
4 changes: 2 additions & 2 deletions pkg/ccm/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func NewInstance(client stackit.NodeClient, projectID, region string) (*Instance
func (i *Instances) InstanceExists(ctx context.Context, node *corev1.Node) (bool, error) {
_, err := i.getInstance(ctx, node)
if errors.Is(err, cloudprovider.InstanceNotFound) {
klog.V(6).Infof("instance not found for node: %s", node.Name)
klog.V(6).Infof("Instance not found for node: %s", node.Name)
return false, nil
}
if err != nil {
Expand Down Expand Up @@ -94,7 +94,7 @@ func (i *Instances) InstanceShutdown(ctx context.Context, node *corev1.Node) (bo
func (i *Instances) InstanceMetadata(ctx context.Context, node *corev1.Node) (*cloudprovider.InstanceMetadata, error) {
server, err := i.getInstance(ctx, node)
if errors.Is(err, cloudprovider.InstanceNotFound) {
klog.V(6).Infof("instance not found for node: %s", node.Name)
klog.V(6).Infof("Instance not found for node: %s", node.Name)
return nil, nil
}
if err != nil {
Expand Down
30 changes: 17 additions & 13 deletions pkg/ccm/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,29 @@ type MetricsRemoteWrite struct {

// LoadBalancer is used for creating and maintaining load balancers.
type LoadBalancer struct {
client stackit.LoadbalancerClient
recorder record.EventRecorder // set in CloudControllerManager.Initialize
projectID string
networkID string
extraLabels map[string]string
client stackit.LoadbalancerClient
recorder record.EventRecorder // set in CloudControllerManager.Initialize
projectID string
opts LoadBalancerOpts
// metricsRemoteWrite setting this enables remote writing of metrics and nil means it is disabled
metricsRemoteWrite *MetricsRemoteWrite
}

type LoadBalancerOpts struct {
API string `yaml:"api"`
NetworkID string `yaml:"networkId"`
ExtraLabels map[string]string `yaml:"extraLabels"`
}

var _ cloudprovider.LoadBalancer = (*LoadBalancer)(nil)

func NewLoadBalancer(client stackit.LoadbalancerClient, projectID, networkID string, extraLabels map[string]string, metricsRemoteWrite *MetricsRemoteWrite) (*LoadBalancer, error) { //nolint:lll // looks weird when shortened
func NewLoadBalancer(client stackit.LoadbalancerClient, projectID string, opts LoadBalancerOpts, metricsRemoteWrite *MetricsRemoteWrite) (*LoadBalancer, error) { //nolint:lll // looks weird when shortened
// LoadBalancer.recorder is set in CloudControllerManager.Initialize
return &LoadBalancer{
client: client,
projectID: projectID,
networkID: networkID,
opts: opts,
metricsRemoteWrite: metricsRemoteWrite,
extraLabels: extraLabels,
}, nil
}

Expand Down Expand Up @@ -126,7 +130,7 @@ func (l *LoadBalancer) EnsureLoadBalancer( //nolint:gocyclo // not really comple
return nil, fmt.Errorf("reconcile metricsRemoteWrite: %w", err)
}

spec, events, err := lbSpecFromService(service, nodes, l.networkID, l.extraLabels, observabilityOptions)
spec, events, err := lbSpecFromService(service, nodes, l.opts, observabilityOptions)
if err != nil {
return nil, fmt.Errorf("invalid load balancer specification: %w", err)
}
Expand Down Expand Up @@ -206,12 +210,12 @@ func (l *LoadBalancer) createLoadBalancer(ctx context.Context, clusterName strin
return nil, fmt.Errorf("reconcile metricsRemoteWrite: %w", err)
}

spec, events, err := lbSpecFromService(service, nodes, l.networkID, l.extraLabels, metricsRemoteWrite)
spec, events, err := lbSpecFromService(service, nodes, l.opts, metricsRemoteWrite)
if err != nil {
return nil, fmt.Errorf("invalid load balancer specification: %w", err)
}
if l.extraLabels != nil {
spec.Labels = ptr.To(l.extraLabels)
if l.opts.ExtraLabels != nil {
spec.Labels = ptr.To(l.opts.ExtraLabels)
}
for _, event := range events {
l.recorder.Event(service, event.Type, event.Reason, event.Message)
Expand All @@ -238,7 +242,7 @@ func (l *LoadBalancer) createLoadBalancer(ctx context.Context, clusterName strin
// It is not called on controller start-up. EnsureLoadBalancer must also ensure to update targets.
func (l *LoadBalancer) UpdateLoadBalancer(ctx context.Context, clusterName string, service *corev1.Service, nodes []*corev1.Node) error {
// only TargetPools are used from spec
spec, events, err := lbSpecFromService(service, nodes, l.networkID, l.extraLabels, nil)
spec, events, err := lbSpecFromService(service, nodes, l.opts, nil)
if err != nil {
return fmt.Errorf("invalid service: %w", err)
}
Expand Down
13 changes: 6 additions & 7 deletions pkg/ccm/loadbalancer_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,15 @@ func getPlanID(service *corev1.Service) (planID *string, msgs []string, err erro
func lbSpecFromService( //nolint:funlen,gocyclo // It is long but not complex.
service *corev1.Service,
nodes []*corev1.Node,
networkID string,
extraLabels map[string]string,
opts LoadBalancerOpts,
observability *loadbalancer.LoadbalancerOptionObservability,
) (*loadbalancer.CreateLoadBalancerPayload, []Event, error) {
lb := &loadbalancer.CreateLoadBalancerPayload{
Options: &loadbalancer.LoadBalancerOptions{},
Networks: &[]loadbalancer.Network{
{
Role: utils.Ptr(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS),
NetworkId: &networkID,
NetworkId: &opts.NetworkID,
},
},
}
Expand All @@ -262,7 +261,7 @@ func lbSpecFromService( //nolint:funlen,gocyclo // It is long but not complex.
lb.Networks = &[]loadbalancer.Network{
{
Role: utils.Ptr(loadbalancer.NETWORKROLE_TARGETS),
NetworkId: &networkID,
NetworkId: &opts.NetworkID,
}, {
Role: utils.Ptr(loadbalancer.NETWORKROLE_LISTENERS),
NetworkId: &listenerNetwork,
Expand All @@ -272,14 +271,14 @@ func lbSpecFromService( //nolint:funlen,gocyclo // It is long but not complex.
lb.Networks = &[]loadbalancer.Network{
{
Role: utils.Ptr(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS),
NetworkId: &networkID,
NetworkId: &opts.NetworkID,
},
}
}

// Add extraLabels if set
if extraLabels != nil {
lb.Labels = ptr.To(extraLabels)
if opts.ExtraLabels != nil {
lb.Labels = ptr.To(opts.ExtraLabels)
}

// Add metric metricsRemoteWrite settings
Expand Down
Loading