Skip to content

Commit 615218b

Browse files
authored
feat(chart): optional dedicated ServiceAccount and Ingress for fleet-manager (#202)
* feat(chart): optional dedicated ServiceAccount and Ingress for fleet-manager Both off by default, ported from the retired cryptos-release chart (#199): - serviceAccount.create makes a dedicated ServiceAccount with automountServiceAccountToken: false. The pod's serviceAccountName is now always explicit (the namespace's default when serviceAccount.create is false, same as the implicit behavior before this change). - ingress.enabled adds an Ingress with className, annotations, hosts and tls, so exposing the manager no longer needs a separately-managed Ingress. Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com> * ci(chart): lint and template-test the ServiceAccount and Ingress gates helm lint plus render checks that the ServiceAccount and Ingress are omitted by default and render correctly when enabled. This adds the same job-chart-lint.yaml filename as #194's PR: whichever of the two merges first determines the file's final content, and the other needs a small rebase to fold its scenarios in rather than overwrite them. Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com> * fix(chart): bind the memory-store Role to the pod's ServiceAccount With storage.mode=memory and serviceAccount.create=true the pod runs as the dedicated ServiceAccount, but the RoleBinding still named the default one, so the single-replica Lease guard would be refused. The RoleBinding now uses the same ServiceAccount helper as the Deployment, and the chart lint workflow checks the pairing. Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com> --------- Signed-off-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com> Co-authored-by: Bugs5382 <12115015+Bugs5382@users.noreply.github.com>
1 parent 9c31c06 commit 615218b

7 files changed

Lines changed: 150 additions & 1 deletion

File tree

‎.github/workflows/job-chart-lint.yaml‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,45 @@ jobs:
8484
exit 1
8585
fi
8686
grep -q 'mcp.enabled requires database.existingSecret' /tmp/err
87+
88+
- name: helm lint (serviceAccount.create)
89+
run: helm lint chart/fleet-manager --set database.existingSecret=pg-dsn --set serviceAccount.create=true
90+
91+
- name: helm lint (ingress.enabled)
92+
run: |
93+
helm lint chart/fleet-manager --set database.existingSecret=pg-dsn --set ingress.enabled=true \
94+
--set ingress.className=nginx \
95+
--set 'ingress.hosts[0].host=fleetos.example.org' \
96+
--set 'ingress.hosts[0].paths[0].path=/' \
97+
--set 'ingress.hosts[0].paths[0].pathType=Prefix'
98+
99+
- name: helm template omits the ServiceAccount and Ingress by default
100+
run: |
101+
out="$(helm template test chart/fleet-manager --set database.existingSecret=pg-dsn)"
102+
echo "$out" | grep -q 'kind: ServiceAccount' && { echo "ServiceAccount rendered with serviceAccount.create: false" >&2; exit 1; }
103+
echo "$out" | grep -q 'kind: Ingress' && { echo "Ingress rendered with ingress.enabled: false" >&2; exit 1; }
104+
echo "$out" | grep -q 'serviceAccountName: default' || { echo "pod does not explicitly run under the default ServiceAccount" >&2; exit 1; }
105+
106+
- name: helm template renders a dedicated ServiceAccount with automount off
107+
run: |
108+
out="$(helm template test chart/fleet-manager --set database.existingSecret=pg-dsn --set serviceAccount.create=true)"
109+
echo "$out" | grep -q 'kind: ServiceAccount'
110+
echo "$out" | grep -q 'automountServiceAccountToken: false'
111+
echo "$out" | grep -q 'serviceAccountName: fleet-manager'
112+
113+
- name: helm template renders the Ingress with the configured host and class
114+
run: |
115+
out="$(helm template test chart/fleet-manager --set database.existingSecret=pg-dsn --set ingress.enabled=true \
116+
--set ingress.className=nginx \
117+
--set 'ingress.hosts[0].host=fleetos.example.org' \
118+
--set 'ingress.hosts[0].paths[0].path=/' \
119+
--set 'ingress.hosts[0].paths[0].pathType=Prefix')"
120+
echo "$out" | grep -q 'kind: Ingress'
121+
echo "$out" | grep -q 'ingressClassName: nginx'
122+
echo "$out" | grep -q 'host: "fleetos.example.org"'
123+
124+
- name: helm template binds the memory-store Role to the pod's ServiceAccount
125+
run: |
126+
out="$(helm template test chart/fleet-manager --set storage.mode=memory --set serviceAccount.create=true)"
127+
subject="$(echo "$out" | sed -n '/kind: RoleBinding/,/^---/p' | sed -n '/^subjects:/,$p' | grep -m1 -E '^ +name:' | awk '{print $2}')"
128+
[ "$subject" = fleet-manager ] || { echo "RoleBinding binds '$subject', not the dedicated ServiceAccount" >&2; exit 1; }

‎chart/fleet-manager/templates/_helpers.tpl‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
1212
{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
1313
{{- end -}}
1414

15+
{{/*
16+
The ServiceAccount the pod runs under: serviceAccount.name (or
17+
fleet-manager.name) when serviceAccount.create is true, the namespace's
18+
default otherwise.
19+
*/}}
20+
{{- define "fleet-manager.serviceAccountName" -}}
21+
{{- if .Values.serviceAccount.create -}}
22+
{{ .Values.serviceAccount.name | default (include "fleet-manager.name" .) }}
23+
{{- else -}}
24+
default
25+
{{- end -}}
26+
{{- end -}}
27+
1528
{{/*
1629
Where a node's admin credentials Secret is mounted.
1730
*/}}

‎chart/fleet-manager/templates/deployment.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ spec:
3636
# this makes it roll the pod so the manager reads the new config.
3737
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
3838
spec:
39+
serviceAccountName: {{ include "fleet-manager.serviceAccountName" . }}
3940
securityContext:
4041
runAsNonRoot: true
4142
runAsUser: 65532
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{{- if .Values.ingress.enabled -}}
2+
{{- $fullName := include "fleet-manager.name" . -}}
3+
{{- $svcPort := .Values.service.port -}}
4+
apiVersion: networking.k8s.io/v1
5+
kind: Ingress
6+
metadata:
7+
name: {{ $fullName }}
8+
labels:
9+
{{- include "fleet-manager.labels" . | nindent 4 }}
10+
{{- with .Values.ingress.annotations }}
11+
annotations:
12+
{{- toYaml . | nindent 4 }}
13+
{{- end }}
14+
spec:
15+
{{- if .Values.ingress.className }}
16+
ingressClassName: {{ .Values.ingress.className }}
17+
{{- end }}
18+
{{- if .Values.ingress.tls }}
19+
tls:
20+
{{- range .Values.ingress.tls }}
21+
- hosts:
22+
{{- range .hosts }}
23+
- {{ . | quote }}
24+
{{- end }}
25+
secretName: {{ .secretName }}
26+
{{- end }}
27+
{{- end }}
28+
rules:
29+
{{- range .Values.ingress.hosts }}
30+
- host: {{ .host | quote }}
31+
http:
32+
paths:
33+
{{- range .paths }}
34+
- path: {{ .path }}
35+
pathType: {{ .pathType }}
36+
backend:
37+
service:
38+
name: {{ $fullName }}
39+
port:
40+
number: {{ $svcPort }}
41+
{{- end }}
42+
{{- end }}
43+
{{- end }}

‎chart/fleet-manager/templates/rbac-memory-store.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ roleRef:
2828
name: {{ include "fleet-manager.name" . }}-memory-store
2929
subjects:
3030
- kind: ServiceAccount
31-
name: default
31+
name: {{ include "fleet-manager.serviceAccountName" . }}
3232
namespace: {{ .Release.Namespace }}
3333
{{- end }}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{{- if .Values.serviceAccount.create -}}
2+
apiVersion: v1
3+
kind: ServiceAccount
4+
metadata:
5+
name: {{ include "fleet-manager.serviceAccountName" . }}
6+
labels:
7+
{{- include "fleet-manager.labels" . | nindent 4 }}
8+
{{- with .Values.serviceAccount.annotations }}
9+
annotations:
10+
{{- toYaml . | nindent 4 }}
11+
{{- end }}
12+
automountServiceAccountToken: false
13+
{{- end }}

‎chart/fleet-manager/values.yaml‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,40 @@ nodeCreds:
158158
# warning on every connection to the node and the fleet view shows it as not
159159
# verified. There is no switch that turns verification off for every node.
160160
nodes: []
161+
162+
# A dedicated ServiceAccount for the Fleet Manager pod, off by default: the
163+
# pod then runs under the namespace's default ServiceAccount, as it always
164+
# has. Turn this on to give the pod its own identity (for example, to attach a
165+
# cloud workload-identity annotation) without touching whatever else runs
166+
# under default in the namespace.
167+
serviceAccount:
168+
create: false
169+
# Optional name override. When empty and create is true, the chart derives
170+
# the name from fleet-manager.name.
171+
name: ""
172+
annotations: {}
173+
174+
# Expose the Fleet Manager through an Ingress, off by default so operators
175+
# consciously choose how to expose the UI (a LoadBalancer Service and a
176+
# port-forward both work with no Ingress at all). className and annotations
177+
# are optional; tls lists are only needed when terminating TLS at the Ingress
178+
# instead of at the manager itself.
179+
#
180+
# ingress:
181+
# enabled: true
182+
# className: "nginx"
183+
# annotations: {}
184+
# hosts:
185+
# - host: fleetos.example.org
186+
# paths:
187+
# - path: /
188+
# pathType: Prefix
189+
# tls:
190+
# - secretName: fleetos-tls
191+
# hosts: ["fleetos.example.org"]
192+
ingress:
193+
enabled: false
194+
className: ""
195+
annotations: {}
196+
hosts: []
197+
tls: []

0 commit comments

Comments
 (0)