Library Charts and Organizational Standardization
In Lessons 1-7, you've built individual Helm charts that deploy applications with templating, hooks, and distribution strategies. But what happens when you have 10 microservices? Do you repeat the same labels, resource probes, and annotations in each chart? What if your security team requires specific SecurityContext defaults across all deployments?
This lesson introduces library charts—a Helm pattern that solves this through reusable templates. Instead of duplicating patterns across charts, you encode them once in a library chart that all application charts consume. Your organization then has a single source of truth for labels, probes, resource defaults, and organizational standards.
By the end of this lesson, you'll understand how library charts enforce consistency across your platform without forcing teams into rigid constraints.
What You'll Learn
This lesson covers 8 concepts organized into 3 groups:
| Concept Group | Concepts | What You'll Build |
|---|---|---|
| Library Chart Fundamentals | 1-2 | Understand library chart type and installation restrictions |
| Creating Reusable Templates | 3-5 | Build organizational templates and consume them in applications |
| Advanced Patterns | 6-8 | Implement overrides, enterprise use cases, and template inheritance |
Prerequisites:
- Completed Lessons 1-4 (Helm basics, templating, values)
- Understanding of
includefunction and template helpers - Experience creating application charts
Time Estimate: 45 minutes
Concept 1: Library Chart Type
Library charts declare their purpose in Chart.yaml with type: library. This tells Helm that this chart exists to be included as a dependency, not to be installed directly.
Creating a Library Chart
Start with the basic structure:
mkdir -p org-standards/templates
# Create Chart.yaml
cat > org-standards/Chart.yaml <<'EOF'
apiVersion: v2
name: org-standards
description: "Organizational standards for labels, probes, and security"
type: library
version: 1.0.0
EOF
# Create values.yaml with organizational defaults
cat > org-standards/values.yaml <<'EOF'
organization:
name: "my-company"
team: "platform"
environment: "dev"
commonLabels:
managed-by: "helm"
org: "my-company"
commonAnnotations:
doc-link: "https://internal.docs/deployments"
securityDefaults:
runAsNonRoot: true
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
EOF
# Create empty templates directory
mkdir org-standards/templates
Output:
org-standards/
├── Chart.yaml
├── values.yaml
└── templates/
$ cat org-standards/Chart.yaml
apiVersion: v2
name: org-standards
description: "Organizational standards for labels, probes, and security"
type: library
version: 1.0.0
The type: library field distinguishes this chart from application charts (which have no type field or type: application).
Concept 2: Why Library Charts Cannot Be Installed Directly
Helm refuses to install library charts directly. They contain only template definitions, not complete deployable resources.
Testing the Restriction
Try installing the library chart:
cd org-standards
# Attempt to install library chart
helm install my-org . --dry-run=client
Output:
error: chart "org-standards" is a library chart. Library charts
are not installable. See https://helm.sh/docs/topics/library_charts/
for more information.
This restriction is intentional. Library charts have no .Chart.Name release—they're meant to provide helper functions that application charts use. Installing them directly would create an empty release with no resources, providing no value.
Checkpoint: Library Chart Fundamentals
Quick Reference:
- Library charts:
type: libraryin Chart.yaml, cannot be installed directly - Purpose: Provide reusable templates consumed by application charts
- Usage: Included as dependencies, not standalone releases
Self-Check Questions:
- What happens if you try to
helm installa library chart? - Why does Helm prevent library chart installation?
- Where does the library chart declaration go in Chart.yaml?
Answers:
- Helm returns an error: "chart is a library chart. Library charts are not installable"
- Library charts contain only template definitions, not complete deployable resources
type: libraryfield in Chart.yaml
Concept 3: Common Templates for Organizational Consistency
Create reusable templates in the library chart that enforce organizational patterns.
Creating Labels Template
cat > org-standards/templates/_labels.tpl <<'EOF'
{{- define "org-standards.labels" -}}
app.kubernetes.io/name: {{ include "org-standards.name" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
org: {{ .Values.organization.name }}
team: {{ .Values.organization.team }}
env: {{ .Values.organization.environment }}
{{- end }}
{{- define "org-standards.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
EOF
Creating Common Annotations Template
cat > org-standards/templates/_annotations.tpl <<'EOF'
{{- define "org-standards.annotations" -}}
documentation: {{ .Values.commonAnnotations.doc-link }}
updated-at: {{ now | date "2006-01-02T15:04:05Z07:00" }}
{{- end }}
EOF
Creating Probes Template
cat > org-standards/templates/_probes.tpl <<'EOF'
{{- define "org-standards.livenessProbe" -}}
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
{{- end }}
{{- define "org-standards.readinessProbe" -}}
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
{{- end }}
EOF
Output:
org-standards/templates/
├── _annotations.tpl
├── _labels.tpl
└── _probes.tpl
$ ls -la org-standards/templates/
total 48
-rw-r--r-- 1 user staff 285 org-standards/templates/_annotations.tpl
-rw-r--r-- 1 user staff 412 org-standards/templates/_labels.tpl
-rw-r--r-- 1 user staff 518 org-standards/templates/_probes.tpl
These templates define labels, annotations, and probes that any application chart can use without reimplementation.
Concept 4: Consuming Library Charts as Dependencies
Application charts declare library charts as dependencies in Chart.yaml.
Create Application Chart with Library Dependency
mkdir -p my-api/templates
# Create Chart.yaml with library dependency
cat > my-api/Chart.yaml <<'EOF'
apiVersion: v2
name: my-api
description: "AI agent API service"
type: application
version: 1.0.0
appVersion: "1.0"
dependencies:
- name: org-standards
version: "1.0.0"
repository: "file://../org-standards"
condition: org-standards.enabled
EOF
# Create application values.yaml
cat > my-api/values.yaml <<'EOF'
appName: my-api
replicaCount: 2
image:
repository: my-org/my-api
tag: "1.0.0"
# Enable the library chart
org-standards:
enabled: true
organization:
name: my-company
team: platform
environment: prod
EOF
# Update Helm dependencies
helm dependency update my-api/
Output:
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "file://../org-standards" repo
Saving 1 charts
Downloading org-standards from repo file://../org-standards
...Deleting outdated charts
$ ls -la my-api/charts/
total 32
drwxr-xr-x 4 user staff 128 org-standards/
The helm dependency update command fetches the library chart and places it in my-api/charts/org-standards/.
Concept 5: Using include to Pull Library Templates
Application charts use include function to reference templates from library charts.
Creating Application Deployment Using Library Templates
cat > my-api/templates/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.appName }}
labels:
{{- include "org-standards.labels" . | nindent 4 }}
annotations:
{{- include "org-standards.annotations" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.appName }}
template:
metadata:
labels:
app: {{ .Values.appName }}
{{- include "org-standards.labels" . | nindent 8 }}
spec:
containers:
- name: api
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 8080
{{- include "org-standards.livenessProbe" . | nindent 8 }}
{{- include "org-standards.readinessProbe" . | nindent 8 }}
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
EOF
Output:
$ helm template my-api .
---
# Source: my-api/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-api
labels:
app.kubernetes.io/name: my-api
app.kubernetes.io/version: "1.0"
app.kubernetes.io/managed-by: Helm
org: my-company
team: platform
env: prod
annotations:
documentation: https://internal.docs/deployments
updated-at: "2025-12-23T10:15:30Z"
spec:
replicas: 2
selector:
matchLabels:
app: my-api
template:
metadata:
labels:
app: my-api
app.kubernetes.io/name: my-api
app.kubernetes.io/version: "1.0"
app.kubernetes.io/managed-by: Helm
org: my-company
team: platform
env: prod
spec:
containers:
- name: api
image: "my-org/my-api:1.0.0"
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
The include function pulls templates from the library chart and injects them into the deployment, automatically inheriting organization labels and probes.
Concept 6: Override Patterns for Application-Specific Values
Applications override library defaults through the values.yaml hierarchy while maintaining organizational standards.
Creating Multiple Application Charts with Overrides
# Application 1: Web service
mkdir -p web-service/templates
cat > web-service/Chart.yaml <<'EOF'
apiVersion: v2
name: web-service
description: "Web frontend"
type: application
version: 1.0.0
dependencies:
- name: org-standards
version: "1.0.0"
repository: "file://../org-standards"
EOF
cat > web-service/values.yaml <<'EOF'
appName: web-service
replicaCount: 3 # More replicas for web traffic
image:
repository: my-org/web-service
tag: "2.1.0"
org-standards:
enabled: true
organization:
name: my-company
team: frontend # Override team
environment: prod
# Override default probes for web service
customProbes:
livenessProbe:
httpGet:
path: /api/health
port: 8080
initialDelaySeconds: 15 # Faster startup
EOF
# Application 2: Background worker
mkdir -p bg-worker/templates
cat > bg-worker/Chart.yaml <<'EOF'
apiVersion: v2
name: bg-worker
description: "Background job processor"
type: application
version: 1.0.0
dependencies:
- name: org-standards
version: "1.0.0"
repository: "file://../org-standards"
EOF
cat > bg-worker/values.yaml <<'EOF'
appName: bg-worker
replicaCount: 2
image:
repository: my-org/bg-worker
tag: "1.5.0"
org-standards:
enabled: true
organization:
name: my-company
team: backend # Override team
environment: prod
EOF
Output:
# Web service inherits all org-standards labels/probes
$ helm template web-service . | grep -A 5 labels:
labels:
app.kubernetes.io/name: web-service
org: my-company
team: frontend # Team overridden in values
# Background worker gets same labels
$ helm template bg-worker . | grep -A 5 labels:
labels:
app.kubernetes.io/name: bg-worker
org: my-company
team: backend # Different team
Each application overrides organizational defaults for its context while maintaining consistency through the library chart.
Checkpoint: Creating and Consuming Library Templates
Quick Reference:
- Template files: Prefix with
_(e.g.,_labels.tpl), define with{{- define "name" -}} - Dependency setup: Add to Chart.yaml dependencies, run
helm dependency update - Template usage:
{{- include "org-standards.labels" . | nindent 4 }} - Override values: Pass through
org-standards:section in application values.yaml
Self-Check Questions:
- How do application charts reference library chart templates?
- What command fetches library chart dependencies?
- How can applications override library default values?
Answers:
- Using
includefunction:{{- include "library-name.template-name" . }} helm dependency update <chart-directory>/- Through values.yaml hierarchy under the library chart's name (e.g.,
org-standards:)
Concept 7: Enterprise Use Cases
Library charts solve real organizational problems: enforcing security policies, maintaining labeling conventions, and standardizing resource defaults across hundreds of deployments.
Common Enterprise Library Chart Patterns
Pattern 1: Security Enforcement
cat > org-standards/templates/_security.tpl <<'EOF'
{{- define "org-standards.securityContext" -}}
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
{{- end }}
EOF
All deployments automatically get security hardening without individual configuration.
Pattern 2: Compliance Labels
cat > org-standards/values.yaml <<'EOF'
complianceLabels:
audit-enabled: "true"
pci-dss: "required"
hipaa: "not-applicable"
gdpr-processing: "true"
EOF
Platform teams enforce compliance requirements that auditors verify through labels.
Pattern 3: Cost Attribution
cat > org-standards/templates/_costAttribution.tpl <<'EOF'
{{- define "org-standards.costLabels" -}}
cost-center: {{ .Values.costCenter }}
project: {{ .Values.projectName }}
owning-team: {{ .Values.organization.team }}
{{- end }}
EOF
Finance teams track costs per team/project through labels injected by the library.
Concept 8: Template Inheritance and Overrides
Templates in library charts can be extended or overridden by application charts, creating a flexible inheritance pattern.
Base Probe Template with Override Points
cat > org-standards/templates/_probes-extended.tpl <<'EOF'
{{- define "org-standards.livenessProbe" -}}
livenessProbe:
{{- if .Values.probes.liveness.custom }}
{{- toYaml .Values.probes.liveness.custom | nindent 2 }}
{{- else }}
httpGet:
path: {{ .Values.probes.liveness.path | default "/health" }}
port: {{ .Values.probes.liveness.port | default 8080 }}
initialDelaySeconds: {{ .Values.probes.liveness.initialDelay | default 30 }}
periodSeconds: {{ .Values.probes.liveness.period | default 10 }}
timeoutSeconds: {{ .Values.probes.liveness.timeout | default 5 }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold | default 3 }}
{{- end }}
{{- end }}
EOF
Application Chart Overrides Probe Behavior
cat > my-app/values.yaml <<'EOF'
# Standard org-standards usage
org-standards:
enabled: true
organization:
name: my-company
team: platform
# Override probe behavior for specific app
probes:
liveness:
path: /custom-health-check
initialDelay: 60
failureThreshold: 5
EOF
Output:
$ helm template my-app . | grep -A 10 "livenessProbe:"
livenessProbe:
httpGet:
path: /custom-health-check # Overridden
port: 8080
initialDelaySeconds: 60 # Overridden
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5 # Overridden
The library chart defines structure and defaults, but applications customize behavior through values without modifying templates.
Checkpoint: Advanced Patterns
Quick Reference:
- Enterprise patterns: Security enforcement, compliance labels, cost attribution
- Template inheritance: Use
defaultfunction and conditional logic for overrides - Flexibility: Provide escape hatches (
.customblocks) for complete overrides
Self-Check Questions:
- How can library charts enforce security policies across all deployments?
- What's the pattern for allowing applications to override library defaults?
- Why include compliance labels in library charts instead of application charts?
Answers:
- Define security templates (SecurityContext, resource limits) that all apps include automatically
- Use
defaultfunction and conditional logic:{{ .Values.custom | default .Values.libraryDefault }} - Ensures consistency across all deployments, simplifies auditing, prevents human error
Common Mistakes
Before starting the exercises, be aware of these common pitfalls:
Mistake 1: Forgetting type: library in Chart.yaml
Problem: Creating a library chart without declaring the type
Symptom: Chart can be installed but produces empty release
Fix: Add type: library to Chart.yaml
Mistake 2: Using Library Chart Name Instead of Template Name
Problem: {{- include "org-standards" . }} instead of {{- include "org-standards.labels" . }}
Symptom: Error: "template: no template "org-standards" associated with template"
Fix: Reference the full template name defined in library chart
Mistake 3: Incorrect Dependency Repository Path
Problem: repository: "../org-standards" instead of repository: "file://../org-standards"
Symptom: helm dependency update fails to find chart
Fix: Use file:// prefix for local file paths
Mistake 4: Not Running helm dependency update
Problem: Adding dependency to Chart.yaml but not updating dependencies
Symptom: Template errors: "template "org-standards.labels" not found"
Fix: Run helm dependency update after modifying Chart.yaml dependencies
Mistake 5: Overriding in Wrong Values Section
Problem: Putting overrides at root level instead of under library chart name Symptom: Library chart ignores custom values, uses defaults Fix: Nest overrides under library chart name:
org-standards: # Library chart name
organization:
team: frontend # Override here
Mistake 6: Hardcoding Values in Library Templates
Problem: Defining fixed values in library templates instead of reading from values.yaml
Symptom: Applications can't customize behavior without forking library
Fix: Use {{ .Values.fieldName | default "fallback" }} pattern
Exercises
Exercise 8.1: Create a Library Chart
Create your own library chart with organizational standards.
Steps:
- Create directory:
mkdir -p org-lib/templates - Create
Chart.yamlwithtype: library - Create
values.yamlwith default labels and annotations - Create
_helpers.tplwith common label template
Validation: helm lint org-lib/ should show no errors
Expected outcome:
- Chart.yaml contains
type: library - values.yaml has default organization metadata
- _helpers.tpl defines reusable label template
Exercise 8.2: Verify Library Chart Cannot Be Installed
Attempt to install the library chart and observe Helm's protection.
Steps:
- Run:
helm install test org-lib/ --dry-run=client - Observe the error message
Expected error:
error: chart "org-lib" is a library chart. Library charts are not installable.
Exercise 8.3: Create Organizational Templates
Add security context, resource requests, and probe templates to your library.
Steps:
- Create
_security.tplwith SecurityContext template - Create
_resources.tplwith resource requests/limits - Create
_probes.tplwith liveness/readiness probes
Validation: helm lint org-lib/ should succeed
Exercise 8.4: Create Application Chart with Library Dependency
Build an application chart that declares the library as a dependency.
Steps:
- Create app chart directory:
mkdir -p my-service/templates - Add library dependency in
Chart.yaml - Run:
helm dependency update my-service/
Validation: ls my-service/charts/ should show org-lib
Exercise 8.5: Use include to Pull Library Templates
Create a deployment that uses library templates.
Steps:
- Create
templates/deployment.yamlin application chart - Use
include "org-lib.labels" .for labels - Use
include "org-lib.livenessProbe" .for probes - Run:
helm template my-service .
Validation: Template output includes labels and probes from library
Exercise 8.6: Override Library Defaults
Modify application values to override library probe defaults.
Steps:
- Add probe customization to
values.yaml - Modify
templates/deployment.yamlto use conditional overrides - Run:
helm template my-service .twice:- First with defaults
- Then with custom values
Validation: Second template output uses custom probe paths/timings
Try With AI
Part 1: Design Library Chart Structure
Ask AI: "I have 5 microservices that all need the same Kubernetes labels (organization, team, cost-center), security context (runAsNonRoot, readOnlyRootFilesystem), and health check probes. I want to avoid repeating this in each service's chart. How would I structure a library chart to enforce these standards across all services?"
Part 2: Evaluate the Recommendation
Review AI's response. Ask yourself:
- Does the recommendation include
type: libraryin Chart.yaml? - Does it separate reusable templates (helpers) from application logic?
- Can all 5 services consume this single library without modification?
Part 3: Request Implementation Guidance
Tell AI: "I need the library to provide templates for common labels, security context, and probes. The application charts should be able to override the probe paths (some use /health, others use /api/health-check). Walk me through how to structure the template conditionals so apps can override without duplicating code."
Part 4: Test the Pattern
Ask AI: "Show me how an application chart would declare this library as a dependency and use the library's label template. I want to see the Chart.yaml, values.yaml, and a sample deployment.yaml that pulls in the library templates."
Part 5: Validate the Approach
Ask yourself:
- Does the application chart dependency declaration match library chart naming?
- Can I see which values override organizational defaults?
- Is the
includesyntax correct for pulling templates from dependency charts? - Would this pattern scale to 10+ applications without duplication?