[

The project uses BundleBee to manage Kubernetes deployment. The monitor is deployed as a CronJob (not a long-running service) since each invocation runs checks and exits.

Architecture

The BundleBee manifest defines two top-level alveoli:

  • applications - the statura application (ServiceAccount, Secret, ConfigMap, CronJob)

  • all - chain of namespace provisioning then application deployment

CronJob

Unlike traditional web services deployed as Deployment + Service, this monitor uses a CronJob:

  • Runs on a configurable schedule (ex: */5 * * * * for every five minutes)

  • Executes all configured checks in parallel using virtual threads

  • Pushes OTEL metrics, then exits

  • Failed jobs are automatically retried (backoffLimit)

  • Finished jobs are cleaned up (ttlSecondsAfterFinished)

Configuration Injection

The configuration is based on two merged datasources:

  • A ConfigMap - see statura.configuration.content placeholder

  • A Secret - see statura.secret.content placeholder, for sensitive values (passwords, authentication, api keys etc...)

Deploy

TIP

the default deployment is based on bundlebee-maven-plugin in the project but it can be adjusted to use plain bundlebee binary as well. A good base to handle environments is in _scripts/deploy.sh script:

#!/usr/bin/env bash
set -euo pipefail

DRY_RUN="${DRY_RUN:-true}"
VERBOSE="${VERBOSE:-false}"
ALVEOLUS="${ALVEOLUS:-all}"
MASTER_KEY="${MASTER_KEY:-notset}"
PLACEHOLDERS_SHARED="${PLACEHOLDERS_SHARED:-shared}"
PLACEHOLDERS_SPECIFIC="${PLACEHOLDERS_SPECIFIC:-dev}"
REGISTRY_KEY="${REGISTRY_KEY:-dev.local}"
REGISTRY_USERNAME="${REGISTRY_USERNAME:-none}"
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-none}"
GOAL="${GOAL:-bundlebee:apply@deploy}"

mvn -f pom.xml \
    -Dbundlebee.kube.dryRun="${DRY_RUN}" \
    -Dbundlebee.kube.verbose="${VERBOSE}" \
    -Dbundlebee.apply.alveolus="${ALVEOLUS}" \
    -Dcipher.masterKey="${MASTER_KEY}" \
    -Dshared.placeholder="${PLACEHOLDERS_SHARED}" \
    -Dspecific.placeholder="${PLACEHOLDERS_SPECIFIC}" \
    -Dregistry.key="${REGISTRY_KEY}" \
    -Dregistry.username="${REGISTRY_USERNAME}" \
    -Dregistry.password="${REGISTRY_PASSWORD}" \
    yupiik-tools:decrypt-properties@shared \
    yupiik-tools:decrypt-properties@specific \
    "${GOAL}"
IMPORTANT

you can refer to crypt-mojos page to see how ciphering is working.

Placeholders

TIP

statura.namespace.disabled can be set to true to not synchronize the namespace and therefore not need the secret credentials to pull the image.

The following placeholders are used by the BundleBee descriptors:

namespace.name*

Target namespace name

registry.key*

Container registry URL/key

registry.password*

Container registry password

registry.username*

Container registry username
statura.affinity

Pod affinity/anti-affinity rules Default: {}.

statura.annotations

Default annotations for all resources Default: {}.

statura.configmap.annotations

ConfigMap annotations Default: {}.

statura.configmap.labels

ConfigMap labels Default: {"app.kubernetes.io/name":"statura"}.

statura.configmap.name

ConfigMap name Default: statura.

statura.configuration.content*

Monitor configuration (data) JSON content (checks, OTEL endpoint, timeouts)

statura.containerSecurityContext

Container-level security context Default: {}.

statura.cronjob.annotations

CronJob resource annotations Default: {}.

statura.cronjob.backoffLimit

Number of retries before marking a job as failed Default: 2.

statura.cronjob.concurrencyPolicy

Concurrency policy (Allow, Forbid, Replace) Default: Forbid.

statura.cronjob.failedJobsHistoryLimit

Number of failed finished jobs to retain Default: 1.

statura.cronjob.imagePullSecrets

Image pull secrets for the pod Default: [].

statura.cronjob.labels

CronJob resource labels Default: {"app.kubernetes.io/name":"statura"}.

statura.cronjob.name

CronJob name Default: statura.

statura.cronjob.podAnnotations

Pod template annotations Default: {}.

statura.cronjob.podLabels

Pod template labels Default: {"app.kubernetes.io/name":"statura"}.

statura.cronjob.restartPolicy

Pod restart policy (OnFailure, Never) Default: OnFailure.

statura.cronjob.schedule

Cron schedule expression (standard cron format) Default: */5 * * * *.

statura.cronjob.startingDeadlineSeconds

Deadline for starting a job if it misses its scheduled time Default: 120.

statura.cronjob.successfulJobsHistoryLimit

Number of successful finished jobs to retain Default: 3.

statura.cronjob.ttlSecondsAfterFinished

TTL for cleaning up finished jobs Default: 300.

statura.image.pullPolicy

Image pull policy Default: IfNotPresent.

statura.image.repository

Container image repository Default: statura.

statura.image.tag

Container image tag Default: 1.0.4.

statura.labels

Default labels for all resources Default: {}.

statura.name

Application name Default: statura.

statura.namespace

Target Kubernetes namespace Default: statura.

statura.nodeSelector

Node selector for scheduling Default: {}.

statura.podSecurityContext

Pod-level security context Default: {}.

statura.resources

Container resource requests and limits Default: {}.

statura.secret.annotations

Secret annotations Default: {}.

statura.secret.content

Content (data) of the secret - mainly for passwords/API keys etc... Note that you cna use bundlebee base64 function to format it as expected by kubernetes. Default: .

statura.secret.labels

Secret labels Default: {"app.kubernetes.io/name":"statura"}.

statura.secret.mount

Where to mount the secret in the Pod. It is unlikely it needs to be changed. Default: /opt/statura/secrets.

statura.secret.name

Secret name Default: statura.

statura.serviceAccount.annotations

ServiceAccount annotations Default: {}.

statura.serviceAccount.automount

Whether to automount the service account token Default: false.

statura.serviceAccount.labels

ServiceAccount labels Default: {"app.kubernetes.io/name":"statura"}.

statura.serviceAccount.name

ServiceAccount name Default: statura.

statura.tmp.size

Size limit for the emptyDir tmp volume Default: 8Mi.

statura.tolerations

Pod tolerations Default: [].