Skip to content

fix(chart): gate the maintenance cronjob on actual GLPI/DB readiness - #196

Open
danielqb wants to merge 1 commit into
eftechcombr:mainfrom
danielqb:fix/cronjob-wait-glpi-ready
Open

fix(chart): gate the maintenance cronjob on actual GLPI/DB readiness#196
danielqb wants to merge 1 commit into
eftechcombr:mainfrom
danielqb:fix/cronjob-wait-glpi-ready

Conversation

@danielqb

@danielqb danielqb commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Problem

The maintenance CronJob (front/cron.php, schedule every N minutes) is a
normal resource created in the same Sync phase as nginx/php-fpm, without
waiting for the post-install glpi-db-install/glpi-db-configure/
glpi-cache-configure Jobs (which run as Helm hooks, post-install
hook-weight 10/20/30) to finish. On a fresh install, this lets the first
scheduled run(s) fire before GLPI is actually usable, failing with
"Unable to load the GLPI configuration from the database" - self-heals
via Kubernetes' OnFailure retry, but noisy (BackOff events, wasted
retries) on every fresh install.

First attempt (insufficient - documented here for the record)

Initially added an initContainer that waits for
/etc/glpi/config/config_db.php to exist before running cron.php.
Verified empirically on a live kind cluster that this REDUCES but does
NOT eliminate the race: glpi-db-install.sh runs db:install --reconfigure, which writes that same config_db.php file as soon as the
schema is created (hook-weight 10) - well before db:configure/
cache:configure (weight 20/30) finish. Across 4 live re-installs with
just the file-existence check, saw BackOff on roughly half of them,
confirmed via captured pod state: the initContainer completed (file
existed) but the "base" container still failed immediately with "Unable
to load the GLPI configuration from the database".

Actual fix

Replaced the file-existence check with a loop of the exact read-only
command glpi-db-install.sh itself already uses to decide whether the
schema is fully installed: php bin/console database:check_schema_integrity
(exit 0 once GLPI is genuinely ready to serve requests). This requires
switching the initContainer from busybox to the real php-fpm image
(needed for the php binary + GLPI codebase) and giving it the same
glpi-config/glpi-secret/MARIADB_PASSWORD env wiring as the main
container, since the check needs a working DB connection to run.

Testing

  • helm lint --strict: 0 failures
  • helm template: initContainer renders with the php-fpm image and the
    correct env/secretKeyRef wiring
  • Live kind cluster (kindest/node:v1.35.0), schedule accelerated to
    every minute to stress-test the install-time race: 5 consecutive
    fresh install cycles (helm uninstall + delete pvc + fresh helm
    install each time), zero BackOff/failed cronjob events across all 5 -
    compared to a ~50% failure rate observed with the file-existence-only
    check across 4 separate live runs beforehand
  • Confirmed GLPI still serves its real login page (HTTP 200) after each
    install

… not just file existence

## Problem

The maintenance CronJob (front/cron.php, schedule every N minutes) is a
normal resource created in the same Sync phase as nginx/php-fpm, without
waiting for the post-install glpi-db-install/glpi-db-configure/
glpi-cache-configure Jobs (which run as Helm hooks, post-install
hook-weight 10/20/30) to finish. On a fresh install, this lets the first
scheduled run(s) fire before GLPI is actually usable, failing with
"Unable to load the GLPI configuration from the database" - self-heals
via Kubernetes' OnFailure retry, but noisy (BackOff events, wasted
retries) on every fresh install.

## First attempt (insufficient - documented here for the record)

Initially added an initContainer that waits for
`/etc/glpi/config/config_db.php` to exist before running cron.php.
Verified empirically on a live kind cluster that this REDUCES but does
NOT eliminate the race: `glpi-db-install.sh` runs `db:install
--reconfigure`, which writes that same config_db.php file as soon as the
*schema* is created (hook-weight 10) - well before db:configure/
cache:configure (weight 20/30) finish. Across 4 live re-installs with
just the file-existence check, saw BackOff on roughly half of them,
confirmed via captured pod state: the initContainer completed (file
existed) but the "base" container still failed immediately with "Unable
to load the GLPI configuration from the database".

## Actual fix

Replaced the file-existence check with a loop of the exact read-only
command glpi-db-install.sh itself already uses to decide whether the
schema is fully installed: `php bin/console database:check_schema_integrity`
(exit 0 once GLPI is genuinely ready to serve requests). This requires
switching the initContainer from busybox to the real php-fpm image
(needed for the php binary + GLPI codebase) and giving it the same
glpi-config/glpi-secret/MARIADB_PASSWORD env wiring as the main
container, since the check needs a working DB connection to run.

## Testing

- helm lint --strict: 0 failures
- helm template: initContainer renders with the php-fpm image and the
  correct env/secretKeyRef wiring
- Live kind cluster (kindest/node:v1.35.0), schedule accelerated to
  every minute to stress-test the install-time race: 5 consecutive
  fresh install cycles (helm uninstall + delete pvc + fresh helm
  install each time), zero BackOff/failed cronjob events across all 5 -
  compared to a ~50% failure rate observed with the file-existence-only
  check across 4 separate live runs beforehand
- Confirmed GLPI still serves its real login page (HTTP 200) after each
  install
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant