Kubernetes Integration¶
MultiFlexi can execute jobs inside Kubernetes pods using the Kubernetes executor.
When a runtemplate is configured with the Kubernetes executor, the
multiflexi-executor daemon deploys the application’s Helm chart into the
cluster (if not already present) and launches a one-shot pod via
kubectl run --attach. The pod’s standard output is captured and stored in
the database as the job’s stdout value.
Prerequisites¶
The following must be available on the machine that runs the
multiflexi-executor daemon:
kubectl – Kubernetes command-line tool, accessible in
$PATHhelm (v3+) – Helm package manager, accessible in
$PATHkubeconfig – A valid kubeconfig file at
~/.kube/config(relative to the daemon user’s$HOME) or referenced via theKUBECONFIGenvironment variable
The daemon typically runs as the multiflexi system user whose home
directory is /var/lib/multiflexi/. Make sure the kubeconfig is placed at
/var/lib/multiflexi/.kube/config with owner multiflexi and permissions
0600:
sudo mkdir -p /var/lib/multiflexi/.kube
sudo cp /path/to/admin.kubeconfig /var/lib/multiflexi/.kube/config
sudo chown -R multiflexi:multiflexi /var/lib/multiflexi/.kube
sudo chmod 600 /var/lib/multiflexi/.kube/config
A Kubernetes namespace (default multiflexi) must exist in the cluster:
kubectl create namespace multiflexi
Application Configuration¶
Helm Chart Reference¶
Each application that supports Kubernetes execution must declare a Helm chart.
This is stored in the helmchart field of the application record and can be
set in two ways:
Via the application JSON definition – The
kubernetes.helm.chartfield in the*.multiflexi.app.jsonfile is mapped to the databasehelmchartcolumn when imported:{ "kubernetes": { "helm": { "enabled": true, "releaseName": "my-app", "namespace": "multiflexi", "chart": "/path/to/chart-dir", "upgradeInstall": true, "timeoutSeconds": 300, "atomic": false, "wait": true }, "artifacts": { "enabled": true, "outputPath": "result.json", "keepPodOnFailure": false } } }
Import with:
multiflexi-cli application import-json --file=multiflexi/myapp.multiflexi.app.jsonDirect database update – Useful when the chart path needs to differ from the JSON definition (e.g. local path vs. OCI reference):
UPDATE apps SET helmchart='/opt/helm-charts/my-app' WHERE id=23;
The helmchart value can be:
A local filesystem path (e.g.
/opt/helm-charts/my-app)An OCI registry reference (e.g.
oci://ghcr.io/org/charts/my-app)A Helm repository chart name (e.g.
myrepo/my-app)
OCI Image¶
The application must also have an ociimage field set (e.g.
docker.io/vitexsoftware/multiflexi-probe). This image is used by
kubectl run to create the one-shot job pod.
Helm Chart Structure¶
A minimal Helm chart for a MultiFlexi application should include:
ConfigMap – For non-secret environment variables
Secret – For sensitive environment variables (passwords, tokens)
Deployment – Running the application container with
envFromreferencing the ConfigMap and SecretServiceAccount – Optional, for cluster permissions
See the multiflexi-probe project’s helm/ directory for a reference
implementation.
Configuring a RunTemplate¶
Using the CLI¶
Set the executor on an existing runtemplate:
multiflexi-cli runtemplate update --id=158 --executor=Kubernetes
Or create a new runtemplate with the Kubernetes executor:
multiflexi-cli runtemplate create \
--app_id=23 \
--company_id=3 \
--name="Probe via K8s" \
--executor=Kubernetes \
--interv=d \
--cron="0 6 * * *" \
--active=1
Scheduling Immediate Execution¶
multiflexi-cli runtemplate schedule --id=158 --schedule_time=now
When --executor is not provided on the schedule command, the executor
is read from the runtemplate record. The above command will use the
Kubernetes executor that was configured on the runtemplate.
Execution Flow¶
When the multiflexi-executor daemon picks up a job with the Kubernetes
executor, the following steps occur:
Helm status check – Runs
helm status <releaseName> --namespace <ns>to determine whether the application’s Helm release is already deployed in the cluster.Helm pre-deployment (if needed) – If the release is not found, runs
helm upgrade --installusing the chart path from thehelmchartdatabase field with--create-namespace,--wait, and the configured timeout.Pod creation – Runs
kubectl runwith--restart=Never --attachto create a one-shot pod using the application’s OCI image. Environment variables from the runtemplate configuration are passed via--envflags. The command executed inside the pod is the application’sexecutablewith itscmdparams.Output capture – The pod’s stdout and stderr are streamed back through the
kubectl --attachconnection and captured by the executor.Artifact collection (if configured) – If
artifacts.enabledis true in the kubernetes config,kubectl cpis used to copy the output file from the pod to the local filesystem and store it in the MultiFlexi file store.Pod cleanup – The pod is deleted unless
keepPodOnFailureis true and the job failed (non-zero exit code).Database storage – The captured stdout, stderr, exit code, and command line are saved to the job record. The
job.stdoutcolumn contains the full standard output from the pod execution.
Verifying Execution¶
Check the job result:
multiflexi-cli job get --id=159907 --format=json
Key fields to verify:
executor– Should beKubernetesexitcode–0for successstdout– Contains the captured pod outputcommand– Shows thekubectl runcommand that was executed
Check pods in the cluster:
kubectl -n multiflexi get pods
helm -n multiflexi list
Troubleshooting¶
Helm Pre-deployment Fails¶
“path not found” – The
helmchartvalue points to a path the daemon user cannot access. Use a path readable by themultiflexiuser or an OCI chart reference.OCI registry 404/403 – The OCI chart doesn’t exist or requires authentication. Run
helm registry loginas the multiflexi user, or use a local chart path.“cluster unreachable” – The kubeconfig is missing or has wrong permissions. Verify
/var/lib/multiflexi/.kube/configexists and is owned bymultiflexi:multiflexi.
ImagePullBackOff¶
The container image tag in values.yaml doesn’t exist on the registry.
Override the tag during Helm install:
helm upgrade --install my-app ./helm --set image.tag=latest -n multiflexi
Pod Fails to Start¶
Check pod events:
kubectl -n multiflexi describe pod <pod-name>
kubectl -n multiflexi get events --sort-by=.lastTimestamp
Empty stdout in Job Record¶
If the job completes but stdout is empty:
Verify the application writes output to stdout (not just to files)
Check the
stderrfield for error messagesEnsure the Kubernetes executor version includes the stdout capture fix (
jobStdout/jobStderrinstance variables inKubernetes.php)
Executor Not Recognized¶
If scheduling reports Executor: Native despite setting Kubernetes:
Verify the runtemplate was updated:
multiflexi-cli runtemplate get --id=<ID> --format=jsonEnsure
Kubernetes.phpis deployed at/usr/share/php/MultiFlexi/Executor/Kubernetes.phpRestart the executor daemon:
sudo systemctl restart multiflexi-executor