Overview:

In this step, we will modify the Helm charts to meet the specific requirements of the Add-On Mart infrastructure. These modifications are necessary for a successful deployment and must be followed precisely. This instruction will guide you through each necessary adaptation.

Artifacts:

For the purpose of this tutorial we will be using this artifacts repository: https://gitlab.portaone.com:8949/read-only/tutorial-for-simple-application

./Step_7/charts_local - directory that stores data prepared during the previous steps.
./Step_7/charts_AddOnMart -updated Helm Charts. The attributes in this directory are essentially the same as in ./Step_7/charts_local, but updated with all the data that will be specified throughout the instructions in this chapter.

Documentation Variables:

The documentation contains custom variables:

  • <application_name>
  • <application_version>
  • <vendor_name>

For details related to variables meaning, please refer => Guide to deploy application in Add-On Mart for third-party developers

General Requirements:

  1. Name Overriding: To comply with Add-On Mart’s naming conventions, each deployed resource must include an instance_id. This is managed by updating the helper templates and values.yaml file.

  2. Vendor ID Label: Adding a vendor_id label is essential for resource monitoring and assignment.

  3. Docker Image Repository: Specify the repository URL and tag for the Docker image to be pulled during deployment.

  4. Credentials to Pull Image: Provide secrets for pulling images from the private Harbor registry.

  5. Resources Monitoring: Enable Kubernetes to monitor changes in configurations and secrets.

  6. Ingress Configuration: Configure IngressRoute for Traefik, which is essential for Add-On Mart.

  7. Namespace: Namespace should be automatically assigned during the deployment.

  8. Configurable Parameters: Ensure all parameters that need to be provisioned by the helmfile are left empty in values.yaml.

For more details related to Helm Charts preparation for Add-On Mart tool, please refer specification → How to create helm chart for your application - a guide for third-party developers#Howtoinstalltraefikinminikubehow_to_deploy_traefik

1. Name Overriding:

Purpose:

To comply with Add-On Mart’s naming conventions, each deployed resource must include an instance_id. This ensures that resource names are unique and identifiable.

This is managed by updating the helper templates and values.yaml file.

Update values.yaml:

./charts_AddOnMart/values.yaml
nameOverride: ""
fullnameOverride: ""

Update _helpers.tpl:

Extend _helpers.tpl to handle name overriding:

<application_name>.fullname  helper has to be used for resources name definition in Helm Charts

./charts_AddOnMart/templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "<application_name>.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "<application_name>.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

2. Vendor ID Label:

Purpose: Adding a vendor_id label is crucial for resource monitoring and assignment. This ensures that the resources can be tracked and managed by the Add-On Mart infrastructure.

Update values.yaml:

./charts_AddOnMart/values.yaml
vendorId: "<vendor_name>"

Update _helpers.tpl:

Add vendor_id to the common labels:

<application_name>.selectorLabels has to be inserted into resources lables.

It is crucially important to indicate vendor id in the deployment.yaml template(manifest) for deployed pod. 

./charts_AddOnMart/templates/_helpers.tpl
{{/*
Common labels
*/}}
{{- define "<application_name>.labels" -}}
helm.sh/chart: {{ include "<application_name>.chart" . }}
{{ include "<application_name>.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "<application_name>.selectorLabels" -}}
vendor_id: {{ .Values.vendorId }}
app.kubernetes.io/name: {{ include "<application_name>.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

3. Docker Image Repository:

Purpose: To have access to the Docker image and to pull it during deployment, specify the repository URL and tag.

Update values.yaml:

./charts_AddOnMart/values.yaml
image:
  pullPolicy: Always
  repository: registry.portaone.com/<vendor_name>/<application_name>
  tag: "<application_version>"

4. Credentials to Pull Image:

Purpose: During deployment to the Add-On Mart infrastructure, the image will be pulled from a private Harbor registry. Provide possibility to fetch secrets for pulling images from the registry.
Secret will be automatically provisioned during deployment step based on the parameters that were stated in the helmfile template.

Update values.yaml:

./charts_AddOnMart/values.yaml
imagePullSecrets: []

Update deployment.yaml:

Add imagePullSecrets:

./charts_AddOnMart/templates/deployment.yaml
spec:
  {{- with .Values.imagePullSecrets }}
  imagePullSecrets:
    {{- toYaml . | nindent 8 }}
  {{- end }}
  containers:
  - name: {{ .Chart.Name }}
    image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
    imagePullPolicy: {{ .Values.image.pullPolicy }}
    ports:
    - name: http
      containerPort: {{ .Values.service.targetPort }}
      protocol: TCP

5. Resources Monitoring:

Purpose: Helm can monitor changes in the data such as config files, secret files, and images. It will redeploy the application if any changes are identified, ensuring that the application is always up-to-date.

Update values.yaml:

./charts_AddOnMart/values.yaml
imageSha: {}

Update deployment.yaml:

Add checksum annotations:

Set an appropriate path to the files that should be monitored(e.g. "/templates/config-cm.yaml", "/templates/secret.yaml")

./charts_AddOnMart/templates/deployment.yaml
metadata:
  annotations:
    checksum/image: {{ get .Values.imageSha (printf "%s_%s" .Values.image.repository (.Values.image.tag | default .Chart.AppVersion)) | default "none" }}
    checksum/config: {{ include (print $.Chart.Name "/templates/config-cm.yaml") . | sha256sum }}
    checksum/secret-env: {{ include (print $.Chart.Name "/templates/secret.yaml") . | sha256sum }}

6. Ingress Configuration:

Purpose: Configure IngressRoute for Traefik, which is essential for Add-On Mart. Add-On Mart infrastructure uses Traefik as the Ingress Controller, providing the ability to use self-signed certificates or provide your own certificates.

Traefik is an Add-On Mart requirement. Based on it Traefik has to be chosen for compatibility with Add-On Mart resources.

IngressRoute is very sensitive to correct configuration and should be properly configured. Do not modify it with own data without a strict necessity. Keep it as in the example

Update values.yaml:

./charts_AddOnMart/values.yaml
ingress:
  enabled: true
  class: ""
  host: ""
  path: /
  annotations: {}
  tls:
    enabled: false
    crt: ""
    key: ""
    secret: ""
    secretAutoCreate: false
    certificateIssuerName: ""

Update tls-secret.yaml:

Add conditions for certificate usage:

./charts_AddOnMart/templates/tls-secret.yaml
{{- if not .Values.ingress.tls.secretAutoCreate }}
{{- if and .Values.ingress.tls.crt .Values.ingress.tls.key }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "<application_name>.fullname" . }}-secrets-tls
type: kubernetes.io/tls
data:
  tls.crt: {{ .Values.ingress.tls.crt }}
  tls.key: {{ .Values.ingress.tls.key }}
{{- end }}
{{- end }}

Update ingressroute.yaml:

Add Certificate resource and update IngressRoute resource:

./charts_AddOnMart/templates/ingressroute.yaml
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "<application_name>.fullname" . -}}
{{- if .Values.ingress.tls.secretAutoCreate }}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: {{ .Values.ingress.host }}
spec:
  secretName: {{ $fullName }}-secrets-tls
  issuerRef:
    name: {{ .Values.ingress.tls.certificateIssuerName }}
    kind: Issuer
  commonName: {{ .Values.ingress.host }}
  dnsNames:
  - {{ .Values.ingress.host }}
{{- end }}
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: {{ $fullName }}-redirect-scheme
  annotations:
    kubernetes.io/ingress.class: {{ .Values.ingress.class }}
spec:
  redirectScheme:
    scheme: https
    permanent: true
    port: "443"
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: {{ $fullName }}-strip-prefix
spec:
  stripPrefix:
    prefixes:
      - {{ .Values.ingress.path }}
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: {{ $fullName }}-http
  annotations:
    kubernetes.io/ingress.class: {{ .Values.ingress.class }}
  labels:
    {{- include "<application_name>.labels" . | nindent 4 }}
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`{{ .Values.ingress.host }}`) && PathPrefix(`{{ .Values.ingress.path }}`)
      kind: Rule
      services:
        - name: {{ $fullName }}
          namespace: {{ .Release.Namespace }}
          port: {{ .Values.service.port }}
      middlewares:
        - name: {{ $fullName }}-redirect-scheme
        - name: {{ $fullName }}-strip-prefix
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: {{ $fullName }}-https
  annotations:
    kubernetes.io/ingress.class: {{ .Values.ingress.class }}
  labels:
    {{- include "<application_name>.labels" . | nindent 4 }}
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`{{ .Values.ingress.host }}`) && PathPrefix(`{{ .Values.ingress.path }}`)
      services:
        - name: {{ $fullName }}
          namespace: {{ .Release.Namespace }}
          port: {{ .Values.service.port }}
      middlewares:
        - name: {{ $fullName }}-strip-prefix
  {{- if .Values.ingress.tls.enabled }}
  tls:
    secretName: {{ .Values.ingress.tls.secret }}
    domains:
      - main: {{ .Values.ingress.host }}
  {{- end }}
{{- end }}

7. Namespace:

Purpose: The namespace should be automatically assigned during deployment to ensure proper access rights and isolation.

Action: Remove namespace indication from all resources stated in Helm charts and remove the namespace resource template.

8. Configurable Parameters:

Purpose: Ensure all parameters that need to be provisioned by the helmfile are left empty in values.yaml. These parameters will be overridden during deployment by helmfile, based on the instance configuration via Add-On Mart Config UI.

Action: Leave empty all parameters that should be provisioned and overwritten by helmfile. 

It is not necessary to keep parameters empty but keep in mind that they will be overwritten during the deployment process if the parameter was specified in the helmfile.

In general, all parameters stated in the Helm Charts can be overwritten using Helmfile templates.

You can move all sensitive information and general information to Helmfile.

Keep in mind that Helmfile overwrites all information stated in the Helm Charts values during the deployment process if the same parameter is indicated in the Helmfile template.

Pay attention to the dependency between Helm Charts and Helmfile templates to avoid confusion with parameters overwriting during the deployment process.

./charts_AddOnMart/values.yaml
vendorId: "<vendor_name>"

nameOverride: ""
fullnameOverride: ""
imagePullSecrets: []
imageSha: {}


replicaCount: 1

image:
  pullPolicy: Always
  repository: registry.portaone.com/<vendor_name>/<application_name>
  tag: "<application_version>"

service:
  type: ClusterIP
  targetPort: 8000
  port: 8888

ingress:
  enabled: true
  class: ""
  host: ""
  path: /
  annotations: {}
  tls:
    enabled: false
    crt: ""
    key: ""
    secret: ""
    secretAutoCreate: false
    certificateIssuerName: ""


appConfig:
  serverUrl: ""
  configOption: ""

appSecret:
  secretUsername: ""
  secretPassword: ""
  secretBase64Encoded: ""

appEnv:
  configPath: /app/config.yaml
  customEnvVariable: ""

Summary:

By following these steps, the Helm charts will be properly adapted to meet the Add-On Mart specifics, ensuring a smooth and successful deployment.