While Helm provides a vast ecosystem of pre-built Charts for popular applications, there are times when you need to deploy custom applications or tailor existing ones beyond their default configurations. Creating your own Helm Chart allows you to define, package, and manage your Kubernetes applications with precision and consistency. In this section, we'll walk through the process of creating a custom Helm Chart, customizing its templates, and deploying it to your Kubernetes cluster.
1. Creating a Helm Chart
Helm makes it easy to scaffold a new Chart with the helm create
command. This command generates a directory structure with all the necessary files and directories to get you started.
helm create my-app
This command creates a new directory called my-app
with the following structure:
my-app/
├── Chart.yaml # Metadata about the Chart (name, version, etc.)
├── values.yaml # Default configuration values
├── charts/ # Dependency Charts
├── templates/ # Kubernetes resource templates
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl
│ └── ... # Other template files
└── .helmignore # Patterns to ignore when packaging the Chart
Key Files and Directories:
- Chart.yaml: Contains metadata about your Chart, such as its name, version, and description.
- values.yaml: Holds the default configuration values for your Chart. Users can override these values during installation.
- templates/: Contains Kubernetes manifest templates that Helm uses to generate the final resource definitions.
- charts/: Directory for Chart dependencies. If your application relies on other Charts, they can be placed here.
- .helmignore: Specifies files and directories to exclude when packaging the Chart.
2. Customizing the Templates
The generated templates are generic and need to be customized to fit your application's requirements. Helm uses the Go templating language, which allows you to inject dynamic values and logic into your Kubernetes manifests.
Example: Customizing deployment.yaml
Let's customize the deployment.yaml
template to better suit a simple web application.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
livenessProbe:
httpGet:
path: /
port: {{ .Values.service.port }}
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: {{ .Values.service.port }}
initialDelaySeconds: 5
periodSeconds: 10
Key Customizations:
-
Metadata Naming: Uses helper templates like
{{ include "my-app.fullname" . }}
to generate consistent and unique names. -
Replica Count: Configures the number of pod replicas based on
values.yaml
. -
Image Configuration: Sets the container image repository, tag, and pull policy from
values.yaml
. - Probes: Defines liveness and readiness probes to ensure the application is running correctly.
Example: Customizing service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
protocol: TCP
name: http
selector:
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
Key Customizations:
-
Service Type and Ports: Configures the service type (e.g.,
ClusterIP
,NodePort
,LoadBalancer
) and ports based onvalues.yaml
. - Selectors: Ensures the Service targets the correct Pods using labels.
3. Defining Default Values
The values.yaml
file holds the default configuration values for your Chart. Users can override these values during installation or upgrade to customize the deployment.
Example values.yaml
:
# Default values for my-app.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 2
image:
repository: nginx
tag: stable
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 80
ingress:
enabled: false
annotations: {}
hosts:
- host: chart-example.local
paths: []
tls: []
resources: {}
Customizing Values:
- replicaCount: Number of pod replicas.
- image: Container image settings.
- service: Service type and port configurations.
- ingress: Ingress settings for external access.
- resources: Resource requests and limits for containers.
4. Packaging and Deploying Your Helm Chart
Once you've customized your Chart, you can package it and deploy it to your Kubernetes cluster.
a. Packaging the Chart
Packaging your Chart creates a .tgz
archive that can be shared or stored in a Helm repository.
helm package my-app
This command generates a file like my-app-0.1.0.tgz
in your current directory.
b. Installing the Custom Chart
You can install your packaged Chart using the helm install
command. If you haven't packaged it, you can also install directly from the Chart directory.
Installing from the Packaged Chart:
helm install my-app-release ./my-app-0.1.0.tgz
Installing Directly from the Chart Directory:
helm install my-app-release ./my-app
Parameters:
-
my-app-release
: The name of your Helm release. -
./my-app
or./my-app-0.1.0.tgz
: Path to your Chart directory or packaged Chart.
c. Verifying the Installation
After installation, verify that your application is running correctly.
helm list
helm status my-app-release
These commands will show the status of your release and the resources created in your Kubernetes cluster.
d. Updating the Chart
If you make changes to your Chart, you can upgrade the release to apply the updates.
-
Update the Chart Files: Modify the templates or
values.yaml
as needed. - Upgrade the Release:
helm upgrade my-app-release ./my-app
If you have packaged the Chart, specify the .tgz
file instead:
helm upgrade my-app-release ./my-app-0.1.0.tgz
e. Sharing Your Chart
To share your custom Chart with others or use it across multiple projects, consider hosting it in a Helm repository. You can use public repositories like Artifact Hub or set up your own private repository.
Adding a Repository:
helm repo add my-repo https://my-repo-url.com/charts
Pushing Your Chart to a Repository:
You can use tools like ChartMuseum to host your own Helm repository or utilize cloud storage solutions.
5. Best Practices for Creating Helm Charts
Creating effective Helm Charts involves following best practices to ensure your Charts are maintainable, reusable, and user-friendly.
-
Use Meaningful Defaults: Set sensible default values in
values.yaml
to make your Chart easy to use out of the box. -
Template Helpers: Utilize helper templates (
_helpers.tpl
) to avoid repetition and maintain consistency across your templates. -
Versioning: Follow semantic versioning in
Chart.yaml
to manage changes and compatibility. -
Documentation: Provide clear documentation within your Chart, including comments in
values.yaml
and aREADME.md
file. -
Validation: Implement schema validation for your
values.yaml
to catch configuration errors early. - Modularity: Break down complex applications into sub-Charts or use dependencies to promote reusability.
Example: Using Helper Templates
In templates/_helpers.tpl
:
{{/*
Return the name of the Chart.
*/}}
{{- define "my-app.name" -}}
{{ .Chart.Name }}
{{- end }}
{{/*
Return the full name of the release.
*/}}
{{- define "my-app.fullname" -}}
{{ .Release.Name }}-{{ .Chart.Name }}
{{- end }}
{{/*
Return common labels.
*/}}
{{- define "my-app.labels" -}}
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
These helpers streamline the naming and labeling process across your templates, ensuring consistency and reducing duplication.
6. Testing Your Helm Chart
Before deploying your Chart to a production environment, it's essential to test it to ensure it behaves as expected.
a. Linting the Chart
Helm provides a linting tool to check your Chart for common issues.
helm lint ./my-app
This command will analyze your Chart files and report any warnings or errors that need to be addressed.
b. Dry-Run Installation
Perform a dry-run installation to see what resources Helm would create without actually deploying them.
helm install my-app-release ./my-app --dry-run --debug
This is useful for verifying that your templates render correctly with the given values.
c. Unit Testing with Helm Tests
Helm allows you to define tests within your Chart to verify the deployment's functionality.
-
Create Test Templates: Add test pods in the
templates/tests/
directory.
templates/tests/test-connection.yaml:
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "my-app.fullname" . }}-test-connection"
labels:
{{- include "my-app.labels" . | nindent 4 }}
helm.sh/hook: test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
- Run the Tests:
helm test my-app-release
Helm will execute the test pods and report the results, helping you verify that your application is functioning as intended.
7. Conclusion
Creating your own Helm Charts empowers you to manage Kubernetes applications with greater control and flexibility. By defining reusable templates, setting configurable values, and adhering to best practices, you can streamline your deployment processes and ensure consistency across environments.
Key Takeaways:
-
Scaffolding: Use
helm create
to generate the basic structure of a Chart. -
Customization: Tailor the templates and
values.yaml
to fit your application's needs. - Packaging and Deployment: Package your Chart for distribution and deploy it using Helm commands.
- Best Practices: Follow guidelines to create maintainable and reusable Charts.
- Testing: Validate your Charts with linting and Helm tests to ensure reliability.
In the next section, we'll explore Helm repositories in more detail, including how to add, manage, and leverage them to access a wide range of Charts for your Kubernetes deployments.
Top comments (0)