Helm Sprig join Function: List to String
Convert lists to delimited strings in Helm templates using the Sprig join function. CSV outputs, label values, annotation lists, and multi-value configurations.
π‘ Quick Answer: The Sprig
joinfunction converts a list to a delimited string:{{ list "a" "b" "c" | join "," }}outputsa,b,c. Use it for CSV annotations, comma-separated env vars, multi-value labels, and anywhere Kubernetes needs a single string from multiple values.
The Problem
Kubernetes manifests often need comma-separated or delimited strings β CORS origins, allowed methods, host lists, toleration keys β but Helm values.yaml naturally uses YAML lists. You need to convert ["a", "b", "c"] to "a,b,c" cleanly in templates.
The Solution
Basic Syntax
# Join a list with comma
{{ list "a" "b" "c" | join "," }}
# Output: a,b,c
# Join with custom delimiter
{{ list "app" "web" "v2" | join "-" }}
# Output: app-web-v2
# Join with space
{{ list "hello" "world" | join " " }}
# Output: hello world
# Join values from values.yaml
{{ .Values.cors.origins | join "," }}
# Input: ["https://a.com", "https://b.com"]
# Output: https://a.com,https://b.comCommon Patterns
CORS Origins Annotation
# values.yaml
cors:
origins:
- https://app.example.com
- https://admin.example.com
- https://api.example.com
# templates/ingress.yaml
annotations:
nginx.ingress.kubernetes.io/cors-allow-origin: {{ .Values.cors.origins | join "," | quote }}
# Output: "https://app.example.com,https://admin.example.com,https://api.example.com"Environment Variable from List
# values.yaml
allowedHosts:
- host1.example.com
- host2.example.com
# templates/deployment.yaml
env:
- name: ALLOWED_HOSTS
value: {{ .Values.allowedHosts | join "," | quote }}Node Affinity Labels
# values.yaml
nodeZones:
- us-east-1a
- us-east-1b
# templates/deployment.yaml
annotations:
scheduler.alpha.kubernetes.io/preferred-zones: {{ .Values.nodeZones | join "," | quote }}ConfigMap with Joined Values
# values.yaml
redis:
sentinels:
- redis-sentinel-0.redis:26379
- redis-sentinel-1.redis:26379
- redis-sentinel-2.redis:26379
# templates/configmap.yaml
data:
REDIS_SENTINELS: {{ .Values.redis.sentinels | join ";" | quote }}
# Output: "redis-sentinel-0.redis:26379;redis-sentinel-1.redis:26379;redis-sentinel-2.redis:26379"join vs cat vs printf
| Function | Input | Output | Delimiter |
|---|---|---|---|
join "," | list "a" "b" | a,b | Custom |
cat | "a" "b" | a b | Space (fixed) |
printf | "%s-%s" "a" "b" | a-b | Custom (2 args) |
Building Lists Dynamically
# Conditional list building with append
{{- $features := list -}}
{{- if .Values.metrics.enabled }}
{{- $features = append $features "metrics" -}}
{{- end }}
{{- if .Values.tracing.enabled }}
{{- $features = append $features "tracing" -}}
{{- end }}
annotations:
features: {{ $features | join "," | quote }}Common Issues
Empty List Produces Empty String
{{ list | join "," }}
# Output: "" (empty)
# Add a default
{{ .Values.origins | default (list "http://localhost") | join "," }}Numeric List Items
# values.yaml
ports:
- 8080
- 9090
# join works but items stay as numbers
{{ .Values.ports | join "," }}
# Output: 8080,9090 (works fine)Nested Lists (Not Supported)
# join only works on flat lists
# For nested structures, use range + join:
{{- $hosts := list -}}
{{- range .Values.ingress.hosts }}
{{- $hosts = append $hosts .host -}}
{{- end }}
{{ $hosts | join "," }}Best Practices
- Always
quoteafterjoinβ YAML annotations and values need quoting - Use
","for standard CSV β most K8s annotations expect comma-separated - Use
";"for URLs β URLs contain commas, so use semicolons - Build lists with
appendβ for conditional list construction - Provide
defaultfor empty lists β avoid empty annotation values
Key Takeaways
joinconverts YAML lists to delimited strings with any separator- Essential for annotations (CORS origins, allowed methods, host lists)
- Always pipe through
quotefor proper YAML output - Build conditional lists with
appendthenjoinfor dynamic configuration - Use
default (list "fallback")to handle potentially empty lists

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
