When implementing canary releases or versioned APIs in Kubernetes, we often need to dynamically inject version numbers into ingress paths. Helm templates should ideally handle this automatically without manual updates for each release.
While Helm doesn't provide direct regex functions, we can achieve similar results using these approaches:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
spec:
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /{{ .Chart.AppVersion | regexFind "^\\d+\\.\\d+" }}/api
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-svc
port:
number: 80
For more complex version string parsing, consider these Helm template options:
# Using regexFind to extract major.minor
{{- $version := .Chart.AppVersion | regexFind "^\\d+\\.\\d+" -}}
# Using split to get version components
{{- $versionParts := splitList "." .Chart.AppVersion -}}
{{- $majorMinor := printf "%s.%s" (first $versionParts) (get $versionParts 1) -}}
Here's a full ingress template implementation with version-based routing:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: versioned-ingress
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /{{ .Chart.AppVersion | regexFind "^\\d+\\.\\d+" }}(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: {{ .Release.Name }}-service
port:
number: 8080
- Ensure your Chart.yaml contains proper semver AppVersion
- Test regex patterns with helm template --debug
- Consider adding validation in your values.yaml
- For complex regex, create named templates in _helpers.tpl
When managing multiple application versions in Kubernetes through Helm, we often need to expose different API versions through the same ingress. The challenge arises when we want to automatically include the major.minor version from Chart.yaml
in the ingress path without manual updates.
While Helm provides numerous template functions through Sprig (sprig.github.io
), it doesn't include direct regex support. The closest functions are string manipulation helpers like trim
, replace
, and split
.
For Semver 2.0.0 compliant versions, we can use split
to extract the major.minor portion:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
spec:
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /{{ (split "." .Chart.AppVersion)._0 }}.{{ (split "." .Chart.AppVersion)._1 }}/
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-srv
port:
number: 80
For more complex version patterns, we can create a custom template function:
{{- define "regexExtract" -}}
{{- $matches := regexFindAll .pattern .input -}}
{{- if $matches -}}{{- index (index $matches 0) 1 -}}{{- end -}}
{{- end -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
spec:
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /{{ include "regexExtract" (dict "pattern" (\d+\.\d+) "input" .Chart.AppVersion) }}/
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}-srv
port:
number: 80
Consider these improvements for production use:
- Add validation in
values.yaml
to ensureappVersion
matches expected format - Include fallback paths when version extraction fails
- Consider using annotations for canary deployments instead of path-based versioning
The string manipulation approach is more efficient than regex for simple cases. Benchmark your templates with:
helm template --dry-run --debug your-chart