No prior knowledge of Helm is required.
- Time to completion
-
45-60m
- Prerequisites
-
It is assumed the reader has at least a basic understanding of the following topics and technologies:
-
YAML
-
Docker/OCI images and containers
-
Application deployments in Kubernetes
-
- Software and tools required
This tutorial was written and tested on CRC (aka OpenShift Local), local OKD/OpenShift cluster provided by Red Hat for developer testing, and thus all URL’s in the tutorial will use the wildcard domain *.app-crc.testing
; however any Kubernetes compatible cluster will suffice for running the tutorial, as long as internet access is available to pull el-CICD Chart and the test images. You will need to adjust your endpoint URL’s to your own cluster’s wildcard if not using CRC.
The tutorial will mostly focus on deploying the Apache Web Server using Red Hat’s official httpd image and will not deploy Secrets, so that whether you are deploying on vanilla Kubernetes or a more security conscious cluster like OpenShift this tutorial will run smoothly with only basic developer permissions required.
1. Overview
Helm is an excellent package management tool for Kubernetes. Deploying or removing an application on and off a Kubernetes cluster is handled very well by Helm.
Where Helm falls short is when it comes to templating Kubernetes manifests. Creating Helm templates can be difficult to learn let alone master.
This tutorial will demonstrate how the el-CICD Chart can make defining Kubernetes manifests much easier for all involved while still taking advantage of Helm’s package management functionality.
el-CICD Chart embeds its templates inside Helm values.yaml file(s), and writing Helm templates are not required when using el-CICD Chart. In order to avoid confusion with the word "template", el-CICD Chart values.yaml file(s) will be referred to as deployment definitions. |
1.1. Starter Helm chart
The following is the starter chart created by Helm when running helm create my-new-chart
along with its issues:
Service
apiVersion: v1
kind: Service
metadata:
name: {{ include "my-new-chart.fullname" . }}
labels:
{{- include "my-new-chart.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "my-new-chart.selectorLabels" . | nindent 4 }}
Deployment
kind: Deployment
metadata:
name: {{ include "my-new-chart.fullname" . }}
labels:
{{- include "my-new-chart.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-new-chart.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "my-new-chart.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "my-new-chart.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
Ingress
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "my-new-chart.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "my-new-chart.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
values.yaml
# Default values for my-new-chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}
- Verbose
-
The files are verbose, and assume a good understanding of the manifests required to deploy an application on Kubernetes.
- Obtuse
-
Go Template syntax (everything between the double-brackets) and the supporting Sprig library is not very user friendly, but it’s required knowledge to understand and modify Helm templates.
Values used to render the chart are defined in files separate from Helm templates, and structured far differently, which can make understanding what will rendered difficult.
- No configuration management
-
Configuration management is not supported by Helm. Defining charts that can adapts across even a narrowly defined set of different deployments can be challenging.
- It’s code
-
Helm templates are code; it constitutes a separate application. This means Helm charts need to be tested in isolation from the application they are meant to deploy. Helm charts acknowledge this by supporting a built-in testing framework.
1.2. el-CICD Chart
el-CICD Chart was created with the intention of leveraging all the package management goodness Helm has to offer while making defining deployments easier. In particular, the following design goals were set:
- Helm centric
-
No extra scripts or special commands for standard Helm deployments or templating should be needed. el-CICD Chart should be able to be used anywhere Helm can be used, and alongside any other Helm chart either as the main chart or a subchart.
- Easier
-
Defining deployments should be done using plain YAML documents, with no extra language skills or libraries.
- More concise
-
Support the DRY (Don’t Repeat Yourself) Principle aggressively to significantly reduce the amount of copying and pasting of boilerplate YAML. For application developers, support reasonable defaults so deployment definitions are confined as much as possible to the application’s needs.
- Support configuration management
-
Defining different configurations for the same set of deployment manifests (e.g. per locale, region, and/or development environment) should be easy and directly supported.
- Extensible
-
Kubernetes is very extensible, as the abundance of Custom Resource Definitions illustrates. el-CICD Chart should be able to render CRD’s out-of-the-box without requiring new Helm template code.
The following tutorial will demonstrate how el-CICD Chart met each of these goals.
2. Tutorial
This tutorial will demonstrate how el-CICD Chart can make defining and defining Kubernetes deployment definitions easier, more readable, and more concise as well as directly supporting configuration management.
All commands used below will refer to kubectl , but if on OpenShift oc will work just as well.
|
2.1. Add and update the el-CICD Chart repository
Add and update the el-CICD Chart repository. This will pull the chart from the GitHub repository to your local machine for use.
$ helm repo add elcicd-charts https://elcicd.github.io/el-CICD-deploy/charts/
$ helm repo update
Deploying Helm charts from OCI repositories is better, but GitHub currently makes is easy to serve Helm charts from GitHub pages |
+ Output::
"elcicd-charts" has been added to your repositories
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "elcicd-charts" chart repository
Update Complete. ⎈Happy Helming!⎈
2.2. el-CICD Chart Templates
The el-CICD Chart aims to define basic Kubernetes resources for application deployments out-of-the-box and provide as many reasonable defaults as possible to reduce the amount of boilerplate required by the end user. The el-CICD Chart also aims to do away with the need to write Helm (Go) templates, and instead follows the Helm requirement for values.yaml files be plain YAML.
The example below is purposefully contrived to be more complicated than necessary. In this case the Ingress will be communicating with the Service over port 8081, and the Service will forward incoming requests to Apache Web Server container over the more standard port 8080. The next part of the tutorial will make it clear why we are making this more complicated than necessary. |
Create and save the following file as elcicd-demo-1.yaml
1
2
3
4
5
6
7
8
9
10
11
elCicdTemplates: (1)
- templateName: deployment (2)
image: registry.redhat.io/rhel8/httpd-24
- templateName: service (3)
port: 8081 (4)
targetPort: 8080 (5)
- templateName: ingress (6)
host: httpd-$<HELM_RELEASE_NAMESPACE>.apps-crc.testing (7)
port: 8081 (8)
1 | All el-CICD Chart templates are defined in a list called elCicdTemplates .
The suffix is meaningless and only serves to be keep the lists unique from Helm’s perspective. el-CICD Chart will automatically merge the lists into a single, unified list. |
||
2 | By convention, there is a one-to-one relation between el-CICD Chart templates and the Kubernetes resources they render.
|
||
3 | Helper attributes are el-CICD Chart template top level keys; e.g. some standard el-CICD attributes every template has:
|
||
4 | $<HELM_RELEASE_NAMESPACE> references a built-in el-CICD Chart variable.
|
Tutorial steps
-
Install the
elcicd-chart-demo
release in theelcicd-chart-demo
namespace using the el-CICD Chart:$ helm upgrade --install --atomic -n elcicd-chart-demo --create-namespace -f elcicd-demo-1.yaml elcicd-chart-demo elcicd-charts/elcicd-chart
- Output
-
Release "elcicd-chart-demo" does not exist. Installing it now. NAME: elcicd-chart-demo LAST DEPLOYED: Tue Jul 16 16:47:02 2024 NAMESPACE: elcicd-chart-demo STATUS: deployed REVISION: 1 TEST SUITE: None
-
View the manifests that generated by el-CICD Chart from the
helm upgrade --install
command:$ helm get manifest -n elcicd-chart-demo elcicd-chart-demo
Output
--- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: selector: elcicd.io/selector: elcicd-chart-demo ports: - name: elcicd-chart-demo-port port: 8081 targetPort: 8080 protocol: TCP # Rendered el-CICD Chart Template -> "service" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: revisionHistoryLimit: 0 selector: matchExpressions: - key: elcicd.io/selector operator: Exists matchLabels: elcicd.io/selector: elcicd-chart-demo template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: containers: - name: elcicd-chart-demo image: registry.redhat.io/rhel8/httpd-24 imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault # Rendered el-CICD Chart Template -> "deployment" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.allow-http: "false" labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: rules: - host: httpd-elcicd-chart-demo.apps-crc.testing http: paths: - path: / pathType: Prefix backend: service: name: elcicd-chart-demo port: number: 8081 tls: - secretName: # Rendered el-CICD Chart Template -> "ingress" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml # Profiles: []
-
View the running
elcicd-chart-demo
resources in the cluster:$ kubectl get -n elcicd-chart-demo -l elcicd.io/selector deploy,rs,pod,cm,service,ingress
- Output
-
NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/elcicd-chart-demo 1/1 1 1 3m29s NAME DESIRED CURRENT READY AGE replicaset.apps/elcicd-chart-demo-6c6fd69cb7 1 1 1 3m29s NAME READY STATUS RESTARTS AGE pod/elcicd-chart-demo-6c6fd69cb7-xtk5k 1/1 Running 0 3m29s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/elcicd-chart-demo ClusterIP 10.217.5.104 <none> 8081/TCP 3m29s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/elcicd-chart-demo <none> httpd-elcicd-chart-demo.apps-crc.testing router-default.apps-crc.testing 80, 443 3m29s
-
Get the value of the host from the Ingress, and verify the Apache Web Server is reachable:
$ kubectl get ingress -n elcicd-chart-demo --no-headers -o custom-columns=:.spec.rules[*].host
- Output
-
httpd-elcicd-chart-demo.apps-crc.testing
Open your browser and go to https://httpd-elcicd-chart-demo.apps-crc.testing.
If not using CRC, run the kubectl get
command above to get the correct host.
-
Uninstall the chart.
$ helm uninstall -n elcicd-chart-demo elcicd-chart-demo
- Output
-
release "elcicd-chart-demo" uninstalled
2.3. Compound el-CICD Chart Templates
In el-CICD Chart Templates, we demonstrated the conciseness and modularity el-CICD Chart templates. We will now show how to combine multiple, related el-CICD Chart templates into a single compound template for even more concise deployment definitions.
Any el-CICD Chart built-in template can be compounded into a single template definition as long as any common helper attributes refer to the same, basic data. |
Create and save the following file as elcicd-demo-2.yaml
1
2
3
4
5
6
elCicdTemplates:
- templateNames: [deployment, service, ingress] (1)
image: registry.redhat.io/rhel8/httpd-24
host: httpd-$<HELM_RELEASE_NAMESPACE>.apps-crc.testing
port: 8081 (2)
targetPort: 8080 (3)
YAML is a superset of JSON; thus YAML will interpret both
as lists. |
1 | Compound templates are defined as a list under the templateNames attribute, versus templateName for a single template. |
2 | In compound templates, all helper attributes are shared among the el-CICD templates.
|
In the first part of the tutorial, el-CICD Chart Templates, we promised to explain why we contrived a different port and target port, and it was to better demonstrate how shared helper attributes would behave in compound templates. |
Tutorial steps
-
Install the
elcicd-chart-demo
release in theelcicd-chart-demo
namespace using the el-CICD Chart:$ helm upgrade --install --atomic -n elcicd-chart-demo --create-namespace -f elcicd-demo-2.yaml elcicd-chart-demo elcicd-charts/elcicd-chart
- Output
-
Release "elcicd-chart-demo" does not exist. Installing it now. NAME: elcicd-chart-demo LAST DEPLOYED: Tue Jul 16 16:47:02 2024 NAMESPACE: elcicd-chart-demo STATUS: deployed REVISION: 1 TEST SUITE: None
-
View the manifests that generated by el-CICD Chart from the
helm upgrade --install
command:$ helm get manifest -n elcicd-chart-demo elcicd-chart-demo
Output
--- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: selector: elcicd.io/selector: elcicd-chart-demo ports: - name: elcicd-chart-demo-port port: 8081 targetPort: 8080 protocol: TCP # Rendered el-CICD Chart Template -> "service" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: revisionHistoryLimit: 0 selector: matchExpressions: - key: elcicd.io/selector operator: Exists matchLabels: elcicd.io/selector: elcicd-chart-demo template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: containers: - name: elcicd-chart-demo image: registry.redhat.io/rhel8/httpd-24 imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault # Rendered el-CICD Chart Template -> "deployment" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.allow-http: "false" labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: rules: - host: httpd-elcicd-chart-demo.apps-crc.testing http: paths: - path: / pathType: Prefix backend: service: name: elcicd-chart-demo port: number: 8081 tls: - secretName: # Rendered el-CICD Chart Template -> "ingress" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml # Profiles: []
-
View the running
elcicd-chart-demo
resources in the cluster:$ kubectl get -n elcicd-chart-demo -l elcicd.io/selector deploy,rs,pod,cm,service,ingress
- Output
-
NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/elcicd-chart-demo 1/1 1 1 4m55s NAME DESIRED CURRENT READY AGE replicaset.apps/elcicd-chart-demo-6c6fd69cb7 1 1 1 4m55s NAME READY STATUS RESTARTS AGE pod/elcicd-chart-demo-6c6fd69cb7-xtk5k 1/1 Running 0 4m55s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/elcicd-chart-demo ClusterIP 10.217.5.104 <none> 8081/TCP 4m55s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/elcicd-chart-demo <none> httpd-elcicd-chart-demo.apps-crc.testing router-default.apps-crc.testing 80, 443 4m55s
-
Get the value of the host from the Ingress, and verify the Apache Web Server is reachable:
$ kubectl get ingress -n elcicd-chart-demo --no-headers -o custom-columns=:.spec.rules[*].host
- Output
-
httpd-elcicd-chart-demo.apps-crc.testing
Open your browser and go to https://httpd-elcicd-chart-demo.apps-crc.testing.
If not using CRC, run the kubectl get
command above to get the correct host.
-
Uninstall the chart.
$ helm uninstall -n elcicd-chart-demo elcicd-chart-demo
- Output
-
release "elcicd-chart-demo" uninstalled
2.4. User-defined Variables
Both el-CICD Chart Templates and Compound el-CICD Chart Templates made use of el-CICD Chart’s built-in variables to help define their host domain. This part of the tutorial will focus on user-defined variables.
A fundamental goal of el-CICD Chart is to eliminate the need for Helm templates and instead let the user define their deployment manifests as plain YAML documents. Another goal is to remove the need for copying and pasting boilerplate YAML as much as possible when defining manifests. User-defined el-CICD Chart variables support these goals.
Create and save the following file as elcicd-demo-3.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
elCicdDefs: (1)
INDEX_HTML_NAME: index.html
DEFAULT_PAGE_CONTENT: <h1>Howdy from $<OBJ_NAME> in release $<HELM_RELEASE_NAME>!<h1>
PAGE_CONTENT: $<DEFAULT_PAGE_CONTENT>
HTML_PAGE: <!DOCTYPE html><html><body>$<PAGE_CONTENT></body></html>
INDEX_HTML_NAME: index.html
PAGE_CONTENT: <h1>Howdy from $<OBJ_NAME> in release $<HELM_RELEASE_NAME>!<h1>
HTML_PAGE: |-
<!DOCTYPE html>
<html>
<body>
<h1>$<PAGE_CONTENT></h1>
</body>
</html>
elCicdTemplates:
- templateNames: [deployment, service, ingress]
image: registry.redhat.io/rhel8/httpd-24
host: httpd-$<NAME_SPACE>.apps-crc.testing
projectedVolumes: (2)
- name: $<HELM_RELEASE_NAME> (3)
mountPath: /var/www/html/
configMaps:
$<INDEX_HTML_NAME>: {}
- templateName: configMap
objName: $<INDEX_HTML_NAME> (4)
data:
$<OBJ_NAME>: $<HTML_PAGE> (5)
1 | All el-CICD Chart variables are defined under elCicdDefs maps.
|
2 | projectedVolumes is a helper attribute for generating projectedVolumes.
|
3 | $<HELM_RELEASE_NAME> is another built-in el-CICD Chart variable that corresponds to .Release.Name in a Helm template. |
4 | objName is a helper attribute that will render as the name of a resource or resources; i.e.metadata.name .
|
Tutorial steps
-
Install the
elcicd-chart-demo
release in theelcicd-chart-demo
namespace using the el-CICD Chart:$ helm upgrade --install --atomic -n elcicd-chart-demo --create-namespace -f elcicd-demo-3.yaml elcicd-chart-demo elcicd-charts/elcicd-chart
- Output
-
Release "elcicd-chart-demo" does not exist. Installing it now. NAME: elcicd-chart-demo LAST DEPLOYED: Tue Jul 16 16:47:02 2024 NAMESPACE: elcicd-chart-demo STATUS: deployed REVISION: 1 TEST SUITE: None
-
View the manifests that generated by el-CICD Chart from the
helm upgrade --install
command:$ helm get manifest -n elcicd-chart-demo elcicd-chart-demo
Output
--- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: index.html helm.sh/chart: elcicd-chart-0.1.0 name: index.html namespace: elcicd-chart-demo data: index.html: |- <!DOCTYPE html> <html> <body> <h1><h1>Howdy from index.html in release elcicd-chart-demo!<h1></h1> </body> </html> # Rendered el-CICD Chart Template -> "configMap" index.html --- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: selector: elcicd.io/selector: elcicd-chart-demo ports: - name: elcicd-chart-demo-port port: 8080 protocol: TCP # Rendered el-CICD Chart Template -> "service" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: revisionHistoryLimit: 0 selector: matchExpressions: - key: elcicd.io/selector operator: Exists matchLabels: elcicd.io/selector: elcicd-chart-demo template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: containers: - name: elcicd-chart-demo image: registry.redhat.io/rhel8/httpd-24 imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL volumeMounts: - mountPath: /var/www/html/ name: elcicd-chart-demo readOnly: false imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: elcicd-chart-demo projected: sources: - configMap: name: index.html # Rendered el-CICD Chart Template -> "deployment" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.allow-http: "false" labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: rules: - host: httpd-elcicd-chart-demo.apps-crc.testing http: paths: - path: / pathType: Prefix backend: service: name: elcicd-chart-demo port: number: 8080 tls: - secretName: # Rendered el-CICD Chart Template -> "ingress" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml # Profiles: []
-
View the running
elcicd-chart-demo
resources in the cluster:$ kubectl get -n elcicd-chart-demo -l elcicd.io/selector deploy,rs,pod,cm,service,ingress
- Output
-
NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/elcicd-chart-demo 1/1 1 1 3m17s NAME DESIRED CURRENT READY AGE replicaset.apps/elcicd-chart-demo-878f4b9d5 1 1 1 3m17s NAME READY STATUS RESTARTS AGE pod/elcicd-chart-demo-878f4b9d5-x88mg 1/1 Running 0 3m17s NAME DATA AGE configmap/index.html 1 3m17s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/elcicd-chart-demo ClusterIP 10.217.5.87 <none> 8080/TCP 3m17s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/elcicd-chart-demo <none> httpd-elcicd-chart-demo.apps-crc.testing router-default.apps-crc.testing 80, 443 3m17s
-
Get the value of the host from the Ingress, and verify the Apache Web Server is reachable:
$ kubectl get ingress -n elcicd-chart-demo --no-headers -o custom-columns=:.spec.rules[*].host
- Output
-
httpd-elcicd-chart-demo.apps-crc.testing
Open your browser and go to https://httpd-elcicd-chart-demo.apps-crc.testing.
If not using CRC, run the kubectl get
command above to get the correct host.
-
Uninstall the chart.
$ helm uninstall -n elcicd-chart-demo elcicd-chart-demo
- Output
-
release "elcicd-chart-demo" uninstalled
2.5. Deployment Profiles
In User-defined Variables, we demonstrated how to define and reference your own variables. In this part of the tutorial you’ll learn about deployment profiles. While the previous parts of the tutorial have focused on el-CICD Chart’s strengths with regards to templating, readability, and conciseness, it’s the deployment profiles that give el-CICD Chart its true power. This feature makes it much, much easier for users to manage the same, basic deployment definitions across numerous environments with minimal configuration changes.
- Example use cases for deployment profiles
-
-
The software development lifecycle (SDLC).
Development, test, and production are rarely configured the same way.
-
Different geographical jurisdictions
Regulatory and/or language requirements almost always differ between geographical jurisdictions.
-
High availability and persistence options
One or more services of an an application need to be deployed as highly available and/or data persistence options, either in production or for testing purposes.
-
Deployment profiles are most useful whenever a resource needs to be deployed differently depending on the situation or environment.
Create and save the following file as elcicd-demo-4.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
elCicdDefs:
MULTI_LINGUAL_PROFILE: MULTI_LINGUAL
INDEX_HTML_NAME: index.html
DEFAULT_PAGE_CONTENT: <h1>Howdy from $<OBJ_NAME> in release $<HELM_RELEASE_NAME>!<h1>
PAGE_CONTENT: $<DEFAULT_PAGE_CONTENT>
HTML_PAGE: <!DOCTYPE html><html><body>$<PAGE_CONTENT></body></html>
elCicdDefs-$<MULTI_LINGUAL_PROFILE>: (1)
PAGE_CONTENT: <h1><a href="$<ENGLISH>">English</a> <a href="$<ESPANOL>">Español</a></h1>
ENGLISH: english.html
ESPANOL: espanol.html
elCicdTemplates:
- templateNames: [deployment, service, ingress]
image: registry.redhat.io/rhel8/httpd-24
host: httpd-$<NAME_SPACE>.apps-crc.testing
projectedVolumes:
- name: $<HELM_RELEASE_NAME>
mountPath: /var/www/html/
configMaps:
$<INDEX_HTML_NAME>: {}
$<ENGLISH>: {} (2)
$<ESPANOL>: {}
- templateName: configMap
objName: $<INDEX_HTML_NAME>
data:
$<OBJ_NAME>: $<HTML_PAGE>
- templateName: configMap
objNames: (3)
- $<ENGLISH>
- $<ESPANOL>
mustHaveAnyProfile:
- $<MULTI_LINGUAL_PROFILE> (4)
elCicdDefs-$<ENGLISH>: (5)
PAGE_CONTENT: $<DEFAULT_PAGE_CONTENT>
elCicdDefs-$<ESPANOL>:
PAGE_CONTENT: <h1>¡Hola desde $<OBJ_NAME> en el lanzamiento $<HELM_RELEASE_NAME>!<h1>
data:
$<OBJ_NAME>: $<HTML_PAGE>
1 | Deployment profiles are defined whenever an el-CICD Chart template and/or elCicdDefs variable map is marked for them.
|
||
2 | If keys in maps or values in maps or lists evaluate to empty or null values after processing, they will be removed.
|
||
3 | objNames is one of two el-CICD Chart matrices (namespaces being the other).
|
||
4 | mustHaveAnyProfile is a template discriminator
|
||
5 | el-Cicd Chart variables maps can be defined for a specific template.
|
2.5.1. Deploy the httpd server without an active deployment profile
Deploying without a deployment profile with the above deployment definition will look identical to the User-defined Variables demonstration in every way. The lack of a proper active profile in this deployment means all the additions made to the deployment definition in elcicd-demo-4.yaml
compared to elcicd-demo-3.yaml
will be ignored.
Tutorial steps
-
Install the
elcicd-chart-demo
release in theelcicd-chart-demo
namespace using the el-CICD Chart:$ helm upgrade --install --atomic -n elcicd-chart-demo --create-namespace -f elcicd-demo-4.yaml elcicd-chart-demo elcicd-charts/elcicd-chart
- Output
-
Release "elcicd-chart-demo" does not exist. Installing it now. NAME: elcicd-chart-demo LAST DEPLOYED: Tue Jul 16 16:47:02 2024 NAMESPACE: elcicd-chart-demo STATUS: deployed REVISION: 1 TEST SUITE: None
-
View the manifests that generated by el-CICD Chart from the
helm upgrade --install
command:$ helm get manifest -n elcicd-chart-demo elcicd-chart-demo
Output
--- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: index.html helm.sh/chart: elcicd-chart-0.1.0 name: index.html namespace: elcicd-chart-demo data: index.html: <!DOCTYPE html><html><body><h1>Howdy from index.html in release elcicd-chart-demo!<h1></body></html> # Rendered el-CICD Chart Template -> "configMap" index.html --- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: selector: elcicd.io/selector: elcicd-chart-demo ports: - name: elcicd-chart-demo-port port: 8080 protocol: TCP # Rendered el-CICD Chart Template -> "service" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: revisionHistoryLimit: 0 selector: matchExpressions: - key: elcicd.io/selector operator: Exists matchLabels: elcicd.io/selector: elcicd-chart-demo template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: containers: - name: elcicd-chart-demo image: registry.redhat.io/rhel8/httpd-24 imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL volumeMounts: - mountPath: /var/www/html/ name: elcicd-chart-demo readOnly: false imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: elcicd-chart-demo projected: sources: - configMap: name: index.html # Rendered el-CICD Chart Template -> "deployment" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.allow-http: "false" labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: rules: - host: httpd-elcicd-chart-demo.apps-crc.testing http: paths: - path: / pathType: Prefix backend: service: name: elcicd-chart-demo port: number: 8080 tls: - secretName: # Rendered el-CICD Chart Template -> "ingress" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml # Profiles: [] # EXCLUDED BY PROFILES: configMap -> objNames: [$<ENGLISH> $<ESPANOL>]
-
View the running
elcicd-chart-demo
resources in the cluster:$ kubectl get -n elcicd-chart-demo -l elcicd.io/selector deploy,rs,pod,cm,service,ingress
- Output
-
NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/elcicd-chart-demo 1/1 1 1 3m49s NAME DESIRED CURRENT READY AGE replicaset.apps/elcicd-chart-demo-878f4b9d5 1 1 1 3m49s NAME READY STATUS RESTARTS AGE pod/elcicd-chart-demo-878f4b9d5-ng28g 1/1 Running 0 3m49s NAME DATA AGE configmap/index.html 1 3m49s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/elcicd-chart-demo ClusterIP 10.217.5.142 <none> 8080/TCP 3m49s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/elcicd-chart-demo <none> httpd-elcicd-chart-demo.apps-crc.testing router-default.apps-crc.testing 80, 443 3m49s
-
Get the value of the host from the Ingress, and verify the Apache Web Server is reachable:
$ kubectl get ingress -n elcicd-chart-demo --no-headers -o custom-columns=:.spec.rules[*].host
- Output
-
httpd-elcicd-chart-demo.apps-crc.testing
Open your browser and go to https://httpd-elcicd-chart-demo.apps-crc.testing.
If not using CRC, run the kubectl get
command above to get the correct host.
-
Uninstall the chart.
$ helm uninstall -n elcicd-chart-demo elcicd-chart-demo
- Output
-
release "elcicd-chart-demo" uninstalled
2.5.2. Install the httpd server with the MULTI_LINGUAL
deployment profile
el-CICD Chart deployment profiles are defined in elCicdProfiles
as a list. The helm update --install
command is modified to apply deployment profile --set elCicdProfiles='{MULTI_LINGUAL}'
clause. If more than one deployment profile is specified, the order of precedence is from least to greatest in determining the values of variables; e.g. given elCicdProfiles={FOO,BAR}
, all conflicting variable definitions defined in the BAR
profile would take precedence over FOO
.
This part of the demonstration will change the server’s home page to display a pair of links that will take you to either English or Spanish versions of the "Howdy!" message.
Tutorial steps
-
Install the
elcicd-chart-demo
release in theelcicd-chart-demo
namespace using the el-CICD Chart:$ helm upgrade --install --atomic -n elcicd-chart-demo --create-namespace --set elCicdProfiles='{MULTI_LINGUAL}' -f elcicd-demo-4.yaml elcicd-chart-demo elcicd-charts/elcicd-chart
- Output
-
Release "elcicd-chart-demo" does not exist. Installing it now. NAME: elcicd-chart-demo LAST DEPLOYED: Tue Jul 16 16:47:02 2024 NAMESPACE: elcicd-chart-demo STATUS: deployed REVISION: 1 TEST SUITE: None
-
View the manifests that generated by el-CICD Chart from the
helm upgrade --install
command:$ helm get manifest -n elcicd-chart-demo elcicd-chart-demo
Output
--- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: index.html helm.sh/chart: elcicd-chart-0.1.0 name: index.html namespace: elcicd-chart-demo data: index.html: <!DOCTYPE html><html><body><h1><a href="english.html">English</a> <a href="espanol.html">Español</a></h1></body></html> # Rendered el-CICD Chart Template -> "configMap" index.html --- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: english.html helm.sh/chart: elcicd-chart-0.1.0 name: english.html namespace: elcicd-chart-demo data: english.html: <!DOCTYPE html><html><body><h1>Howdy from english.html in release elcicd-chart-demo!<h1></body></html> # Rendered el-CICD Chart Template -> "configMap" english.html --- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: espanol.html helm.sh/chart: elcicd-chart-0.1.0 name: espanol.html namespace: elcicd-chart-demo data: espanol.html: <!DOCTYPE html><html><body><h1>¡Hola desde espanol.html en el lanzamiento elcicd-chart-demo!<h1></body></html> # Rendered el-CICD Chart Template -> "configMap" espanol.html --- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: selector: elcicd.io/selector: elcicd-chart-demo ports: - name: elcicd-chart-demo-port port: 8080 protocol: TCP # Rendered el-CICD Chart Template -> "service" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: revisionHistoryLimit: 0 selector: matchExpressions: - key: elcicd.io/selector operator: Exists matchLabels: elcicd.io/selector: elcicd-chart-demo template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: containers: - name: elcicd-chart-demo image: registry.redhat.io/rhel8/httpd-24 imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL volumeMounts: - mountPath: /var/www/html/ name: elcicd-chart-demo readOnly: false imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: elcicd-chart-demo projected: sources: - configMap: name: english.html - configMap: name: espanol.html - configMap: name: index.html # Rendered el-CICD Chart Template -> "deployment" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.allow-http: "false" labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo namespace: elcicd-chart-demo spec: rules: - host: httpd-elcicd-chart-demo.apps-crc.testing http: paths: - path: / pathType: Prefix backend: service: name: elcicd-chart-demo port: number: 8080 tls: - secretName: # Rendered el-CICD Chart Template -> "ingress" elcicd-chart-demo --- # Source: elcicd-chart/templates/render.yaml # Profiles: [MULTI-LINGUAL]
-
View the running
elcicd-chart-demo
resources in the cluster:$ kubectl get -n elcicd-chart-demo -l elcicd.io/selector deploy,rs,pod,cm,service,ingress
- Output
-
NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/elcicd-chart-demo 1/1 1 1 5m23s NAME DESIRED CURRENT READY AGE replicaset.apps/elcicd-chart-demo-58494f8c55 1 1 1 5m23s NAME READY STATUS RESTARTS AGE pod/elcicd-chart-demo-58494f8c55-5tp6x 1/1 Running 0 5m23s NAME DATA AGE configmap/english.html 1 5m23s configmap/espanol.html 1 5m23s configmap/index.html 1 5m23s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/elcicd-chart-demo ClusterIP 10.217.5.97 <none> 8080/TCP 5m23s NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/elcicd-chart-demo <none> httpd-elcicd-chart-demo.apps-crc.testing router-default.apps-crc.testing 80, 443 5m23s
-
Get the value of the host from the Ingress, and verify the Apache Web Server is reachable:
$ kubectl get ingress -n elcicd-chart-demo --no-headers -o custom-columns=:.spec.rules[*].host
- Output
-
httpd-elcicd-chart-demo.apps-crc.testing
Open your browser and go to https://httpd-elcicd-chart-demo.apps-crc.testing.
If not using CRC, run the kubectl get
command above to get the correct host.
-
Uninstall the chart.
$ helm uninstall -n elcicd-chart-demo elcicd-chart-demo
- Output
-
release "elcicd-chart-demo" uninstalled
2.6. Free Form Templates
So far this tutorial has focused on the easy deployments of services using built-in helper el-CICD Chart templates. Unfortunately, because Kubernetes has many dozens of resources, and it is infinitely extensible with Custom Resource Definitions (CRD), creating helper templates for every resource deployable to a Kubernetes cluster is not feasible.
To address this, el-CICD Chart supports templating any arbitrary YAML as an el-CICD Chart template, including Kubernetes resources. Rather than using a named helper template with templateName(s)
, the full YAML of the resource is written under the template
key. While more verbose than their helper template counterparts, they still allow for the use of el-CICD Chart variables, deployment profiles, and matrices; thus, they will still be able to take advantage of the most powerful features of the el-CICD Chart.
- Example use cases for free form templates
-
-
Any default Kubernetes resource without a corresponding el-CICD Chart helper template
-
Custom Resource Definitions
Many Kubernetes add-ons have CRD’s and will therefore not have corresponding el-CICD Chart helper templates.
-
General YAML templating
Some use cases involve YAML that does not represent a Kubernetes object directly.
-
Third party chart integration
Converting an already working Helm chart into a el-CICD Chart compatible chart may not be feasible and/or is probably not worth the time. el-CICD Chart can be used as a general YAML templating tool to generate values.yaml files for other Helm charts via Helm post-renderering.
-
Dynamic Kustomizations
kustomization.yaml files only support statically declared data. If you need a more dynamic solution, kustomization.yaml files can be templated using el-CICD Chart, and
kustomize
applied during Helm post-rendering.
-
-
Create and save the following file as elcicd-demo-5.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
elCicdDefs:
ENGLISH_JOB: job-en
ESPANOL_JOB: job-es
OBJ_NAMES:
- $<ENGLISH_JOB>
- $<ESPANOL_JOB>
ENV:
- name: WELCOME_MSG
value: $<WELCOME_MSG>
JOB_NAMESPACE_2: elcicd-chart-demo-2
NAMESPACES: (1)
- $<HELM_RELEASE_NAMESPACE>
- $<JOB_NAMESPACE_2>
COMMAND: ["bash", "-c"]
JOB_SCRIPT:
- for COUNTER in {1..5};
do
echo ${WELCOME_MSG};
done
elCicdDefs-$<ENGLISH_JOB>:
WELCOME_MSG: 'Howdy from $<OBJ_NAME> in release $<HELM_RELEASE_NAME>!'
elCicdDefs-$<ESPANOL_JOB>:
WELCOME_MSG: '¡Hola desde $<OBJ_NAME> en el lanzamiento $<HELM_RELEASE_NAME>!'
elCicdTemplates:
- templateName: namespace
objName: $<JOB_NAMESPACE_2>
- templateName: job
objNames: $<OBJ_NAMES>
namespaces: $<NAMESPACES>
objName: $<>-helper (2)
image: quay.io/centos/centos:stream9-minimal
command: $<COMMAND>
args: $<JOB_SCRIPT>
env: $<ENV>
- objNames: $<OBJ_NAMES>
namespaces: $<NAMESPACES>
objName: $<>-raw
template: (3)
apiVersion: batch/v1
kind: Job
spec:
template:
spec:
containers:
- name: $<OBJ_NAME>
image: quay.io/centos/centos:stream9-minimal
command: $<COMMAND>
args: $<JOB_SCRIPT>
env: $<ENV> (4)
restartPolicy: Never
1 | Like objNames , namespaces is an el-CICD Chart matrix.
Each element in the |
2 | Both objNames and namespaces can use patterns to further decorate each final matrix value.
|
3 | The template helper attribute contains the free form YAML definition.
|
4 | Defining environment variables in a container is the same whether using helper or raw templates. |
There is rarely if ever a reason to use a raw template when cl-CICD Chart helper templates exist. This example is for demonstration purposes only. |
Tutorial steps
-
Install the
elcicd-chart-demo
release in theelcicd-chart-demo
namespace using the el-CICD Chart:$ helm upgrade --install --atomic -n elcicd-chart-demo --create-namespace -f elcicd-demo-5.yaml elcicd-chart-demo elcicd-charts/elcicd-chart
- Output
-
Release "elcicd-chart-demo" does not exist. Installing it now. NAME: elcicd-chart-demo LAST DEPLOYED: Tue Jul 16 16:47:02 2024 NAMESPACE: elcicd-chart-demo STATUS: deployed REVISION: 1 TEST SUITE: None
-
View the manifests that generated by el-CICD Chart from the
helm upgrade --install
command:$ helm get manifest -n elcicd-chart-demo elcicd-chart-demo
Output
--- # Source: elcicd-chart/templates/render.yaml apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: elcicd-chart-demo-2 helm.sh/chart: elcicd-chart-0.1.0 name: elcicd-chart-demo-2 namespace: elcicd-chart-demo # Rendered el-CICD Chart Template -> "namespace" elcicd-chart-demo-2 --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-en-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-en-helper namespace: elcicd-chart-demo spec: template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-en-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-en-helper namespace: elcicd-chart-demo spec: containers: - name: job-en-helper image: quay.io/centos/centos:stream9-minimal imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: Howdy from job-en-helper in release elcicd-chart-demo! imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault restartPolicy: "Never" # Rendered el-CICD Chart Template -> "job" job-en-helper --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-en-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-en-helper namespace: elcicd-chart-demo-2 spec: template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-en-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-en-helper namespace: elcicd-chart-demo-2 spec: containers: - name: job-en-helper image: quay.io/centos/centos:stream9-minimal imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: Howdy from job-en-helper in release elcicd-chart-demo! imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault restartPolicy: "Never" # Rendered el-CICD Chart Template -> "job" job-en-helper --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-es-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-es-helper namespace: elcicd-chart-demo spec: template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-es-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-es-helper namespace: elcicd-chart-demo spec: containers: - name: job-es-helper image: quay.io/centos/centos:stream9-minimal imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: ¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo! imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault restartPolicy: "Never" # Rendered el-CICD Chart Template -> "job" job-es-helper --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-es-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-es-helper namespace: elcicd-chart-demo-2 spec: template: metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-es-helper helm.sh/chart: elcicd-chart-0.1.0 name: job-es-helper namespace: elcicd-chart-demo-2 spec: containers: - name: job-es-helper image: quay.io/centos/centos:stream9-minimal imagePullPolicy: Always ports: - name: default-port containerPort: 8080 protocol: TCP resources: limits: {} requests: {} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: ¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo! imagePullSecrets: [] securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault restartPolicy: "Never" # Rendered el-CICD Chart Template -> "job" job-es-helper --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-en-raw helm.sh/chart: elcicd-chart-0.1.0 name: job-en-raw namespace: elcicd-chart-demo spec: template: spec: containers: - args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: Howdy from job-en-raw in release elcicd-chart-demo! image: quay.io/centos/centos:stream9-minimal name: job-en-raw restartPolicy: Never # Rendered YAML Template -> kind: "Job" name: "job-en-raw" --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-en-raw helm.sh/chart: elcicd-chart-0.1.0 name: job-en-raw namespace: elcicd-chart-demo-2 spec: template: spec: containers: - args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: Howdy from job-en-raw in release elcicd-chart-demo! image: quay.io/centos/centos:stream9-minimal name: job-en-raw restartPolicy: Never # Rendered YAML Template -> kind: "Job" name: "job-en-raw" --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-es-raw helm.sh/chart: elcicd-chart-0.1.0 name: job-es-raw namespace: elcicd-chart-demo spec: template: spec: containers: - args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: ¡Hola desde job-es-raw en el lanzamiento elcicd-chart-demo! image: quay.io/centos/centos:stream9-minimal name: job-es-raw restartPolicy: Never # Rendered YAML Template -> kind: "Job" name: "job-es-raw" --- # Source: elcicd-chart/templates/render.yaml apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/instance: elcicd-chart-demo app.kubernetes.io/managed-by: Helm elcicd.io/selector: job-es-raw helm.sh/chart: elcicd-chart-0.1.0 name: job-es-raw namespace: elcicd-chart-demo-2 spec: template: spec: containers: - args: - for COUNTER in {1..5}; do echo ${WELCOME_MSG}; done command: - bash - -c env: - name: WELCOME_MSG value: ¡Hola desde job-es-raw en el lanzamiento elcicd-chart-demo! image: quay.io/centos/centos:stream9-minimal name: job-es-raw restartPolicy: Never # Rendered YAML Template -> kind: "Job" name: "job-es-raw" --- # Source: elcicd-chart/templates/render.yaml # Profiles: []
-
View the running
elcicd-chart-demo
resources in the cluster:$ kubectl get -n elcicd-chart-demo jobs,pods
- Output
-
NAME STATUS COMPLETIONS DURATION AGE job.batch/job-en-helper Complete 1/1 11s 23s job.batch/job-en-raw Complete 1/1 12s 23s job.batch/job-es-helper Complete 1/1 11s 23s job.batch/job-es-raw Complete 1/1 12s 23s NAME READY STATUS RESTARTS AGE pod/job-en-helper-vx985 0/1 Completed 0 23s pod/job-en-raw-zx24g 0/1 Completed 0 23s pod/job-es-helper-t9b5v 0/1 Completed 0 23s pod/job-es-raw-lbr42 0/1 Completed 0 23s
-
View the running
elcicd-chart-demo-2
resources in the cluster:$ kubectl get -n elcicd-chart-demo-2 jobs,pods
- Output
-
NAME STATUS COMPLETIONS DURATION AGE job.batch/job-en-helper Complete 1/1 12s 44s job.batch/job-en-raw Complete 1/1 13s 44s job.batch/job-es-helper Complete 1/1 12s 44s job.batch/job-es-raw Complete 1/1 12s 44s NAME READY STATUS RESTARTS AGE pod/job-en-helper-8r6pg 0/1 Completed 0 44s pod/job-en-raw-ww6z9 0/1 Completed 0 44s pod/job-es-helper-vtlqj 0/1 Completed 0 44s pod/job-es-raw-r8ftk 0/1 Completed 0 44s
-
Check the logs of the Jobs:
Only two of the eight jobs are displayed for brevity. $ oc logs -f -n elcicd-chart-demo job-es-helper-t9b5v
- Output
-
Howdy from job-en-helper in release elcicd-chart-demo! Howdy from job-en-helper in release elcicd-chart-demo! Howdy from job-en-helper in release elcicd-chart-demo! Howdy from job-en-helper in release elcicd-chart-demo! Howdy from job-en-helper in release elcicd-chart-demo!
$ oc logs -f -n elcicd-chart-demo-2 job-en-helper-8r6pg
- Output
-
¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo! ¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo! ¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo! ¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo! ¡Hola desde job-es-helper en el lanzamiento elcicd-chart-demo!
-
Uninstall the chart.
$ helm uninstall -n elcicd-chart-demo elcicd-chart-demo
- Output
-
release "elcicd-chart-demo" uninstalled
2.7. Remove the el-CICD Chart repository
$ helm repo remove elcicd-charts
- Output
"elcicd-charts" has been removed from your repositories
This concludes the el-CICD Chart tutorial.