How to Use Regex in Helm Templates for Dynamic Ingress Path Versioning


2 views

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 ensure appVersion 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