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 will default to global settings (30m). - 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.
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 all associated Release objects. 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: