From a1474ded5b219adae56fb680b46a0c14945dfe45 Mon Sep 17 00:00:00 2001 From: Chris Werner Rau Date: Fri, 23 Jan 2026 14:34:50 +0100 Subject: [PATCH 1/2] feat(openstack-cloud-controller-manager): add splitMode This allows the user to deploy the controller-manager split between the management cluster and the workload cluster. Signed-off-by: Chris Werner Rau --- .../Chart.lock | 6 ++ .../templates/clusterrole.yaml | 2 + .../templates/clusterrolebinding-sm.yaml | 2 +- .../templates/clusterrolebinding.yaml | 7 ++ .../{daemonset.yaml => controller.yaml} | 68 ++++++++++++++++++- .../templates/role.yaml | 2 +- .../templates/rolebinding.yaml | 2 +- .../templates/service-sm.yaml | 2 +- .../templates/serviceaccount.yaml | 2 + .../templates/servicemonitor.yaml | 2 +- .../values.yaml | 30 ++++++++ .../servicemonitor_test.yaml | 14 ++-- 12 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 charts/openstack-cloud-controller-manager/Chart.lock rename charts/openstack-cloud-controller-manager/templates/{daemonset.yaml => controller.yaml} (68%) diff --git a/charts/openstack-cloud-controller-manager/Chart.lock b/charts/openstack-cloud-controller-manager/Chart.lock new file mode 100644 index 0000000000..9085110c1a --- /dev/null +++ b/charts/openstack-cloud-controller-manager/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + version: 2.14.1 +digest: sha256:ac04d66e6abb3cfc89f4c10e49d79770c352c510744bc51e3595937721b7f41a +generated: "2024-01-10T10:12:58.796725699+01:00" diff --git a/charts/openstack-cloud-controller-manager/templates/clusterrole.yaml b/charts/openstack-cloud-controller-manager/templates/clusterrole.yaml index 7257630653..9fe5dc2843 100644 --- a/charts/openstack-cloud-controller-manager/templates/clusterrole.yaml +++ b/charts/openstack-cloud-controller-manager/templates/clusterrole.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.splitMode.enabled) (eq .Values.splitMode.type "workload") }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -87,3 +88,4 @@ rules: - get - list - watch +{{- end }} diff --git a/charts/openstack-cloud-controller-manager/templates/clusterrolebinding-sm.yaml b/charts/openstack-cloud-controller-manager/templates/clusterrolebinding-sm.yaml index 9c89bcb65f..7b6bcf13f6 100644 --- a/charts/openstack-cloud-controller-manager/templates/clusterrolebinding-sm.yaml +++ b/charts/openstack-cloud-controller-manager/templates/clusterrolebinding-sm.yaml @@ -1,4 +1,4 @@ -{{- if .Values.serviceMonitor.enabled }} +{{- if and .Values.serviceMonitor.enabled (or (not .Values.splitMode.enabled) (eq .Values.splitMode.type "management")) }} kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: diff --git a/charts/openstack-cloud-controller-manager/templates/clusterrolebinding.yaml b/charts/openstack-cloud-controller-manager/templates/clusterrolebinding.yaml index e484354f0f..36ac7d8c60 100644 --- a/charts/openstack-cloud-controller-manager/templates/clusterrolebinding.yaml +++ b/charts/openstack-cloud-controller-manager/templates/clusterrolebinding.yaml @@ -1,3 +1,4 @@ +{{- if or (not .Values.splitMode.enabled) (eq .Values.splitMode.type "workload") }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -13,6 +14,12 @@ roleRef: kind: ClusterRole name: {{ .Values.clusterRoleName }} subjects: +{{- if and .Values.splitMode.enabled (eq .Values.splitMode.type "workload") }} +- kind: User + name: {{ .Values.splitMode.subject.name }} +{{- else }} - kind: ServiceAccount name: {{ .Values.serviceAccountName }} namespace: {{ .Release.Namespace | quote }} +{{- end }} +{{- end }} diff --git a/charts/openstack-cloud-controller-manager/templates/daemonset.yaml b/charts/openstack-cloud-controller-manager/templates/controller.yaml similarity index 68% rename from charts/openstack-cloud-controller-manager/templates/daemonset.yaml rename to charts/openstack-cloud-controller-manager/templates/controller.yaml index ae5da1059a..4517810706 100644 --- a/charts/openstack-cloud-controller-manager/templates/daemonset.yaml +++ b/charts/openstack-cloud-controller-manager/templates/controller.yaml @@ -1,5 +1,10 @@ +{{- if or (not .Values.splitMode.enabled) (eq .Values.splitMode.type "management") }} apiVersion: apps/v1 +{{- if .Values.splitMode.enabled }} +kind: Deployment +{{- else }} kind: DaemonSet +{{- end }} metadata: name: {{ include "occm.name" . }} labels: {{- include "occm.labels.standard" . | nindent 4 }} @@ -9,11 +14,19 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: + {{- if .Values.splitMode.enabled }} + replicas: {{ .Values.splitMode.replicas }} + {{- end }} selector: matchLabels: {{- include "occm.controllermanager.matchLabels" . | nindent 6 }} + {{- if .Values.splitMode.enabled }} + strategy: + type: RollingUpdate + {{- else }} updateStrategy: type: RollingUpdate + {{- end }} template: metadata: annotations: @@ -26,10 +39,17 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- if .Values.splitMode.enabled }} + {{- with .Values.splitMode.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- else }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} + {{- end }} {{- with .Values.podSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -42,7 +62,11 @@ spec: hostAliases: {{- toYaml . | nindent 8 }} {{- end }} + {{- if .Values.splitMode.enabled }} + automountServiceAccountToken: false + {{- else }} serviceAccountName: {{ .Values.serviceAccountName }} + {{- end }} containers: - name: openstack-cloud-controller-manager image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}" @@ -56,6 +80,10 @@ spec: - --cloud-config=$(CLOUD_CONFIG) - --cluster-name=$(CLUSTER_NAME) - --cloud-provider=openstack + {{- if .Values.splitMode.enabled }} + - --kubeconfig=/etc/kubernetes/kubeconfig + - --leader-elect=true + {{- end }} - --use-service-account-credentials=false - --controllers={{- trimAll "," (include "occm.enabledControllers" . ) -}} {{- if .Values.serviceMonitor.enabled }} @@ -72,10 +100,26 @@ spec: {{- if .Values.serviceMonitor.enabled }} ports: - containerPort: 10258 + {{- if not .Values.splitMode.enabled }} hostPort: 10258 + {{- end }} name: http protocol: TCP {{- end }} + {{- if .Values.splitMode.enabled }} + volumeMounts: + {{- if .Values.splitMode.extraVolumeMounts }} + {{- toYaml .Values.splitMode.extraVolumeMounts | nindent 12 }} + {{- end }} + - mountPath: /etc/kubernetes + name: kubeconfig-volume + readOnly: true + {{- if .Values.secret.enabled }} + - mountPath: /etc/config + name: cloud-config-volume + readOnly: true + {{- end }} + {{- else }} {{- if or (.Values.extraVolumeMounts) (.Values.secret.enabled) }} volumeMounts: {{- end }} @@ -87,6 +131,7 @@ spec: {{- if .Values.extraVolumeMounts }} {{- toYaml .Values.extraVolumeMounts | nindent 12 }} {{- end }} + {{- end }} {{- if .Values.livenessProbe }} livenessProbe: {{- toYaml .Values.livenessProbe | nindent 12 }} @@ -110,12 +155,31 @@ spec: {{- if .Values.extraInitContainers }} initContainers: {{ toYaml .Values.extraInitContainers | nindent 6 }} {{- end }} - hostNetwork: {{ .Values.hostNetwork }} dnsPolicy: {{ .Values.dnsPolicy }} + {{- if not .Values.splitMode.enabled }} + hostNetwork: {{ .Values.hostNetwork }} + {{- end }} {{- if .Values.priorityClassName }} priorityClassName: {{ .Values.priorityClassName }} {{- end }} + {{- if .Values.splitMode.enabled }} + volumes: + {{- if .Values.splitMode.extraVolumes }} + {{- toYaml .Values.splitMode.extraVolumes | nindent 6 }} + {{- end }} + - name: kubeconfig-volume + secret: + secretName: {{ .Values.splitMode.kubeconfig.secretName }} + items: + - key: {{ .Values.splitMode.kubeconfig.secretKey }} + path: kubeconfig + {{- if .Values.secret.enabled }} + - name: cloud-config-volume + secret: + secretName: {{ .Values.secret.name }} + {{- end }} + {{- else }} {{- if or (.Values.extraVolumes) (.Values.secret.enabled) }} volumes: {{- end }} @@ -127,3 +191,5 @@ spec: {{- if .Values.extraVolumes }} {{ toYaml .Values.extraVolumes | nindent 6 }} {{- end }} + {{- end }} +{{- end }} diff --git a/charts/openstack-cloud-controller-manager/templates/role.yaml b/charts/openstack-cloud-controller-manager/templates/role.yaml index cc8085ade1..934da5bb3d 100644 --- a/charts/openstack-cloud-controller-manager/templates/role.yaml +++ b/charts/openstack-cloud-controller-manager/templates/role.yaml @@ -1,4 +1,4 @@ -{{- if .Values.secret.enabled }} +{{- if and .Values.secret.enabled (not .Values.splitMode.enabled) }} apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: diff --git a/charts/openstack-cloud-controller-manager/templates/rolebinding.yaml b/charts/openstack-cloud-controller-manager/templates/rolebinding.yaml index 9ef27a6c73..d6021c8088 100644 --- a/charts/openstack-cloud-controller-manager/templates/rolebinding.yaml +++ b/charts/openstack-cloud-controller-manager/templates/rolebinding.yaml @@ -1,4 +1,4 @@ -{{- if .Values.secret.enabled }} +{{- if and .Values.secret.enabled (not .Values.splitMode.enabled) }} apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: diff --git a/charts/openstack-cloud-controller-manager/templates/service-sm.yaml b/charts/openstack-cloud-controller-manager/templates/service-sm.yaml index 5ae23dd4a4..b8f68843af 100644 --- a/charts/openstack-cloud-controller-manager/templates/service-sm.yaml +++ b/charts/openstack-cloud-controller-manager/templates/service-sm.yaml @@ -1,4 +1,4 @@ -{{- if .Values.serviceMonitor.enabled }} +{{- if and .Values.serviceMonitor.enabled (or (not .Values.splitMode.enabled) (eq .Values.splitMode.type "management")) }} apiVersion: v1 kind: Service metadata: diff --git a/charts/openstack-cloud-controller-manager/templates/serviceaccount.yaml b/charts/openstack-cloud-controller-manager/templates/serviceaccount.yaml index 73bc388255..3e975a8db0 100644 --- a/charts/openstack-cloud-controller-manager/templates/serviceaccount.yaml +++ b/charts/openstack-cloud-controller-manager/templates/serviceaccount.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.splitMode.enabled }} apiVersion: v1 kind: ServiceAccount metadata: @@ -8,3 +9,4 @@ metadata: {{- with .Values.commonAnnotations }} {{- toYaml . | nindent 4 }} {{- end }} +{{- end }} diff --git a/charts/openstack-cloud-controller-manager/templates/servicemonitor.yaml b/charts/openstack-cloud-controller-manager/templates/servicemonitor.yaml index 8b81d017ac..bc8b17c213 100644 --- a/charts/openstack-cloud-controller-manager/templates/servicemonitor.yaml +++ b/charts/openstack-cloud-controller-manager/templates/servicemonitor.yaml @@ -1,4 +1,4 @@ -{{- if .Values.serviceMonitor.enabled }} +{{- if and .Values.serviceMonitor.enabled (or (not .Values.splitMode.enabled) (eq .Values.splitMode.type "management")) }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: diff --git a/charts/openstack-cloud-controller-manager/values.yaml b/charts/openstack-cloud-controller-manager/values.yaml index 39503d8d5e..8a75662cad 100644 --- a/charts/openstack-cloud-controller-manager/values.yaml +++ b/charts/openstack-cloud-controller-manager/values.yaml @@ -174,3 +174,33 @@ cluster: clusterRoleName: system:cloud-controller-manager serviceAccountName: cloud-controller-manager + +# External mode configuration +# Enables split deployment across management and workload clusters +splitMode: + # Enable external mode + enabled: false + # Which part to deploy: "management" or "workload" + # - management: Deploys the Deployment (controller) with kubeconfig + # - workload: Deploys only RBAC resources with configurable subject + type: management + + # Management cluster settings (when type=management) + kubeconfig: + # Name of the pre-existing secret containing kubeconfig + secretName: "" + # Key in the secret containing the kubeconfig data + secretKey: value + # Number of replicas for the Deployment + replicas: 1 + # Node selector for external mode Deployment + nodeSelector: {} + # Extra volumes for external mode + extraVolumes: [] + # Extra volume mounts for external mode + extraVolumeMounts: [] + + # Workload cluster settings (when type=workload) + # Subject for the ClusterRoleBinding + subject: + name: openstack-cloud-controller-manager diff --git a/tests/helm/openstack-cloud-controller-manager/servicemonitor_test.yaml b/tests/helm/openstack-cloud-controller-manager/servicemonitor_test.yaml index 4f9b044d16..0e92bab644 100644 --- a/tests/helm/openstack-cloud-controller-manager/servicemonitor_test.yaml +++ b/tests/helm/openstack-cloud-controller-manager/servicemonitor_test.yaml @@ -1,7 +1,7 @@ suite: OCCM ServiceMonitor templates: - templates/clusterrolebinding-sm.yaml - - templates/daemonset.yaml + - templates/controller.yaml - templates/service-sm.yaml - templates/servicemonitor.yaml @@ -28,11 +28,11 @@ tests: - contains: path: spec.template.spec.containers[0].args content: --bind-address=127.0.0.1 - template: templates/daemonset.yaml + template: templates/controller.yaml - notContains: path: spec.template.spec.containers[0].args content: --authorization-always-allow-paths=/metrics - template: templates/daemonset.yaml + template: templates/controller.yaml - it: wires the ServiceMonitor to the OCCM metrics endpoint set: @@ -87,19 +87,19 @@ tests: app: openstack-cloud-controller-manager component: controllermanager release: test-release - template: templates/daemonset.yaml + template: templates/controller.yaml - contains: path: spec.template.spec.containers[0].args content: --authorization-always-allow-paths=/metrics - template: templates/daemonset.yaml + template: templates/controller.yaml - contains: path: spec.template.spec.containers[0].args content: --bind-address=0.0.0.0 - template: templates/daemonset.yaml + template: templates/controller.yaml - contains: path: spec.template.spec.containers[0].ports content: containerPort: 10258 name: http any: true - template: templates/daemonset.yaml + template: templates/controller.yaml From 949a99a913d2d35b5a924fdc90ac9297ae1cf4f3 Mon Sep 17 00:00:00 2001 From: Chris Werner Rau Date: Wed, 22 Jul 2026 10:50:49 +0200 Subject: [PATCH 2/2] chore: adjust gitignore Signed-off-by: Chris Werner Rau --- .gitignore | 5 +++++ charts/openstack-cloud-controller-manager/Chart.lock | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 charts/openstack-cloud-controller-manager/Chart.lock diff --git a/.gitignore b/.gitignore index 7611fa3410..2280cbadab 100644 --- a/.gitignore +++ b/.gitignore @@ -162,3 +162,8 @@ zz_generated.openapi.go # Openstack credential file clouds.yaml + +# helm files + +*.lock +*.zip diff --git a/charts/openstack-cloud-controller-manager/Chart.lock b/charts/openstack-cloud-controller-manager/Chart.lock deleted file mode 100644 index 9085110c1a..0000000000 --- a/charts/openstack-cloud-controller-manager/Chart.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: common - repository: https://charts.bitnami.com/bitnami - version: 2.14.1 -digest: sha256:ac04d66e6abb3cfc89f4c10e49d79770c352c510744bc51e3595937721b7f41a -generated: "2024-01-10T10:12:58.796725699+01:00"