Moodle Dev Fleet Deployment¶
This bundle deploys the development Moodle environment with the local
gem-moodle Helm chart. The chart renders the Moodle web pods, MariaDB, Redis, cron,
PVCs, service accounts, service, and ingress.
Table Of Contents¶
[[TOC]]
Fleet Layout¶
Fleet applies the bundle from moodle-dev/fleet.yaml into the moodle-dev
namespace. The bundle depends on the namespace and secret bundles first:
moodle-dev/namespace: creates the namespace.moodle-dev/secrets: creates the Moodle, MariaDB, and registry secrets.moodle-dev: deploys the local Helm chart from this directory.moodle-dev/websocket: deploys the websocket service as a separate Fleet bundle.
The Helm release name is moodle, so the main resources are named from that
release, for example moodle, moodle-mariadb, moodle-redis, and
moodle-cron.
Runtime Shape¶
The main moodle Deployment contains two containers in the same pod:
moodle: nginx on port 8080. It serves HTTP and proxies PHP requests to the local FPM container.fpm: Moodle PHP-FPM on port 9000. It runs the Moodle install or upgrade bootstrap before starting PHP-FPM.
External traffic flows through the ingress to the moodle service, then to the
nginx container. Nginx forwards PHP requests to 127.0.0.1:9000 inside the same
pod.
Supporting resources:
moodle-mariadb: MariaDB StatefulSet for the Moodle database.moodle-redis: Redis StatefulSet for Moodle sessions.moodle-cron: Kubernetes CronJob that runs Moodle cron.moodle-moodle: shared Moodle data PVC, mounted at/var/www/moodledata.data-moodle-mariadb-0: MariaDB StatefulSet PVC.data-moodle-redis-0: Redis StatefulSet PVC.
Images and Hostname¶
The development values use the custom GEM images:
- PHP-FPM image:
registry.gem.mintfit.hamburg/development/moodle:latest-dev - nginx image:
registry.gem.mintfit.hamburg/development/moodle/nginx:latest-dev
The public Moodle URL is configured as:
https://moodle-development.gem.mintfit.hamburg
Change these settings in moodle-dev/values.yaml, commit the change, and let
Fleet reconcile the bundle.
Startup and Upgrade Handling¶
The chart mounts bootstrap scripts from a ConfigMap into the FPM and cron containers.
During FPM startup the chart:
- Configures PHP-FPM.
- Prepares Moodle data and local cache directories.
- Waits for MariaDB.
- Acquires a MariaDB advisory lock.
- Creates or updates
config.php. - Injects chart-managed Moodle config, including local cache and Redis session settings.
- Runs Moodle install or upgrade unless
moodle.skipUpgradeistrue. - Waits for Redis when Redis is enabled.
- Starts PHP-FPM.
The MariaDB advisory lock serializes install and upgrade work, so multiple web replicas do not run Moodle maintenance at the same time.
Persistence and Data Safety¶
The chart uses stable PVC names and does not pin a cluster-specific
volumeName. That keeps the chart portable across clusters and storage setups.
The Moodle data PVC is annotated with helm.sh/resource-policy: keep, so Helm
does not delete it during normal release removal. MariaDB and Redis use
StatefulSet volume claim templates.
Changing the chart and redeploying should not delete Moodle data or the Moodle
database PVCs. Still create a snapshot or backup before destructive operations,
storage class changes, namespace deletion, or manual PVC/PV cleanup. For
important production-like data, the backing PV reclaim policy should be
Retain.
Multiple Replicas¶
The Moodle web Deployment intentionally does not render spec.replicas. This
allows Rancher to manage the replica count from the UI without Fleet resetting it
on every reconciliation.
The setup supports multiple Moodle web replicas because:
- Moodle data uses a
ReadWriteManyPVC. - Moodle sessions are stored in Redis.
- Local cache is kept per pod in
/tmp/moodle-localcache. - FPM has its own readiness probe, so a pod is not marked ready while nginx is up but PHP-FPM is still starting.
- Install and upgrade work is protected by a MariaDB advisory lock.
Only scale the moodle Deployment. Do not scale moodle-mariadb or
moodle-redis; both are single-replica StatefulSets in this chart.
To scale from the command line:
kubectl scale deployment/moodle -n moodle-dev --replicas=2
The same change can be made in Rancher by scaling the moodle Deployment in the
moodle-dev namespace.
Redis¶
Redis is enabled by default and is used for Moodle sessions. The bootstrap script
injects the Redis session settings into config.php.
This chart currently configures Redis for sessions only. Moodle MUC cache stores and locking can still be tuned separately in Moodle if needed.
Cron¶
Moodle cron is run by a Kubernetes CronJob named moodle-cron.
Current defaults:
cron:
enabled: true
schedule: "*/1 * * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
startingDeadlineSeconds: 300
The CronJob runs:
php admin/cli/cron.php --keep-alive=0
--keep-alive=0 makes each Kubernetes CronJob execution run once and exit.
concurrencyPolicy: Forbid prevents Kubernetes from starting a new cron pod
while the previous one is still running.
The Moodle administration UI controls Moodle's internal scheduled tasks. It does
not change the Kubernetes CronJob schedule, resource limits, history limits, or
concurrency policy. Change those settings in moodle-dev/values.yaml.
Local Validation¶
Run these commands before committing chart changes:
cd moodle-dev
helm lint . -f values.yaml
helm template moodle . -n moodle-dev -f values.yaml
helm template moodle . -n moodle-dev -f values.yaml > /tmp/moodle-dev-rendered.yaml
kubectl apply --dry-run=server -n moodle-dev -f /tmp/moodle-dev-rendered.yaml
The server-side dry run requires access to the target cluster.
Inspecting the Deployment¶
Useful status commands:
kubectl get deploy,statefulset,cronjob,pod,pvc -n moodle-dev
kubectl get ingress -n moodle-dev
kubectl get job,pod -n moodle-dev -l app.kubernetes.io/name=moodle-cron
Useful logs:
kubectl logs -n moodle-dev deploy/moodle -c fpm --tail=100
kubectl logs -n moodle-dev deploy/moodle -c moodle --tail=100
kubectl logs -n moodle-dev job/<cron-job-name> --tail=100
For a specific pod:
kubectl describe pod -n moodle-dev <pod-name>
kubectl logs -n moodle-dev <pod-name> -c fpm --tail=100
kubectl logs -n moodle-dev <pod-name> -c moodle --tail=100
Operational Notes¶
Edit moodle-dev/values.yaml for normal configuration changes, then commit and
push so Fleet reconciles the desired state. Avoid long-lived manual edits to
rendered Kubernetes resources because Fleet will continue reconciling from Git.
The current FPM and cron image startup still runs as root because the image
prepares files and ownership at container startup. That can trigger warnings in
namespaces enforcing the Kubernetes restricted Pod Security profile. A full
fix requires changing the image and startup flow to run without root privileges.
If Moodle cron fails on an old ad-hoc task from a removed plugin or failed copy operation, fix the stale task in Moodle or the Moodle database. That is application data, not a chart scheduling problem.