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
8 changes: 8 additions & 0 deletions charts/standard-application-stack/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v11.4.0] - 2026-06-22
### Added
- Optional kubelock binary injection via `kubelock.injectBinary` (default: `false`). When enabled with `kubelock.enabled`, an init container copies the kubelock binary from `kubelock.image` into a shared volume mounted at `/usr/local/bin/kubelock` on the main container (deployment, celery, and jobs). Default image tag is `v0.4.1`.
### Changed
- kubelock RBAC rules consolidated into `helpers/_kubelock.yaml` (`mintel_common.kubelockRoleRules`).
- kubelock Lease access is scoped to the configured lock name via `resourceNames` (`kubelock.nameOverride` or release/job fullname) for the new Lease-based kubelock release.
- Legacy `endpoints` rules are retained for workloads still using the older Endpoints-based kubelock image.

## [v11.3.0] - 2026-02-19
### Added
- Add preStop hook `mintel_common.deployment.lifecycle` to auth-proxy container
Expand Down
2 changes: 1 addition & 1 deletion charts/standard-application-stack/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 11.3.0
version: 11.4.0

dependencies:
- name: redis
Expand Down
18 changes: 16 additions & 2 deletions charts/standard-application-stack/templates/deployment-celery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ spec:
{{- end }}
{{- end }}
{{- end }}
{{- $kubelockInject := include "mintel_common.kubelock.injectBinaryEnabled" .Values.kubelock | trim -}}
{{- if eq $kubelockInject "true" }}
initContainers:
{{- $kubelockVolumeName := include "mintel_common.kubelock.volumeName" (include "mintel_common.fullname" .) }}
{{- include "mintel_common.kubelock.initContainer" (dict "kubelock" .Values.kubelock "volumeName" $kubelockVolumeName) | nindent 8 }}
{{- end }}
containers:
- name: main
image: {{ .Values.celery.image | default (include "mintel_common.image" .) }}
Expand Down Expand Up @@ -245,8 +251,12 @@ spec:
{{- with .Values.celery.resources }}
resources: {{- toYaml . | nindent 12 }}
{{- end }}
{{- if (or .Values.volumeMounts .Values.celery.volumeMounts) }}
{{- if or .Values.volumeMounts .Values.celery.volumeMounts (eq $kubelockInject "true") }}
volumeMounts:
{{- if eq $kubelockInject "true" }}
{{- $kubelockVolumeName := include "mintel_common.kubelock.volumeName" (include "mintel_common.fullname" .) }}
{{- include "mintel_common.kubelock.volumeMount" (dict "volumeName" $kubelockVolumeName) | nindent 12 }}
{{- end }}
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
Expand Down Expand Up @@ -309,7 +319,7 @@ spec:
{{- end }}
{{- end }}
{{- end }}
{{- if (or .Values.volumes (and .Values.filebeatSidecar .Values.filebeatSidecar.enabled)) }}
{{- if or .Values.volumes (and .Values.filebeatSidecar .Values.filebeatSidecar.enabled) (eq $kubelockInject "true") }}
volumes:
{{- with .Values.volumes }}
{{- toYaml . | nindent 8 }}
Expand All @@ -319,5 +329,9 @@ spec:
name: {{ include "mintel_common.fullname" . }}-filebeat
name: {{ include "mintel_common.fullname" . }}-filebeat
{{- end }}
{{- if eq $kubelockInject "true" }}
{{- $kubelockVolumeName := include "mintel_common.kubelock.volumeName" (include "mintel_common.fullname" .) }}
{{- include "mintel_common.kubelock.volume" (dict "volumeName" $kubelockVolumeName) | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
26 changes: 22 additions & 4 deletions charts/standard-application-stack/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,17 @@ spec:
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.extraInitContainers }}
{{- $kubelockInject := include "mintel_common.kubelock.injectBinaryEnabled" .Values.kubelock | trim -}}
{{- if or (eq $kubelockInject "true") .Values.extraInitContainers }}
initContainers:
{{- if eq $kubelockInject "true" }}
{{- $kubelockVolumeName := include "mintel_common.kubelock.volumeName" (include "mintel_common.fullname" .) }}
{{- include "mintel_common.kubelock.initContainer" (dict "kubelock" .Values.kubelock "volumeName" $kubelockVolumeName) | nindent 8 }}
{{- end }}
{{- with .Values.extraInitContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- if .Values.useHostNetwork }}
hostNetwork: true
{{- end }}
Expand Down Expand Up @@ -345,9 +352,16 @@ spec:
resources: {{- toYaml . | nindent 12 }}
{{- end }}
{{- include "mintel_common.deployment.lifecycle" . | nindent 10 }}
{{- if .Values.volumeMounts }}
{{- $kubelockInject := include "mintel_common.kubelock.injectBinaryEnabled" .Values.kubelock | trim -}}
{{- if or .Values.volumeMounts (eq $kubelockInject "true") }}
volumeMounts:
{{- toYaml .Values.volumeMounts | nindent 12 }}
{{- if eq $kubelockInject "true" }}
{{- $kubelockVolumeName := include "mintel_common.kubelock.volumeName" (include "mintel_common.fullname" .) }}
{{- include "mintel_common.kubelock.volumeMount" (dict "volumeName" $kubelockVolumeName) | nindent 12 }}
{{- end }}
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- if (and .Values.filebeatSidecar .Values.filebeatSidecar.enabled) }}
- name: filebeat
Expand Down Expand Up @@ -448,7 +462,7 @@ spec:
- mountPath: {{ .Values.gitSyncSidecar.root }}
name: {{ include "mintel_common.fullname" . }}-git-sync
{{- end }}
{{- if or (and .Values.filebeatSidecar .Values.filebeatSidecar.enabled) (and .Values.gitSyncSidecar .Values.gitSyncSidecar.enabled) (.Values.volumes) }}
{{- if or (and .Values.filebeatSidecar .Values.filebeatSidecar.enabled) (and .Values.gitSyncSidecar .Values.gitSyncSidecar.enabled) (.Values.volumes) (eq (include "mintel_common.kubelock.injectBinaryEnabled" .Values.kubelock | trim) "true") }}
volumes:
{{- if not .Values.statefulset }}
{{- if .Values.persistentVolumes }}
Expand All @@ -471,5 +485,9 @@ spec:
- name: {{ include "mintel_common.fullname" . }}-git-sync
emptyDir: {}
{{- end }}
{{- if eq (include "mintel_common.kubelock.injectBinaryEnabled" .Values.kubelock | trim) "true" }}
{{- $kubelockVolumeName := include "mintel_common.kubelock.volumeName" (include "mintel_common.fullname" .) }}
{{- include "mintel_common.kubelock.volume" (dict "volumeName" $kubelockVolumeName) | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
111 changes: 111 additions & 0 deletions charts/standard-application-stack/templates/helpers/_kubelock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{{/* vim: set filetype=mustache: */}}

{{/*
RBAC rules for kubelock leader election.

Shared by both kubelock Role creation paths:
- Release-level: templates/kubelock-role.yaml (Values.kubelock.enabled)
- Per-job: templates/jobs.yaml via mintel_common.role (jobs[].kubelock.enabled)

Expects the lock name (KUBELOCK_NAME / kubelock --name):
- leases: new kubelock (gitlab.com/mintel/satoshi/tools/kubelock), scoped via resourceNames
- endpoints: legacy kubelock (mintel/kubelock), unscoped for backward compatibility
*/}}
{{- define "mintel_common.kubelockRoleRules" -}}
- apiGroups:
- coordination.k8s.io
resources:
- leases
resourceNames:
- {{ . | quote }}
verbs:
- get
- list
- create
- update
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
- list
- create
- update
{{- end -}}

{{/*
Return true when kubelock binary injection is enabled. Expects a kubelock values dict.
*/}}
{{- define "mintel_common.kubelock.injectBinaryEnabled" -}}
{{- and .enabled .injectBinary -}}
{{- end -}}

{{/*
Return the kubelock container image. Expects a kubelock values dict.
*/}}
{{- define "mintel_common.kubelock.image" -}}
{{- if .image.fullname -}}
{{- .image.fullname -}}
{{- else -}}
{{- $registry := .image.registry | default "551844124467.dkr.ecr.${CLUSTER_REGION}.amazonaws.com" -}}
{{- $repository := .image.repository | default "gitlab/mintel/satoshi/tools/kubelock" -}}
{{- $tag := .image.tag | default "v0.4.1" | toString -}}
{{- printf "%s/%s:%s" $registry $repository $tag -}}
{{- end -}}
{{- end -}}

{{/*
Return the kubelock image pull policy. Expects a kubelock values dict.
*/}}
{{- define "mintel_common.kubelock.imagePullPolicy" -}}
{{- .image.pullPolicy | default "IfNotPresent" -}}
{{- end -}}

{{/*
Shared emptyDir volume name for kubelock binary injection. Expects the workload name prefix.
*/}}
{{- define "mintel_common.kubelock.volumeName" -}}
{{- printf "%s-kubelock-bin" . -}}
{{- end -}}

{{/*
emptyDir volume for kubelock binary injection. Expects dict with key "volumeName".
*/}}
{{- define "mintel_common.kubelock.volume" -}}
- name: {{ .volumeName }}
emptyDir: {}
{{- end -}}

{{/*
Main-container volumeMount for an injected kubelock binary. Expects dict with key "volumeName".
*/}}
{{- define "mintel_common.kubelock.volumeMount" -}}
- name: {{ .volumeName }}
mountPath: /usr/local/bin/kubelock
subPath: kubelock
{{- end -}}

{{/*
Init container that copies the kubelock binary into the shared emptyDir volume.
Expects dict with keys "kubelock" (values dict) and "volumeName".
The kubelock image must include /bin/sh (busybox-based builds support injectBinary).
*/}}
{{- define "mintel_common.kubelock.initContainer" -}}
- name: kubelock-binary
image: {{ include "mintel_common.kubelock.image" .kubelock }}
imagePullPolicy: {{ include "mintel_common.kubelock.imagePullPolicy" .kubelock }}
command:
- /bin/sh
- -ec
- cp /usr/local/bin/kubelock /kubelock-bin/kubelock && chmod 755 /kubelock-bin/kubelock
volumeMounts:
- name: {{ .volumeName }}
mountPath: /kubelock-bin
{{- with .kubelock.resources }}
resources: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .kubelock.securityContext }}
securityContext: {{- toYaml . | nindent 4 }}
{{- end }}
{{- end -}}
22 changes: 3 additions & 19 deletions charts/standard-application-stack/templates/helpers/_role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ name: string # The name of the role. Defaults to global name if no
annotations: dict # Any extra custom annotations.
argo: dict # Standard argo object (as processed by mintel_common.argoAnnotations).
rules: list(string) # A list of keywords that determine which rules get added to the role.
# Example: list "kubelock"
# Example: list "kubelock" (used by per-job kubelock in jobs.yaml;
# release workloads use kubelock-role.yaml instead)

*/}}
{{- define "mintel_common.role" -}}
Expand All @@ -28,23 +29,6 @@ metadata:
{{ end }}
rules:
{{ if (has "kubelock" $config.rules) }}
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- create
- update
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
- list
- create
- update
{{ include "mintel_common.kubelockRoleRules" ($config.kubelockLeaseName | default (include "mintel_common.fullname" $)) | nindent 0 }}
{{- end -}}
{{- end -}}
36 changes: 29 additions & 7 deletions charts/standard-application-stack/templates/jobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
{{- $data := dict "Release" $.Release "Chart" $.Chart "Values" $.Values "component" .name }}
{{- $job := mergeOverwrite $.Values.jobDefaults . }}
{{- with $job }}
{{- $kubelock := mergeOverwrite (deepCopy $.Values.kubelock) .kubelock -}}
{{- $serviceAccountEnabled := or .kubelock.enabled .irsa.enabled }}
{{- $kubelockInject := include "mintel_common.kubelock.injectBinaryEnabled" $kubelock | trim -}}
{{- $jobName := (include "mintel_common.fullname" $data) -}}
---
apiVersion: {{ include "common.capabilities.job.apiVersion" $ }}
Expand Down Expand Up @@ -48,15 +50,25 @@ spec:
{{- if (and $.Values.serviceAccount (or $.Values.serviceAccount.create $.Values.serviceAccount.name)) }}
serviceAccountName: {{ $jobName }}
{{- end }}
restartPolicy: {{ .restartPolicy }}
{{- with .volumes }}
{{- if or .volumes (eq $kubelockInject "true") }}
volumes:
{{- if eq $kubelockInject "true" }}
{{- include "mintel_common.kubelock.volume" (dict "volumeName" (include "mintel_common.kubelock.volumeName" $jobName)) | nindent 12 }}
{{- end }}
{{- with .volumes }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- with .extraInitContainers }}
{{- if or .extraInitContainers (eq $kubelockInject "true") }}
initContainers:
{{- toYaml . | nindent 12 }}
{{- if eq $kubelockInject "true" }}
{{- include "mintel_common.kubelock.initContainer" (dict "kubelock" $kubelock "volumeName" (include "mintel_common.kubelock.volumeName" $jobName)) | nindent 12 }}
{{- end }}
{{- with .extraInitContainers }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
restartPolicy: {{ .restartPolicy }}
containers:
- name: main
image: {{ .image | default (include "mintel_common.image" $) }}
Expand Down Expand Up @@ -105,18 +117,28 @@ spec:
{{- end }}
resources: {{- toYaml . | nindent 12 }}
{{- end }}
{{- with .volumeMounts }}
volumeMounts: {{- toYaml . | nindent 16 }}
{{- if or .volumeMounts (eq $kubelockInject "true") }}
volumeMounts:
{{- if eq $kubelockInject "true" }}
{{- include "mintel_common.kubelock.volumeMount" (dict "volumeName" (include "mintel_common.kubelock.volumeName" $jobName)) | nindent 16 }}
{{- end }}
{{- with .volumeMounts }}
{{- toYaml . | nindent 16 }}
{{- end }}
{{- end }}

{{- if $serviceAccountEnabled }}
---
{{- $serviceAccountConfig := dict "name" $jobName "argo" .argo "irsa" .irsa }}
{{- include "mintel_common.serviceAccount" (list $ $serviceAccountConfig) }}

{{/* Per-job kubelock RBAC when jobs[].kubelock.enabled (or jobDefaults.kubelock.enabled).
Creates a dedicated ServiceAccount, Role, and RoleBinding for this Job.
Release workloads use templates/kubelock-role.yaml (Values.kubelock.enabled) instead. */}}
{{- if .kubelock.enabled }}
---
{{- $roleConfig := dict "name" $jobName "argo" .argo "rules" (list "kubelock") -}}
{{- $leaseName := .kubelock.nameOverride | default $jobName -}}
{{- $roleConfig := dict "name" $jobName "argo" .argo "rules" (list "kubelock") "kubelockLeaseName" $leaseName -}}
{{- include "mintel_common.role" (list $ $roleConfig) }}
---
{{- $roleBindingConfig := dict "name" $jobName "argo" .argo "roleName" $jobName "serviceAccountName" $jobName -}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{{/*
Binds the release kubelock Role (kubelock-role.yaml) to the main ServiceAccount
(Values.serviceAccount). Created when Values.kubelock.enabled is true.
*/}}
{{- if (and .Values.serviceAccount .Values.serviceAccount.create) }}

{{- if (and .Values.kubelock .Values.kubelock.enabled) }}
Expand Down
Loading
Loading