Helm Charts for Expertflow CX Solution - Developer Edition
Instructions for Developers
Component Chart
A general Chart has a hierarchy like below
chart-name/
├── charts
├── Chart.yaml
├── templates
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── serviceaccount.yaml
│ └── service.yaml
└── values.yaml
Chart.yaml contains metadata about the chart, like its version, appVersion and related information. Whenever there is a change in the application , the appVersion is incremented using semantic versioning. The chart version is incremented when there is a change in the chart. In simpler words a single appVersion can be maintained across different chart version and vice a versa
templates directory contains actual deployment contents for the component, with every single file being evaluated by a certain variable or function in the values file ( details given below )
values.yaml file for component is main file where end-user is allowed to change/update their required parameters and based on those evaluations are made when generating templates.
Meta Chart ( ef-cx )
For Expertflow Solution, a meta Chart is created which on its own doesn't do any thing except it
- Create a generic FQDN variable which will be used across all the sub-charts
- defines a global registry variable to provide offline deployments
- creates commonEFConnection configmap which is populated in component charts where needed.
- creates Image Pull Secret for the images to be pulled from a certain registry
- creates SSL certificate as secrete required for all ingress routes.
- declares sub-charts.
details are given below for actions performed by the meta-chart.( values.yaml ).
Generally, below given parameters are evaluated when the Chart is deployed.
{{ .Release.Name }} is replaced with the release name of the helm install command
{{ .Release.Namespace }} refers to the current namespace where the solution is to be deployed.
{{ .Values.global.ingressRouter }} will be replaced with the corresponding value from the values.yaml file.
common as sub-chart
A special library chart is included in the charts directory named as "common". This chart includes many commonly required functions which may help perform complex evaluations using simpler function calls. One of the function that is more commonly used in all charts ( both meta and sub-charts ) is the "common.tplvalues.render", which can help placing a function call in values.yaml file and then evaluate it. Note: This functionality is normally not possible without using rendering function.
demo as sub-chart
This chart is provided as a template chart to evaluate and perform testing for any one with requirements not enabled in any of the existing charts. You can place your test files in demo/templates folder and run evaluations using this chart.
Meta Chart Detailed
In addition to sub-chart details, below given are the details for this meta chart. Any key:value pair present in this file supersedes the values file in sub-chart's values file.
Item | Details | default |
---|---|---|
global.ingressRouter | This parameter defines the FQDN used across the Expertflow Solution and is evaluated as a standard FQDN expression i-e can be a FQDN or, subdomain only. | "ef.com" |
global.registry | this parameter gives the end user ability to customize the deployment in an air-gapped environment. Changing its values will evaluate all images below this variable and must be changed in "imageCredentials.registry " | "gitimages.expertflow.com" |
imageCredentials.registry | provides the registry URL | "gitimages.expertflow.com" |
imageCredentials.username | username to use | "efcx" |
imageCredentials.password | Password for the user | "RecRpsuH34yqp56YRFUb" |
imageCredentials.email | an email address for the user | "devops@expertflow.com" |
ssl.enabled | when enabled to true, a self-Signed-Certificate ( includes .Values.global.ingressRouter, 127.0.0.1 and ef.expertflow as default Domain Names ) | |
ssl.generateTLS | If False use the external/customer's SSL Cert/Key pair (mentioned below for defaultKey and defaultCert) | |
ssl.defaultSANList | Additional Domains to be included in the list of SANS | ef.expertflow |
ssl.defaultIPList | Additional IP address list for inclusion | 127.0.0.1 |
ssl.defaultKey | custom SSL Key | Key should be Base64 encoded |
ssl.defaultCert | custom SSL Cert | Cert should be Base64 encoded |
SubChart Declaration
MetaChart includes declaration of sub-charts in below given format.
Subchart Item | Details | Default |
---|---|---|
subchart.install | Enable or Disable this chart TRUE/FALSE | true |
subchart.replicaCount | Replica Count for this sub-Chart's pods | 1 |
subchart.image.repository | storage path on the registry | per component |
subchart.image.tag | tag to be used for this chart | per component |
subchart.includeCommonEfConnections | Whether CommonEFConnection CM be added to this component. TRUE/FALSE | true |
Note:
Image Pull Secret is created at runtime based on these variables, a valid dockerconfig in JSON format is created at runtime and added to the kubernetes engine as secret with the name of expertflow-gitlab-creds
CommonEfConnections ConfigMap
this configmap is now part of the global values.yaml file under commonEfConnections
array and any addition/removal should be done in the values.yaml file only. It is created unconditionally ( no true/false switch is available ) and is available to the specified sub-charts
sub-charts
All sub-charts are named after the component name for which it is developed and its values are evaluated from its values.yaml file
list of sub-chart values evaluated and used during installation
item | details | default |
---|---|---|
replicaCount | gives the total number of replicas for this deployment | 1 |
image.repository: | repository to fetch the image from | per component |
image.pullPolicy | when to pull the image 'Always', 'Never','IfNotPresent' | 'IfNotPresent' |
image.tag | image tag | |
imagePullSecrets: | image pull secrets | expertflow-gitlab-creds. generated automatically during helm install |
nameOverride | String to partially override common.names.fullname (DO NOT USE) | "" |
fullnameOverride | String to fully override common.names.fullname(DO NOT USE) | "" |
environment.enabled | whether this component has its own env from a config-map | true |
includeCommonEfConnections | whether to load the commonEFConnection configmap into this component's env | false |
envOverride | Include component level environement variables. Evaluated as Array | '[]' |
includeCommonEfConnectionscontainerPort | whether to load the commonEFConnection configmap into this component's envPort this component exposes | false"" [ 0-9 ]+ |
containerPortName | Name of the Port | "" [ a-z0-9 ] + must be 15 characters long |
restartPolicy | whether to restart the container process if it dies | Always |
extraContainerPorts | List of extra ports to be added to the deployment for this component.Also add this port to the service | {} |
sidecars | Any sidecar container for this component. Evaluated as YAML template | {} |
initContainers | Any initContainer for this component. Evaluated as YAML template | {} |
serviceAccount | Whether to add a service account for this component. | false |
podAnnotations | Annotation to be added to the pod. YAML template | {} |
podSecurityContext | SecurityContext for this Pod | {} |
securityContext | SecutiryContext to the Pod | {} |
service.enabled | Whether to enable the service for this component. | true |
service.type | Type of the service | ClusterIP |
service.port | Port of the service exposed | |
service.targetPort | the destination port in the deployment/pods | "" |
service.name | Name of the service to be exposed ( not used , use template ) | '{{ .Release.Name }}-{{ .Release.Chart }}-svc |
service.extraPorts | whether to expose any additional ports on this service. Evaluated as list | '[]' |
ingress.enabled | whether to expose this component via ingress | true |
ingress.className | ingress class to be used for this ingress | "" |
ingress.annotations: | ingress related annotation which are required for the ingress to work properly | "" |
ingress.paths: | list of paths this ingress will be exposing to the ingress controller | "" |
ingress.tls | defaults to true for the https/SSL based ingress | true |
customLivenessProbe | livenessProbe for this component. Evaluated as Yaml | '{}' |
customReadinessProbe | readinessProbe for this component. Evaluated as Yaml | '{}' |
customStartupProbe | startupProbe for this component. Evaluated as Yaml | '{}' |
resources | resource allocation and limits for this component | {} |
autoscaling.enabled | Whether to enable autoscaling for this componenet | false |
autoscaling.minReplicas | minimum number of replicas to maintain | 1 |
autoscaling.maxReplicas: 100 | maximum number of replicas to scale upto | 100 |
autoscaling.targetCPUUtilizationPercentage: 80 | At what percentage of CPU utilization do the autoscaling | 80 |
autoscaling.targetMemoryUtilizationPercentage: 80 | At what percentage of RAM utilization do the autoscaling | 80 |
nodeSelector | Node selector | '{}' |
toleration | Pod Tolerations | '[]' |
affinity | Pod Affinity | '{}' |
Attention:
Most of the configurable parameters are already adjusted in both component and global values files. However, for some components like Conversation Controller and other components which require adjustable configuration at runtime, configmaps are generates at the time of deployment of the helm chart. These must be compiled with proper indentation at required place in values.yaml file.
Creating a new sub-chart
Creating a new chart is simple. helm provides an option to create a new template chart which you can use to adjust according to the requirement
helm create <chart-name>
this will create a chart with the entered chart-name with all the required templates in templates directory. Once created, please edit the chart and make necessary changes.
Duplicate the chart to minimize the effort.
For easily creating a chart adhering to Expertflow requirements, you can also copy an existing chart's values.yaml and templates folder within newly created chart and adjust it values. Below are the steps for such an exercise.
helm create new-connector
# Enter the newly created chart directory
cd new-connector
yes| cp ../connect360/values.yaml .
yes| cp ../connect360/templates/{deployment.yaml,service.yaml,configmap.yaml,ingress.yaml} templates/
NOTE: for MAC based systems please install the gnu sed using
# brew install gnu-sed
and use the `gsed` instead of the sed command.
# Change all the occurences of the source chart connect360 to new-connector
sed -i -e 's/connect360/<NEW-CONNECTOR>/g' values.yaml templates/*.yaml ( for Linux users )
gsed -i -e 's/connect360/<NEW-CONNECTOR>/g' values.yaml templates/*.yaml ( for macOS users )
#however, some files need manual changes like port-name, service.port and other parameters
* values.yaml
* Chart.yaml
Update ConfigMaps
ConfigMaps for Environment Variables
For normal environment variables' substitution , please modify the templates/configmap.yaml
and add/update the environment variables.
Only add variables in <component-name>/templates/configmap.yaml file which are static across the deployment like reference to other services etc. For configurational parameters, add them to the global values file under the envOverride
section. otherwise a complete rebuild of the chart will be required.
ConfigMaps for Mount Points
If the component requires files to be mounted inside the pod, please follow these steps.
- create the folder containing files under <new-connector>/<new-folder> ( e.g <new-connector>/cache-builder )
- under new-folder copy all files required for configmaps.
- create a new template under new-connector/templates/ with the relevant purposeful name ending with yaml ( e.g new-connector/templates/cache-builder.yaml)
- follow these guide lines
- CODE
apiVersion: v1 kind: ConfigMap metadata: name: {{ include "<NEW-CONNECTOR>.fullname" . }}-actions-cm namespace: {{ .Release.Namespace }} labels: {{- include "<NEW-CONNECTOR>.labels" . | nindent 4 }} data: {{ (.Files.Glob "cache-builder/**").AsConfig | indent 2 }}
The above given template will generate config-map containing all the files under cache-builder with file-name as the keyname
- If the data files to be imported are binary , change the
data:
tag toBinaryData
so that the kubernetes does not convert them to base64 encoded values.
once the newly created chart's values are adjusted, you will have rebuild the chart dependency by running
rm -f Chart.lock;
helm dependency update .
helm dependency build .
Update mechanism for a sub-chart
Developers are required to follow these guidelines when updating their respective subcharts.
- All sub-charts a rendered using templates present in the templates folder. These templates are evaluated based on their decisions from the component's values.yaml
- All config-maps, deployments, services are named after the chart name defined in the Chart.yaml file of each component.
- All config-maps must end with "-cm". added manually to the templated config-map name
- All Service names must end with "-svc". added manually to the templated service name
- All Service name references in configmaps must be "{{ .Release.Name }}-{{ .Chart.Name }}-svc " for example to reference
agent-manager
's service endpoint, it should be referenced as "{{ .Release.Name }}-agent-manager-svc", where Release.Name is the deployment profile name of the whole CX solution. - All components must declare their exposed ports by name satisifying the port naming convention. For example agent-manager port of 8080 serving on http protocol will be named as http-ag-ma-8080.
- the portname must be 15 characters long otherwise Kubernetes engine will fail the deployment.
- protocol must be at the start of the port name.
- All Services must refer to the port of the container with the name of the port
Versioning of the Charts
All sub-charts must adhere to semvers conventions used and should be updated whenever there is a change in the chart's structure like env, cm, svc or deployment is changed.
- Change the version of the chart to next available semver number
- update the sub-chart's version in meta-chart's Chart.yaml
Update dependencies
rm -f Chart.lock; helm dependency build .
Package the existing sub-chart
helm package <component-dir-name>
Push the chart to the repo.
Login to the expertflow Charts repository . skip this step if already logged in.
helm registry login --username efcx --password Expertflow123$ charts.expertflow.com/library
push the chart to the EF repo using
helm push <component-name-version.tgz> oci://charts.expertflow.com/library
Update the ef-cx meta chart
Once new component is added, update the ef-cx/Charts.yaml file to represent the update information. This is a templated entry like below
- name: new-connector
condition: anew-connector.install
version: "1.0.0"
repository: oci://charts.expertflow.com
update the values.yaml file in ef-cx meta-chart. A sample entry will look like below:
###
new-connector:
install: true
replicaCount: 1
envOverride:
- name: variable
value: value
image:
repository: cim/new-connector
tag: "4.1-SR2"
includeCommonEfConnections: true
###
Create the helm package archive ( new sub-chart )
for pushing to helm repo, create the package which we will push to repo in next step.
helm package <new-component-dir-name>
This command will create a file with the <component-name-version.tgz> format in current directory
Push the chart to the repo ( new sub-chart )
Login to the expertflow Charts repository . skip this step if already logged in.
helm registry login --username efcx --password Expertflow123$ charts.expertflow.com/library
push the chart to the EF repo using ( new sub-chart )
helm push <component-name-version.tgz> oci://charts.expertflow.com/library
Update the meta ef-cx chart
Once all the sub-charts information is updated in both chart.yaml
and values.yaml
for ef-cx.
Update the ef-cx meta chart version
Change the version of the meta ef-cx chart in its chart.yaml
Update the ef-cx dependency
helm dependency update ef-cx
package the ef-cx chart
helm package ef-cx
push the ef-cx meta chart to repo
helm push <ef-cx-version.tgz> oci://charts.expertflow.com/library
Troubleshooting Steps.
Rendering Helm charts without installing them
As a developer of helm charts, You can also render the changes without installing the helm chart directly by
helm install --namespace expertflow --set global.ingressRouter=devops218.ef.com "ef-cx" --dry-run --debug .
Or Just to render the templates ( inside the chart directory )
helm template --debug --values values.yaml .
there are certain scenarios where the YAML is not rendered correctly ( due to incorrect spaces or tab characters ) You can disable the api-validation using ( inside the chart directory )
helm install --namespace <namespace> <release-name> --dry-run --disable-openapi-validation --debug --values values.yaml .
this will show the incorrect YAML that needs proper indentation.
Dumping all the rendered manifests to a folder
You can also dump all the generated/rendered manifests into a folder for evaluation using
Check if the Go language is installed on your system
go version
if go lang is not installed, you can install the golang by following instruction on https://go.dev/doc/install
once golang is installed, run this command to fetch the required go module
go get -u github.com/databus23/schelm
export the required environment variables for golang
export GOPATH=$(go env GOPATH)
add the golang in your PATH
export PATH=$PATH:$GOPATH/bin
export all the rendered charts into /root/rendered
folder
helm install --namespace <namespace> <release-name> --dry-run --debug .|schelm /root/rendered