Skip to content

Commit 3e493e1

Browse files
committed
Send traffic to the arm64 pods from one Service
The arm64 variant has its own `app.kubernetes.io/name`, so the chart made a second Service for it. The HTTPRoute backs only the amd64 Service, so the arm64 pods never received traffic. Every pod template now carries `app.kubernetes.io/component`, which holds the workload name and is the same for all architectures. When arm64 is enabled, the Service and the PodDisruptionBudget select that label, so one Service reaches the pods of both architectures and the load balancer sends traffic to both. When arm64 is off, the selector does not change. No Deployment selector changes, so no workload is recreated. The label is added before it is selected, so an environment that enables arm64 later gets no interval without endpoints. Bump the chart first, then enable arm64. In one sync the amd64 pods would still roll to get the label while the selector already moved.
1 parent a380dcf commit 3e493e1

6 files changed

Lines changed: 96 additions & 60 deletions

File tree

charts/lago-rails/templates/_helpers.tpl

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Common labels
3737
*/}}
3838
{{- define "lago-rails.labels" -}}
3939
helm.sh/chart: {{ include "lago-rails.chart" . }}
40-
{{ include "lago-rails.selectorLabels" . }}
40+
{{ include "lago-rails.architecture.selectorLabels" . }}
4141
{{- if .Chart.AppVersion }}
4242
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
4343
{{- end }}
@@ -73,32 +73,40 @@ amd64 name.
7373
{{- end }}
7474

7575
{{/*
76-
Create architecture-specific selector labels. The amd64 result delegates to
77-
the existing helper so its rendered labels do not change.
76+
Create architecture-specific selector labels. Each architecture keeps its own
77+
`app.kubernetes.io/name`, so a Deployment selector matches only its own pods.
78+
The Deployment selector is immutable, so this helper must not change.
7879
*/}}
7980
{{- define "lago-rails.architecture.selectorLabels" -}}
8081
{{- if eq (include "lago-rails.architecture.isArm64" .) "true" -}}
81-
app.kubernetes.io/name: {{ printf "%s-arm64" .Values.internalArchitectureName | trunc 63 | trimSuffix "-" }}
82+
app.kubernetes.io/name: {{ printf "%s-arm64" (include "lago-rails.name" .) | trunc 63 | trimSuffix "-" }}
8283
app.kubernetes.io/instance: {{ .Release.Name }}
8384
{{- else -}}
8485
{{- include "lago-rails.selectorLabels" . -}}
8586
{{- end -}}
8687
{{- end }}
8788

8889
{{/*
89-
Create architecture-specific labels. The amd64 result delegates to the
90-
existing helper so its rendered labels do not change.
90+
The architecture-independent label that every pod of this workload carries. The
91+
Service and the PodDisruptionBudget select it, so they reach the pods of all
92+
architectures.
9193
*/}}
92-
{{- define "lago-rails.architecture.labels" -}}
93-
{{- if eq (include "lago-rails.architecture.isArm64" .) "true" -}}
94-
helm.sh/chart: {{ include "lago-rails.chart" . }}
95-
{{ include "lago-rails.architecture.selectorLabels" . }}
96-
{{- if .Chart.AppVersion }}
97-
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
94+
{{- define "lago-rails.componentLabel" -}}
95+
app.kubernetes.io/component: {{ include "lago-rails.name" . }}
9896
{{- end }}
99-
app.kubernetes.io/managed-by: {{ .Release.Service }}
97+
98+
{{/*
99+
Selector labels for the Service and the PodDisruptionBudget. arm64 pods have a
100+
different `app.kubernetes.io/name`, so the selector moves to the `component`
101+
label when arm64 is enabled. Every pod already carries that label, because the
102+
chart adds it to all pod templates.
103+
*/}}
104+
{{- define "lago-rails.service.selectorLabels" -}}
105+
{{- if .Values.global.architectures.arm64.enabled -}}
106+
app.kubernetes.io/instance: {{ .Release.Name }}
107+
{{ include "lago-rails.componentLabel" . }}
100108
{{- else -}}
101-
{{- include "lago-rails.labels" . -}}
109+
{{- include "lago-rails.selectorLabels" . -}}
102110
{{- end -}}
103111
{{- end }}
104112

charts/lago-rails/templates/deployment.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ metadata:
88
{{- toYaml . | nindent 4 }}
99
{{- end }}
1010
labels:
11-
{{- include "lago-rails.architecture.labels" . | nindent 4 }}
11+
{{- include "lago-rails.labels" . | nindent 4 }}
1212
spec:
1313
{{- if not .Values.autoscaling.enabled }}
1414
replicas: {{ .Values.replicaCount }}
@@ -23,7 +23,8 @@ spec:
2323
{{- toYaml . | nindent 8 }}
2424
{{- end }}
2525
labels:
26-
{{- include "lago-rails.architecture.labels" . | nindent 8 }}
26+
{{- include "lago-rails.labels" . | nindent 8 }}
27+
{{- include "lago-rails.componentLabel" . | nindent 8 }}
2728
{{- with .Values.podLabels }}
2829
{{- toYaml . | nindent 8 }}
2930
{{- end }}
@@ -480,7 +481,6 @@ spec:
480481
{{- $_ := set $amd64Values "tolerations" (concat .Values.tolerations $amd64.tolerations) }}
481482
{{- $amd64Context := dict "Values" $amd64Values "Chart" .Chart "Release" .Release "Capabilities" .Capabilities "Template" .Template "Files" .Files }}
482483
{{- $architectureFullname := include "lago-rails.fullname" $amd64Context }}
483-
{{- $architectureName := include "lago-rails.name" $amd64Context }}
484484
{{- if .Values.global.architectures.amd64.enabled }}
485485
{{ include "lago-rails.deployment" $amd64Context }}
486486
{{- end }}
@@ -492,7 +492,6 @@ spec:
492492
{{- $arm64Values := deepCopy .Values }}
493493
{{- $_ := set $arm64Values "internalArchitecture" "arm64" }}
494494
{{- $_ := set $arm64Values "internalArchitectureFullname" $architectureFullname }}
495-
{{- $_ := set $arm64Values "internalArchitectureName" $architectureName }}
496495
{{- $_ := set $arm64Values "replicaCount" $arm64.replicaCount }}
497496
{{- $_ := set $arm64Values "nodeSelector" (mustMergeOverwrite (deepCopy .Values.nodeSelector) $arm64.nodeSelector) }}
498497
{{- $_ := set $arm64Values "tolerations" (concat .Values.tolerations $arm64.tolerations) }}

charts/lago-rails/templates/hpa.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ kind: HorizontalPodAutoscaler
44
metadata:
55
name: {{ include "lago-rails.architecture.fullname" . }}
66
labels:
7-
{{- include "lago-rails.architecture.labels" . | nindent 4 }}
7+
{{- include "lago-rails.labels" . | nindent 4 }}
88
spec:
99
scaleTargetRef:
1010
apiVersion: apps/v1
@@ -42,7 +42,6 @@ spec:
4242
{{- $arm64Values := deepCopy .Values }}
4343
{{- $_ := set $arm64Values "internalArchitecture" "arm64" }}
4444
{{- $_ := set $arm64Values "internalArchitectureFullname" (include "lago-rails.fullname" .) }}
45-
{{- $_ := set $arm64Values "internalArchitectureName" (include "lago-rails.name" .) }}
4645
{{- $_ := set $arm64Values "autoscaling" $arm64.autoscaling }}
4746
{{- $arm64Context := dict "Values" $arm64Values "Chart" .Chart "Release" .Release "Capabilities" .Capabilities "Template" .Template "Files" .Files }}
4847
{{ include "lago-rails.hpa" $arm64Context }}
Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
{{- define "lago-rails.pdb" -}}
1+
{{/*
2+
One PodDisruptionBudget for all architectures. The pods of both serve the same
3+
Service, so one budget applies to them together.
4+
*/}}
5+
{{- if .Values.podDisruptionBudget.enabled }}
26
apiVersion: policy/v1
37
kind: PodDisruptionBudget
48
metadata:
5-
name: {{ include "lago-rails.architecture.fullname" . }}
9+
name: {{ include "lago-rails.fullname" . }}
610
labels:
7-
{{- include "lago-rails.architecture.labels" . | nindent 4 }}
11+
{{- include "lago-rails.labels" . | nindent 4 }}
812
spec:
913
{{- with .Values.podDisruptionBudget.minAvailable }}
1014
minAvailable: {{ . }}
@@ -14,21 +18,5 @@ spec:
1418
{{- end }}
1519
selector:
1620
matchLabels:
17-
{{- include "lago-rails.architecture.selectorLabels" . | nindent 6 }}
18-
{{- end }}
19-
20-
{{- if .Values.podDisruptionBudget.enabled }}
21-
{{- $amd64Values := deepCopy .Values }}
22-
{{- $amd64Context := dict "Values" $amd64Values "Chart" .Chart "Release" .Release "Capabilities" .Capabilities "Template" .Template "Files" .Files }}
23-
{{ include "lago-rails.pdb" $amd64Context }}
24-
{{- $arm64 := .Values.architectures.arm64 }}
25-
{{- if and .Values.global.architectures.arm64.enabled (or (gt (int $arm64.replicaCount) 0) $arm64.autoscaling.enabled) }}
26-
---
27-
{{- $arm64Values := deepCopy .Values }}
28-
{{- $_ := set $arm64Values "internalArchitecture" "arm64" }}
29-
{{- $_ := set $arm64Values "internalArchitectureFullname" (include "lago-rails.fullname" .) }}
30-
{{- $_ := set $arm64Values "internalArchitectureName" (include "lago-rails.name" .) }}
31-
{{- $arm64Context := dict "Values" $arm64Values "Chart" .Chart "Release" .Release "Capabilities" .Capabilities "Template" .Template "Files" .Files }}
32-
{{ include "lago-rails.pdb" $arm64Context }}
33-
{{- end }}
21+
{{- include "lago-rails.service.selectorLabels" . | nindent 6 }}
3422
{{- end }}
Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
{{- define "lago-rails.service" -}}
1+
{{/*
2+
One Service for all architectures. The selector has no
3+
`app.kubernetes.io/component`, so it matches amd64 pods and arm64 pods.
4+
*/}}
5+
{{- if .Values.service.enabled }}
26
apiVersion: v1
37
kind: Service
48
metadata:
5-
name: {{ include "lago-rails.architecture.fullname" . }}
9+
name: {{ include "lago-rails.fullname" . }}
610
labels:
7-
{{- include "lago-rails.architecture.labels" . | nindent 4 }}
11+
{{- include "lago-rails.labels" . | nindent 4 }}
812
spec:
913
type: {{ .Values.service.type }}
1014
ports:
@@ -13,21 +17,5 @@ spec:
1317
protocol: TCP
1418
name: http
1519
selector:
16-
{{- include "lago-rails.architecture.selectorLabels" . | nindent 4 }}
17-
{{- end }}
18-
19-
{{- if .Values.service.enabled }}
20-
{{- $amd64Values := deepCopy .Values }}
21-
{{- $amd64Context := dict "Values" $amd64Values "Chart" .Chart "Release" .Release "Capabilities" .Capabilities "Template" .Template "Files" .Files }}
22-
{{ include "lago-rails.service" $amd64Context }}
23-
{{- $arm64 := .Values.architectures.arm64 }}
24-
{{- if and .Values.global.architectures.arm64.enabled (or (gt (int $arm64.replicaCount) 0) $arm64.autoscaling.enabled) }}
25-
---
26-
{{- $arm64Values := deepCopy .Values }}
27-
{{- $_ := set $arm64Values "internalArchitecture" "arm64" }}
28-
{{- $_ := set $arm64Values "internalArchitectureFullname" (include "lago-rails.fullname" .) }}
29-
{{- $_ := set $arm64Values "internalArchitectureName" (include "lago-rails.name" .) }}
30-
{{- $arm64Context := dict "Values" $arm64Values "Chart" .Chart "Release" .Release "Capabilities" .Capabilities "Template" .Template "Files" .Files }}
31-
{{ include "lago-rails.service" $arm64Context }}
32-
{{- end }}
20+
{{- include "lago-rails.service.selectorLabels" . | nindent 4 }}
3321
{{- end }}

charts/lago/tests/architecture_test.yaml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ suite: Test amd64 and arm64 API and worker deployments
22
templates:
33
- charts/api/templates/deployment.yaml
44
- charts/worker/templates/deployment.yaml
5+
- charts/api/templates/service.yaml
56

67
set:
78
global:
@@ -201,6 +202,59 @@ tests:
201202
- hasDocuments:
202203
count: 1
203204

205+
- it: keeps a separate name in each deployment selector
206+
template: charts/api/templates/deployment.yaml
207+
asserts:
208+
- equal:
209+
path: spec.selector.matchLabels
210+
value:
211+
app.kubernetes.io/name: lago-api
212+
app.kubernetes.io/instance: RELEASE-NAME
213+
documentIndex: 0
214+
- equal:
215+
path: spec.selector.matchLabels
216+
value:
217+
app.kubernetes.io/name: lago-api-arm64
218+
app.kubernetes.io/instance: RELEASE-NAME
219+
documentIndex: 1
220+
221+
- it: gives the pods of both architectures the same component label
222+
template: charts/api/templates/deployment.yaml
223+
asserts:
224+
- equal:
225+
path: spec.template.metadata.labels["app.kubernetes.io/component"]
226+
value: lago-api
227+
documentIndex: 0
228+
- equal:
229+
path: spec.template.metadata.labels["app.kubernetes.io/component"]
230+
value: lago-api
231+
documentIndex: 1
232+
233+
- it: renders one API service that selects the component when arm64 is on
234+
template: charts/api/templates/service.yaml
235+
asserts:
236+
- hasDocuments:
237+
count: 1
238+
- equal:
239+
path: spec.selector
240+
value:
241+
app.kubernetes.io/instance: RELEASE-NAME
242+
app.kubernetes.io/component: lago-api
243+
244+
- it: keeps the original API service selector when arm64 is off
245+
template: charts/api/templates/service.yaml
246+
set:
247+
global:
248+
architectures:
249+
arm64:
250+
enabled: false
251+
asserts:
252+
- equal:
253+
path: spec.selector
254+
value:
255+
app.kubernetes.io/name: lago-api
256+
app.kubernetes.io/instance: RELEASE-NAME
257+
204258
- it: renders an arm64 worker without replicas when KEDA controls it
205259
template: charts/worker/templates/deployment.yaml
206260
set:

0 commit comments

Comments
 (0)