Fix duplicate port names in controller-manager containers (#751)

* Fix duplicate port names in controller-manager containers

Multiple controller-manager containers were using the same "heathz" port
name, causing Kubernetes warnings about duplicate ports in the
StatefulSet. This also affected the prometheus port "prom-cm".

Changes:
* Renamed healthz port to hp-cm (health port - controller manager)
* Renamed prom-cm to pm-cm for consistency
* Addedd {{ .portSuffix }} variable to differentiate external controller
  ports
* Implemented port suffix logic

The suffix logic handles cluster names by:
1. Names <9 chars: use full name as suffic
  * e.g.: child01 -> -child01
2. Names with trailing numbers: preserve the number format users chose
  * Detects 1-2 digit numbers with optional hyphen
  * Truncates base name to fit within 15 chars
  * e.g.: verlongcluster-01 -> -verylo-01
3. Names without numbers: use SHA-256 hash for uniqueness
  * Trunactes name to 5 chars and appends 3-char hash
  * e.g.: verlongclustername -> -veryl-a3f

The logic separates container suffix (full name) from port suffix
(truncated) so container names remain descriptive while port names stay
compliant.

Fixes #525 #655

Signed-off-by: Rowan Ruseler <[email protected]>

* Add optional port name overrides for ext. controller

The auto-generated port name suffixes for external controller manager
can collide when cluster names are similar, as the 3-character has
provides only 4,096 possibilities. With the optional healthPortName and
prometheusPortName fields to cluster configuration, allows users to
explicity set port names when automatica generation creates collisions.

Signed-off-by: Rowan Ruseler <[email protected]>

* Fix portSuffix generation

Changed from "and" to "or", so portSuffic is calculated when either
healthPortName or prometheusPortName is unset.

Signed-off-by: Rowan Ruseler <[email protected]>

---------

Signed-off-by: Rowan Ruseler <[email protected]>
Co-authored-by: kfox1111 <[email protected]>
This commit is contained in:
Rowan Ruseler
2026-02-23 15:20:25 +01:00
committed by GitHub
co-authored by kfox1111
parent 3daadc6456
commit b0aa3e4266
3 changed files with 56 additions and 8 deletions
+1 -1
View File
@@ -356,7 +356,7 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr
| `externalControllerManagers.defaults.configMap.annotations` | Annotations to add to the Controller Manager ConfigMap | `{}` | | `externalControllerManagers.defaults.configMap.annotations` | Annotations to add to the Controller Manager ConfigMap | `{}` |
| `externalControllerManagers.defaults.ignoreNamespaces` | These namespaces are ignored by controller manager | `[]` | | `externalControllerManagers.defaults.ignoreNamespaces` | These namespaces are ignored by controller manager | `[]` |
| `externalControllerManagers.defaults.cacheNamespaces` | If specified restricts the manager's cache to watch objects in the desired namespaces. Defaults to all namespaces. | `{}` | | `externalControllerManagers.defaults.cacheNamespaces` | If specified restricts the manager's cache to watch objects in the desired namespaces. Defaults to all namespaces. | `{}` |
| `externalControllerManagers.clusters` | A dictionary of clusters to add with optional overrides. If empty, all clusters defined in kubeConfigs will be used. | `{}` | | `externalControllerManagers.clusters` | A dictionary of clusters to add with optional overrides (kubeConfigName, reconcile, healthPortName, prometheusPortName). If empty, all clusters defined in kubeConfigs will be used. | `{}` |
| `tools.kubectl.image.registry` | The OCI registry to pull the image from | `registry.k8s.io` | | `tools.kubectl.image.registry` | The OCI registry to pull the image from | `registry.k8s.io` |
| `tools.kubectl.image.repository` | The repository within the registry | `kubectl` | | `tools.kubectl.image.repository` | The repository within the registry | `kubectl` |
| `tools.kubectl.image.pullPolicy` | The image pull policy | `IfNotPresent` | | `tools.kubectl.image.pullPolicy` | The image pull policy | `IfNotPresent` |
@@ -13,7 +13,7 @@
{{- if or .Values.controllerManager.reconcile.clusterSPIFFEIDs .Values.controllerManager.reconcile.clusterStaticEntries }} {{- if or .Values.controllerManager.reconcile.clusterSPIFFEIDs .Values.controllerManager.reconcile.clusterStaticEntries }}
{{- $reconcileEntries = add $reconcileEntries 1 }} {{- $reconcileEntries = add $reconcileEntries 1 }}
{{- end }} {{- end }}
{{- include "spire-controller-manager.container" (dict "Values" .Values "Chart" .Chart "startPort" $startPort "suffix" "" "settings" $settings "defaults" $defaults "webhooksEnabled" $webhooksEnabled) }} {{- include "spire-controller-manager.container" (dict "Values" .Values "Chart" .Chart "startPort" $startPort "suffix" "" "portSuffix" "" "healthPortName" "" "prometheusPortName" "" "settings" $settings "defaults" $defaults "webhooksEnabled" $webhooksEnabled) }}
{{- end }} {{- end }}
{{- if .Values.externalControllerManagers.enabled }} {{- if .Values.externalControllerManagers.enabled }}
{{- $clusters := default .Values.kubeConfigs .Values.externalControllerManagers.clusters }} {{- $clusters := default .Values.kubeConfigs .Values.externalControllerManagers.clusters }}
@@ -23,7 +23,43 @@
{{- if hasKey $root.Values.externalControllerManagers.clusters $name }} {{- if hasKey $root.Values.externalControllerManagers.clusters $name }}
{{- $clusterSettings = index $root.Values.externalControllerManagers.clusters $name }} {{- $clusterSettings = index $root.Values.externalControllerManagers.clusters $name }}
{{- end }} {{- end }}
{{/*
Generate port names for controller-manager ports.
Can be explicitly set via healthPortName and prometheusPortName in cluster configuration.
Otherwise uses default prefixes (hp-cm/pm-cm) with auto-generated suffixes.
Auto-generation preserves trailing numbers from cluster names or uses hash for uniqueness.
*/}}
{{- $suffix := printf "-%s" $name }} {{- $suffix := printf "-%s" $name }}
{{- $portSuffix := $suffix }}
{{- $healthPortName := "" }}
{{- $prometheusPortName := "" }}
{{- if hasKey $clusterSettings "healthPortName" }}
{{- $healthPortName = $clusterSettings.healthPortName }}
{{- end }}
{{- if hasKey $clusterSettings "prometheusPortName" }}
{{- $prometheusPortName = $clusterSettings.prometheusPortName }}
{{- end }}
{{- if or (eq $healthPortName "") (eq $prometheusPortName "") }}
{{- if gt (len $name) 9 }}
{{- $numberMatch := regexFind "[-]?[0-9]{1,2}$" $name }}
{{- if $numberMatch }}
{{- $numLen := len $numberMatch }}
{{- $baseLen := sub (len $name) $numLen | int }}
{{- $baseName := substr 0 $baseLen $name }}
{{- if not (hasPrefix "-" $numberMatch) }}
{{- $numberMatch = printf "-%s" $numberMatch }}
{{- end }}
{{- $maxBase := sub 9 (len $numberMatch) | int }}
{{- $baseName = $baseName | trunc $maxBase | trimSuffix "-" }}
{{- $portSuffix = printf "-%s%s" $baseName $numberMatch }}
{{- else }}
{{- $hash := sha256sum $name | trunc 3 }}
{{- $portSuffix = printf "-%s-%s" ($name | trunc 5 | trimSuffix "-") $hash }}
{{- end }}
{{- end }}
{{- end }}
{{- $startPort = add $startPort 2 }} {{- $startPort = add $startPort 2 }}
{{- $kubeConfig := $name }} {{- $kubeConfig := $name }}
{{- if hasKey $clusterSettings "kubeConfigName" }} {{- if hasKey $clusterSettings "kubeConfigName" }}
@@ -41,7 +77,7 @@
{{- if gt $reconcileFederation 1 }} {{- if gt $reconcileFederation 1 }}
{{- fail "You can only have one controller-manager with reconcile.clusterFederatedTrustDomains set to true" }} {{- fail "You can only have one controller-manager with reconcile.clusterFederatedTrustDomains set to true" }}
{{- end }} {{- end }}
{{- include "spire-controller-manager.container" (dict "Values" $root.Values "Chart" $root.Chart "startPort" $startPort "suffix" $suffix "settings" $clusterSettings "defaults" $clusterDefaults "webhooksEnabled" false "kubeConfig" $kubeConfig ) }} {{- include "spire-controller-manager.container" (dict "Values" $root.Values "Chart" $root.Chart "startPort" $startPort "suffix" $suffix "portSuffix" $portSuffix "healthPortName" $healthPortName "prometheusPortName" $prometheusPortName "settings" $clusterSettings "defaults" $clusterDefaults "webhooksEnabled" false "kubeConfig" $kubeConfig ) }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- end }} {{- end }}
@@ -83,27 +119,37 @@
{{- if gt (len $extraEnv) 0 }} {{- if gt (len $extraEnv) 0 }}
{{- $extraEnv | toYaml | nindent 4 }} {{- $extraEnv | toYaml | nindent 4 }}
{{- end }} {{- end }}
{{/* Port names: hp-cm (health), pm-cm (prometheus) - abbreviated for 15 char limit */}}
{{/* Can be overridden via healthPortName and prometheusPortName in cluster config */}}
ports: ports:
{{- if .webhooksEnabled }} {{- if .webhooksEnabled }}
- name: https - name: https
containerPort: 9443 containerPort: 9443
protocol: TCP protocol: TCP
{{- end }} {{- end }}
{{- $hpName := .healthPortName }}
{{- if eq $hpName "" }}
{{- $hpName = printf "hp-cm%s" .portSuffix }}
{{- end }}
- containerPort: {{ $healthPort }} - containerPort: {{ $healthPort }}
name: healthz name: {{ $hpName }}
{{- if or (dig "telemetry" "prometheus" "enabled" .Values.telemetry.prometheus.enabled .Values.global) (and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "prometheus" true .Values.global)) }} {{- if or (dig "telemetry" "prometheus" "enabled" .Values.telemetry.prometheus.enabled .Values.global) (and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "prometheus" true .Values.global)) }}
{{- $pmName := .prometheusPortName }}
{{- if eq $pmName "" }}
{{- $pmName = printf "pm-cm%s" .portSuffix }}
{{- end }}
- containerPort: {{ $promPort }} - containerPort: {{ $promPort }}
name: prom-cm{{ .suffix }} name: {{ $pmName }}
{{- end }} {{- end }}
{{- if eq .Values.controllerManager.staticManifestMode "off" }} {{- if eq .Values.controllerManager.staticManifestMode "off" }}
livenessProbe: livenessProbe:
httpGet: httpGet:
path: /healthz path: /healthz
port: healthz port: {{ $hpName }}
readinessProbe: readinessProbe:
httpGet: httpGet:
path: /readyz path: /readyz
port: healthz port: {{ $hpName }}
{{- end }} {{- end }}
resources: resources:
{{- toYaml .Values.controllerManager.resources | nindent 4 }} {{- toYaml .Values.controllerManager.resources | nindent 4 }}
+3 -1
View File
@@ -850,13 +850,15 @@ externalControllerManagers:
## @param externalControllerManagers.defaults.cacheNamespaces [object] If specified restricts the manager's cache to watch objects in the desired namespaces. Defaults to all namespaces. ## @param externalControllerManagers.defaults.cacheNamespaces [object] If specified restricts the manager's cache to watch objects in the desired namespaces. Defaults to all namespaces.
cacheNamespaces: {} cacheNamespaces: {}
## @param externalControllerManagers.clusters [object] A dictionary of clusters to add with optional overrides. If empty, all clusters defined in kubeConfigs will be used. ## @param externalControllerManagers.clusters [object] A dictionary of clusters to add with optional overrides (kubeConfigName, reconcile, healthPortName, prometheusPortName). If empty, all clusters defined in kubeConfigs will be used.
clusters: {} clusters: {}
# clustera: # clustera:
# Should match the name of the config in the kubeConfigs section # Should match the name of the config in the kubeConfigs section
# kubeConfigName: foo # kubeConfigName: foo
# reconcile: # reconcile:
# clusterStaticEntries: true # clusterStaticEntries: true
# healthPortName: "hp-clustera-01"
# prometheusPortName: "pm-clustera-01"
# other: {} # other: {}
tools: tools: