The Context
One of KuboCD's key features is its ability to generate Helm value files from a concise set of high-level input parameters using a templating mechanism.
This mechanism combines a template with a data model.
Our previous example used only the .Parameters element of the data model:
podinfo-p01.yaml
However, the full data model includes the following top-level elements:
.Parameters: The parameters provided in theReleasecustom resource..Release: The release object itself..Context: The deployment context.
The Context is a flexible YAML object designed to hold shared configuration data relevant across multiple deployments.
For example, the podinfo package includes an ingressClassName parameter with a default value of nginx. If a cluster uses a different ingress controller, this value would need to be overridden for every Release. Ideally, widespread configuration like this should be defined once in a global cluster-level context.
Similarly, if all application ingress URLs share a common root domain, that domain should also be centralized.
Here is how to implement this logic.
Creating a Context
A Context is a KuboCD Custom Resource:
cluster.yaml
apiVersion: kubocd.kubotal.io/v1alpha1
kind: Context
metadata:
namespace: contexts
name: cluster
spec:
description: Global context for the kubodoc cluster
protected: true
context:
ingress:
className: nginx
domain: ingress.kubodoc.local
storageClass:
data: standard
workspace: standard
certificateIssuer:
public: cluster-self
internal: cluster-self
Key Attributes:
description: A short description of the context.protected: Prevents accidental deletion (requires the KuboCD webhook).context: A tree of values injected into the data model duringvaluestemplating.- Must be valid YAML.
- Has a flexible structure but should align with what
Packagetemplates expect.
In this example, the context includes:
ingress.className: The ingress controller type.ingress.domain: The suffix for ingress URLs.storageClass: Definitions fordataandworkspacestorage profiles (set tostandardfor Kind).certificateIssuer: Identifiers for public and internal certificate issuers. (We will configure a self-signed CA in the cert-manager section).
Cluster-wide contexts should be placed in a dedicated namespace:
Note
Since the context is often shared across many applications, its structure should be carefully designed and well-documented.
Modifying the Package
Our initial podinfo package did not utilize the context. Here is an updated version that does:
podinfo-p02.yaml
apiVersion: v1alpha1
type: Package
name: podinfo
tag: 6.7.1-p02
schema:
parameters:
$schema: http://json-schema.org/schema#
type: object
additionalProperties: false
properties:
host: { type: string }
required:
- host
context:
$schema: http://json-schema.org/schema#
additionalProperties: true
type: object
properties:
ingress:
type: object
additionalProperties: true
properties:
className: { type: string }
domain: { type: string }
required:
- domain
- className
required:
- ingress
modules:
- name: main
source:
helmRepository:
url: https://stefanprodan.github.io/podinfo
chart: podinfo
version: 6.7.1
values: |
ingress:
enabled: true
className: {{ .Context.ingress.className }}
hosts:
- host: {{ .Parameters.host }}.{{ .Context.ingress.domain }}
paths:
- path: /
pathType: ImplementationSpecific
Key Changes:
tag: updated to6.7.1-p02.hostparameter: Replacesfqdn. Now represents only the hostname (excluding the domain).modules[X].values: Updated to use.Contextvariables.schema.context: Added to define and validate the expected context structure.
Pack and push this new version:
====================================== Packaging package 'podinfo-p02.yaml'
--- Handling module 'main':
Fetching chart podinfo:6.7.1...
Chart: podinfo:6.7.1
--- Packaging
Generating index file
Wrap all in assembly.tgz
--- push OCI image: quay.io/kubodoc/packages/podinfo:6.7.1-p02
Successfully pushed
Deployment with Context
Here is the corresponding Release manifest:
podinfo2-ctx.yaml
Key Features:
- Interval Removed:
spec.package.intervalis omitted and defaults to5m. - Parameter Update:
fqdnis replaced byhost. contextsSection: Lists contexts to merge into the template data model.
Warning
Referencing a non-existent context will result in an error.
Apply the deployment:
Check that the new Release is READY:
NAME REPOSITORY TAG CONTEXTS STATUS READY WAIT PRT AGE DESCRIPTION
podinfo2 quay.io/kubodoc/packages/podinfo 6.7.1-p02 contexts:cluster READY 1/1 - 17m A first sample release of podinfo
Verify that the ingress has been configured correctly:
NAME CLASS HOSTS ADDRESS PORTS AGE
podinfo2-main nginx podinfo2.ingress.kubodoc.local 10.96.59.9 80 120m
Note
Remember to update your /etc/hosts or DNS if you wish to access this ingress.
Context Aggregation
An application's effective context is often the result of aggregating multiple context objects.
For instance, you might create a project-level context to share variables across all applications in a specific project, which is then merged with the global cluster context.
The examples below merge the contexts that a Release lists. A Context can also merge other contexts, its parents. See Parents.
Example 1: merging Contexts
Create a project namespace:
Create the project context:
project01.yaml
Apply it to the namespace:
List all defined contexts:
NAMESPACE NAME DESCRIPTION PARENTS STATUS AGE
contexts cluster Global context for the kubodoc cluster READY 2d2h
project01 project01 Context for project 1 READY 2m35s
We need to update the package to use the new project.subdomain variable:
podinfo-p03.yaml
apiVersion: v1alpha1
type: Package
name: podinfo
tag: 6.7.1-p03
schema:
parameters:
$schema: http://json-schema.org/schema#
type: object
additionalProperties: false
properties:
host: { type: string }
required:
- host
context:
$schema: http://json-schema.org/schema#
additionalProperties: true
type: object
properties:
ingress:
type: object
additionalProperties: true
properties:
className: { type: string }
domain: { type: string }
required:
- domain
- className
project:
type: object
additionalProperties: true
properties:
subdomain: { type: string }
required:
- subdomain
required:
- ingress
- project
modules:
- name: main
source:
helmRepository:
url: https://stefanprodan.github.io/podinfo
chart: podinfo
version: 6.7.1
values: |
ingress:
enabled: true
className: {{ .Context.ingress.className }}
hosts:
- host: {{ .Parameters.host }}.{{ .Context.project.subdomain }}.{{ .Context.ingress.domain }}
paths:
- path: /
pathType: ImplementationSpecific
Pack the updated package:
Create a new Release:
podinfo-prj01.yaml
---
apiVersion: kubocd.kubotal.io/v1alpha1
kind: Release
metadata:
name: podinfo
spec:
description: A release of podinfo on project01
package:
repository: quay.io/kubodoc/packages/podinfo
tag: 6.7.1-p03
parameters:
host: podinfo
contexts:
- namespace: contexts
name: cluster
- name: project01
debug:
dumpContext: true
dumpParameters: true
Notes:
metadata.namespace: Not defined in the file; will be set via CLI.metadata.name: Simplypodinfo.spec.contexts: Now includes two entries. The second one references the project context (defaults to the release namespace).debug: Added to dump the resulting context and parameters into theReleasestatus for inspection.
Deploy the release:
Verify that both contexts are active:
NAME REPOSITORY TAG CONTEXTS STATUS READY WAIT PRT AGE DESCRIPTION
podinfo quay.io/kubodoc/packages/podinfo 6.7.1-p03 contexts:cluster,project01:project01 READY 1/1 - 8m31s A release of podinfo on project01
Check the resulting ingress:
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
default podinfo1-main nginx podinfo1.ingress.kubodoc.local 10.96.207.51 80 4h46m
default podinfo2-main nginx podinfo2.ingress.kubodoc.local 10.96.207.51 80 4h6m
project01 podinfo-main nginx podinfo.prj01.ingress.kubodoc.local 10.96.207.51 80 4h
Inspect the Release status to see the merged context:
apiVersion: kubocd.kubotal.io/v1alpha1
kind: Release
metadata:
....
spec:
....
status:
context:
ingress:
className: nginx
domain: ingress.kubodoc.local
project:
id: p01
subdomain: prj01
storageClass:
data: standard
workspace: standard
....
parameters:
host: podinfo2
....
Warning
In production, contexts can become large. Use debug mode sparingly.
Example 2: Context Overrides
In this example, we keep the objective (adding a subdomain) but use the podinfo-p02 package (which does not use project.subdomain). Instead, we will override ingress.domain.
Create a dedicated namespace:
Create a project context:
project02.yaml
Notice that ingress.domain exists in both the cluster and project contexts. When merging, later contexts in the list override earlier ones.
Create and deploy the release:
podinfo-prj02.yaml
---
apiVersion: kubocd.kubotal.io/v1alpha1
kind: Release
metadata:
name: podinfo
spec:
description: A release of podinfo on project02
package:
repository: quay.io/kubodoc/packages/podinfo
tag: 6.7.1-p02
parameters:
host: podinfo
contexts:
- namespace: contexts
name: cluster
- name: project02
debug:
dumpContext: true
dumpParameters: true
Check the Release context:
status:
context:
ingress:
className: nginx
domain: prj02.ingress.kubodoc.local
project:
id: p02
storageClass:
data: standard
workspace: standard
Verify the ingress host:
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
default podinfo1-main nginx podinfo1.ingress.kubodoc.local 10.96.218.98 80 2d20h
default podinfo2-main nginx podinfo2.ingress.kubodoc.local 10.96.218.98 80 110m
project01 podinfo-main nginx podinfo.prj01.ingress.kubodoc.local 10.96.218.98 80 26m
project02 podinfo-main nginx podinfo.prj02.ingress.kubodoc.local 10.96.218.98 80 2m52s
Modifying Contexts
Any change to a context resource is automatically propagated to the Release objects that use it:
- The
Releaseobjects that name it inspec.contexts. - Every
Release, when theConfigresources make it a global default context. - Every
Releaseof its namespace, when theConfigresources make its name a namespace default context.
However, actual updates (Helm upgrades) only occur for deployments that are genuinely affected by the change.
For example, modify the project01 context:
kubectl -n project01 patch context.kubocd.kubotal.io project01 --type='json' -p='[{"op": "replace", "path": "/spec/context/project/subdomain", "value": "project01" }]'
Observe the ingress update:
The host podinfo.project01.ingress.kubodoc.local should appear shortly.
To restore the original value: