Skip to main content

Charts, images and installation bundle

This page describes where the Helm charts come from, which container images an installation pulls, how to mirror the images into a private registry and how to supply pull credentials. Operators use this page to prepare the registry before installation, and for every installation without internet access. Models, packages and air-gapped installs describes the model and package images in detail.

Charts​

ChartVersionApplication versionInstalls
foundation4ai-core0.3.00.3.0NATS JetStream, Valkey, Prometheus and optionally PostgreSQL, from packaged dependency charts
foundation4ai0.3.00.3.0The API server, workers, dashboard and installation Jobs, from the api-server and dashboard dependency charts

The charts come from one of two sources:

  • Deployment files. The directories charts/foundation4ai-core and charts/foundation4ai of the deployment files supplied by the Foundation4 provider. Commands refer to the charts by path, such as ./charts/foundation4ai-core.
  • Registry references. Chart references in an Open Container Initiative (OCI) registry, supplied by the Foundation4 provider. Commands refer to the charts by reference, such as oci://<chart registry>/<chart path>/foundation4ai-core, with --version 0.3.0.

The charts include every dependency chart. Installation runs no helm dependency command and needs no access to public chart repositories.

Confirm the chart version before installation:

helm show chart ./charts/foundation4ai-core
helm show chart ./charts/foundation4ai

Expected result: each output contains version: 0.3.0 and appVersion: 0.3.0.

For OCI references, log in to the chart registry and pull both charts into the working directory:

helm registry login <chart registry>
helm pull oci://<chart registry>/<chart path>/foundation4ai-core --version 0.3.0 --untar --untardir charts
helm pull oci://<chart registry>/<chart path>/foundation4ai --version 0.3.0 --untar --untardir charts

Expected result: Login Succeeded, then the directories charts/foundation4ai-core and charts/foundation4ai. The installation commands then use the same paths as with the deployment files.

Foundation4 images​

The application release pulls three Foundation4 images and, when configured, model and package images.

ImageRuns asRepository valueTag value
API serverAPI server, workers and the installation Jobsapi-server.image.repositoryglobal.serverImageTag, or api-server.image.tag
gRPC serviceSidecar container (a second container in the same pod) in the API server and worker podsapi-server.image.repositoryGrpcglobal.grpcImageTag, or api-server.image.tagGrpc
DashboardDashboarddashboard.image.repositoryglobal.dashboardImageTag, or dashboard.image.tag
Model imagesImage volumes with model filesapi-server.models[].image.referencePart of the reference
Package imagesImage volumes with Python packages for the gRPC serviceapi-server.packages[].image.referencePart of the reference

The following rules apply to the Foundation4 images:

  • Tags required. The three tag values have no default. A missing tag produces an image reference that ends in a colon, and the pods fail with InvalidImageName.
  • Repositories required. The chart defaults name the provider's registry. The values file sets every repository to the registry that the cluster pulls from.
  • Pull policy. api-server.image.pullPolicy applies to the API server, worker, gRPC service and Job containers; dashboard.image.pullPolicy applies to the dashboard. Model and package images take image.pullPolicy from their own entry. Both chart values default to IfNotPresent.
  • Architecture. The images are built for amd64 nodes.

Core release images​

The core release pulls the following public images. The table lists each image without a registry host; the source column names the public registry.

ImageComponentSourceRegistry value
nats:2.12.4-alpineNATS JetStream serverDocker Hubglobal.image.registry
natsio/nats-server-config-reloader:0.21.1NATS configuration reloaderDocker Hubglobal.image.registry
natsio/nats-box:0.19.3NATS utility podDocker Hubglobal.image.registry
valkey/valkey:9.0.1Redis-compatible cacheDocker Hubglobal.imageRegistry
prometheus/prometheus:v3.9.1Prometheus serverQuayprometheus.server.image.repository, which includes the registry
prometheus-operator/prometheus-config-reloader:v0.89.0Prometheus configuration reloaderQuayprometheus.configmapReload.prometheus.image.repository, which includes the registry
pgvector/pgvector:pg18-trixieBundled PostgreSQL, evaluation profile onlyDocker Hubpostgres.image.registry

The image list changes with the chart version. The following command prints the name and application version of each dependency chart in the supplied core chart:

for c in charts/foundation4ai-core/charts/*.tgz; do
helm show chart "$c" | grep -E '^(name|appVersion):'
done

Expected result: the names nats, postgres, prometheus and valkey, each with an application version.

Test and utility images​

Two further sets of images are pulled only on demand:

  • Helm tests. helm test foundation4ai-core starts a NATS test pod from the NATS utility image, with the registry value and pull secrets of NATS, and a Valkey test pod. The Valkey test pod uses valkey/valkey without the registry value and without pull secrets, so the Valkey test fails where the cluster cannot reach Docker Hub.
  • Recipe checks. The just check recipe starts pods from the public images natsio/nats-box:latest, redis:alpine and curlimages/curl. The recipe is not usable where the cluster cannot reach Docker Hub.

Mirroring to a private registry​

A cluster without internet access, or with a registry policy, pulls every image from a private registry. Copy each image of the two tables above into the registry with the same repository path and tag, for example with skopeo:

skopeo copy docker://<source registry>/<repository>:<tag> docker://<registry>/<repository>:<tag>

Expected result: Writing manifest to image destination for each image.

Then override the registry of each image in the values file:

global:
image:
registry: <registry>
imageRegistry: <registry>
serverImageTag: "<api server image tag>"
grpcImageTag: "<grpc service image tag>"
dashboardImageTag: "<dashboard image tag>"

prometheus:
server:
image:
repository: <registry>/prometheus/prometheus
configmapReload:
prometheus:
image:
repository: <registry>/prometheus-operator/prometheus-config-reloader

postgres:
image:
registry: <registry>

api-server:
image:
repository: <registry>/foundation4ai-api
repositoryGrpc: <registry>/foundation4ai-grpc

dashboard:
image:
repository: <registry>/foundation4ai-dashboard

The values set the following:

  • NATS. global.image.registry applies to the NATS server, the configuration reloader and the NATS utility pod.
  • Valkey. global.imageRegistry applies to the Valkey image.
  • Prometheus. The Prometheus repositories include the registry, so the values replace the full repository path.
  • PostgreSQL. postgres.image.registry applies to the bundled PostgreSQL. The production profile does not install the image.
  • Foundation4 images. The repository names follow the naming of the provider's registry; the mirrored names can differ.

After installation, kubectl -n foundation4ai get pods -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' lists every image in use. Expected result: every image starts with the private registry.

Pull credentials​

Create an image pull secret in the namespace foundation4ai from a Docker configuration file that holds the registry credentials:

kubectl -n foundation4ai create secret generic <pull secret> \
--type=kubernetes.io/dockerconfigjson --from-file=.dockerconfigjson=<docker config file>

Expected result: secret/<pull secret> created.

Each chart reads pull secrets from a different value, in one of two formats:

global:
imagePullSecrets:
- name: <pull secret>
image:
pullSecretNames:
- <pull secret>

redis:
imagePullSecrets:
- <pull secret>

prometheus:
imagePullSecrets:
- name: <pull secret>

postgres:
imagePullSecrets:
- name: <pull secret>

The values apply as follows:

  • Foundation4 pods. global.imagePullSecrets applies to the API server, worker, Job and dashboard pods. The API server pod also receives each imagePullSecrets entry of api-server.models and api-server.packages; the worker pod does not. A secret for model or package images is therefore listed in global.imagePullSecrets as well.
  • NATS. global.image.pullSecretNames is a list of secret names.
  • Valkey. redis.imagePullSecrets is a list of secret names. Valkey also reads global.imagePullSecrets as a list of names, so the name entries set for the Foundation4 pods produce an unusable extra entry in the Valkey pod. Pulls succeed when the redis.imagePullSecrets entry is present.
  • Prometheus and PostgreSQL. prometheus.imagePullSecrets and postgres.imagePullSecrets are lists of name entries.
  • Node credentials. Where the platform provides registry credentials on the nodes, such as a kubelet credential provider, the pull secrets are not needed.

The public core images need no pull secrets. The core values apply only where the core images are mirrored into a registry that requires credentials.

Expiring registry tokens​

Some cloud registries issue pull tokens that expire, for example after 12 hours. A pull secret that holds such a token stops working at expiry. Pods that are already running continue, but every new pull fails with ImagePullBackOff: a rescheduled pod, a new replica, or the installation Jobs of the next helm upgrade.

One of the following arrangements keeps pulls working:

  • Node credentials. The kubelet obtains registry credentials from the platform, and the pull secrets are omitted.
  • Token refresh. A scheduled process replaces the content of the pull secret before the token expires.
  • Long-lived credentials. The registry issues credentials that do not expire, such as a robot account or a mirror inside the cluster network.

Local images on a single node​

An evaluation installation can run without a registry by loading the images onto the node and setting the pull policy to Never. The kubelet then starts a container only from an image already present on the node, and a missing image fails with ErrImageNeverPull. The pattern therefore suits a single node only: every image must exist on every node that can run the pod.

On k3s, import each image archive into the container runtime of the node:

sudo k3s ctr images import <image archive>

Expected result: the output names the imported image reference.

Set pullPolicy: Never in api-server.image.pullPolicy, dashboard.image.pullPolicy and the image.pullPolicy of each model and package entry. The core images keep the default IfNotPresent, which uses an image present on the node without pulling. Install for evaluation describes the evaluation installation.

Installation bundle​

The Foundation4 provider can supply the installation files as a bundle: the deployment files with both charts, image archives and example values. The bundle format is not yet confirmed. The following steps apply to any bundle:

  1. Verify the bundle against the checksum file supplied with the bundle before extracting the bundle.

    sha256sum -c <checksum file>

    Expected result: <bundle file>: OK.

  2. Extract the bundle into an empty working directory, with the tool that matches the archive format. For a compressed tar archive:

    tar -xzf <bundle file> -C <working directory>

    Expected result: the working directory contains the deployment files, including both charts.

  3. Load each image archive into the private registry, or onto the node for a single-node evaluation.

    skopeo copy docker-archive:<image archive> docker://<registry>/<repository>:<tag>

    Expected result: Writing manifest to image destination for each archive.

Do not use the example values of a bundle unchanged. The example values point at the provider's registry and can enable debug logging.