Konfidence is pre-release software. Concepts and APIs are unstable and subject to change.
Skip to content

Author a Helm artifact ​

After this guide, you have a Helm chart and an OCM component constructor ready to validate and publish as a Konfidence artifact. Once the published artifact is included in a vector, the Kubernetes deployer installs the chart in the landscape.

The examples build a service named my-service and push everything to registry.example.com/my-org.

Prerequisites ​

Before you begin, make sure you have:

Build and push the container image ​

  1. Create a Dockerfile in your service directory. The following example copies a prebuilt binary into a small base image. Replace the build with your own toolchain.

    dockerfile
    FROM alpine:3.20
    COPY my-service /usr/local/bin/my-service
    EXPOSE 8080
    ENTRYPOINT ["my-service"]
  2. Build and push the image with the version you plan to release:

    bash
    docker build -t registry.example.com/my-org/my-service:1.0.0 .
    docker push registry.example.com/my-org/my-service:1.0.0

The registry lists my-service:1.0.0 afterward.

Create a minimal chart ​

Create a my-service/ directory for the chart and a templates/ directory inside it:

bash
mkdir -p my-service/templates

Create the following files inside my-service/. Run the packaging commands from its parent directory. helm create generates a larger chart that follows the same rules.

  1. Create Chart.yaml:

    yaml
    apiVersion: v2
    name: my-service
    version: 1.0.0
    appVersion: "1.0.0"
  2. Create values.yaml with the image reference:

    yaml
    image:
      repository: registry.example.com/my-org/my-service
      tag: "1.0.0"
  3. Create templates/deployment.yaml:

    yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: {{ .Release.Name }}
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/instance: {{ .Release.Name }}
      template:
        metadata:
          labels:
            app.kubernetes.io/instance: {{ .Release.Name }}
        spec:
          containers:
            - name: my-service
              image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
              ports:
                - containerPort: 8080
  4. Create templates/service.yaml:

    yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: {{ .Release.Name }}
    spec:
      selector:
        app.kubernetes.io/instance: {{ .Release.Name }}
      ports:
        - port: 80
          targetPort: 8080

The chart renders one Deployment and one Service, both named after the release.

Package and push the chart ​

  1. Package the chart directory:

    bash
    helm package ./my-service
  2. Push the package to the registry:

    bash
    helm push my-service-1.0.0.tgz oci://registry.example.com/my-org/charts

The chart is available as registry.example.com/my-org/charts/my-service:1.0.0. Keep charts and container images in separate registry paths so that pushing a chart does not replace an image tag.

Reference the chart from the artifact component ​

  1. Create manifest.json with the Helm type:

    json
    {
      "type": "helm.konfidence.cloud",
      "allowReuse": false
    }

    Set allowReuse to true only when one running instance can serve several vectors.

  2. Create component-constructor.yaml with the manifest and the chart as resources:

    yaml
    components:
      - name: github.com/my-org/my-service
        version: 1.0.0
        provider:
          name: my-org
        resources:
          - name: my-service-manifest
            type: cloud.konfidence.artifact.manifest
            version: 1.0.0
            relation: local
            input:
              type: file/v1
              path: ./manifest.json
          - name: my-service-chart
            type: helmChart
            version: 1.0.0
            relation: external
            access:
              type: ociArtifact
              imageReference: registry.example.com/my-org/charts/my-service:1.0.0

    The component carries exactly one resource of type helmChart.

Derive every resource name from the release name ​

Several vectors deploy the same chart into one landscape namespace. The deployer gives each deployment its own release name. Every resource in the chart must derive metadata.name from that release name, either directly or through the chart's fullname helper. A hard-coded name collides when a second vector deploys the chart.

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-config

The fullname helper that helm create generates works as well:

yaml
metadata:
  name: {{ include "my-service.fullname" . }}

Do not hard-code names:

yaml
metadata:
  name: my-service-config

Do not set metadata.namespace in templates. The deployer installs every release into the landscape namespace.

The deployer owns the release itself: its name, its namespace, and its labels. Everything in the chart is duplicated per instance. Deliver resources that must exist once per cluster, such as a CustomResourceDefinition, through a separate delivery path.

Fields the deployer sets on the HelmRelease

The deployer creates one Flux HelmRelease per artifact instance and sets these fields. Your chart cannot override them.

FieldValue
metadata.nameThe ArtifactDeployment name
spec.releaseNameThe ArtifactDeployment name
spec.chart.spec.sourceRefThe HelmRepository with the same name
spec.targetNamespaceThe landscape namespace
spec.storageNamespaceThe landscape namespace
spec.commonMetadata.labelskonfidence.cloud/artifact-deployment=<artifact-deployment-name>

The release name is deterministic per component, version, allowReuse setting, and VectorDeployment.

Verify the result ​

Render the chart twice with different release names and compare the resource names. This is the check the deployer relies on.

bash
helm template vector-a ./my-service | grep '^  name:'
helm template vector-b ./my-service | grep '^  name:'

Every name in the first output starts with vector-a, and every name in the second output starts with vector-b. A name that appears unchanged in both outputs is hard-coded and must derive from the release name.

Next steps ​

Use the following guides to publish your artifact and expose its Service:

EU and German government funding logos

Funded by the European Union – NextGenerationEU.

The views and opinions expressed are solely those of the author(s) and do not necessarily reflect the views of the European Union or the European Commission. Neither the European Union nor the European Commission can be held responsible for them.