highscore.php persists the high score into MySQL — the app connects to the database at mysql.database.svc.cluster.local.
Example snippet from highscore.php showing the connection details:
- GitOps: manifests are tracked in Git and applied declaratively.
- Selective deploy: point Kustomize to only
./databaseso only DB manifests are applied from the infra branch. - Reconciliation and drift detection are handled automatically by Flux.
- Flux GitRepository / Kustomization: https://fluxcd.io
- Kustomize: https://kubectl.docs.kubernetes.io/references/kustomize/
- Sealed Secrets (example encryption): https://github.com/bitnami-labs/sealed-secrets
- Kubernetes concepts: https://kubernetes.io/docs/concepts/
- Application code:
7-demobranch. - Infrastructure manifests (cluster-level):
infrastructurebranch (Sealed Secrets, cert-manager, database, ingress-nginx, etc.)
infrastructure branch:
database/ directory you should find manifests for:
Example plain-text Secret currently in the repo (for demonstration only):
Secrets in plain text in a Git repository are a security risk. We will later encrypt these (for example, with Sealed Secrets — see Introduction to Sealed Secrets in Kubernetes) before storing them in Git.
infrastructure branch and a Kustomization that references only the ./database path. This ensures only the database resources are applied, avoiding cluster-wide changes from other infra manifests.
Example GitRepository manifest (save this as a Flux Source in the flux-system namespace):
flux CLI. Example:
database subdirectory:
path: ./database ensures Flux/Kustomize applies manifests only from the database directory of the infrastructure branch.
Create, reconcile, and verify
After placing infra-source-git.yml and infra-database-kustomize-git-mysql.yml in your Flux cluster manifests repo (for example, block-buster/flux-clusters/dev-cluster) commit and push them. You can then reconcile manually to apply immediately.
Example terminal sequence (switching to the Flux cluster repo and exporting the Git source):
database namespace should be created by Flux:
Pending while PVs are provisioned. Example:
- Deployment/Pod status:
kubectl -n database get pods,deploy - Service:
kubectl -n database get svc mysql(ClusterIP, port 3306) - PVC / PV is
Boundif using dynamic storage:kubectl -n database get pvc - ConfigMap initialization scripts applied and Secret exists (but remember it’s currently plain text)
- View pod logs:
kubectl -n database logs deploy/mysql - Check PVC status:
kubectl -n database get pvc - Describe pod for events and volume errors:
kubectl -n database describe pod <pod-name>
Tip: If the MySQL pod stays Pending, check your storage class and PV provisioning. Use
kubectl describe pod and kubectl get pvc -o wide to inspect volume binding and related events.- Seal or encrypt Secrets (e.g., Sealed Secrets) and store the sealed manifest in Git rather than plain text.
- Add application Flux sources and Kustomizations that deploy the Block Buster app images (from your OCI registry) against this cluster namespace so the app can connect to
mysql.database.svc.cluster.local. - Monitor Flux reconciliation and application health:
flux get kustomizationskubectl -n <app-namespace> get pods,svc
- Database namespace exists and is Active.
- MySQL pod is Running and Deployment is Available.
- Service
mysqlis a ClusterIP on port 3306. - PVC is Bound and data directory is writable.
- Secrets are sealed/encrypted before committing to Git.
- Flux: https://fluxcd.io
- Kustomize: https://kubectl.docs.kubernetes.io/references/kustomize/
- Sealed Secrets: https://github.com/bitnami-labs/sealed-secrets
- Kubernetes docs: https://kubernetes.io/docs/
- MySQL Docker image: https://hub.docker.com/_/mysql