How to persistently override the APMIA MySQL extension schema.json on Kubernetes (ConfigMap + subPath)?
When you customize the APMIA MySQL extension's schema.json on Kubernetes (for example, to add Galera/wsrep metrics), editing the file directly inside the Pod with "kubectl exec" is non-persistent. When the Pod restarts or is rescheduled it pulls the original container image and reverts every manual change.
This article describes how to override schema.json persistently using a Kubernetes ConfigMap mounted with subPath, so that only that single file is replaced and the change survives Pod recycles, node failures, and rollouts.
APMIA MySQL extension build 25.x or 26.x.
Kubernetes (any distribution). The Deployment may optionally be managed by Helm.
The container filesystem is ephemeral. A change made with "kubectl exec" lives only in the running container layer; on restart or reschedule the Pod is recreated from the image and the original schema.json is restored. A persistent, declarative override is required.
Inject the customized schema.json externally through a ConfigMap and mount it over the target file using subPath. subPath overwrites ONLY that one file and leaves all other adjacent configuration files in the directory untouched.
Step 1: Identify the REAL target path
The MySQL extension ships as a bundle (BOOT_LOAD=MySQL) that unpacks on first boot into a hash/version-named directory. The path is NOT a fixed name such as extensions/MySQL/config and it is NOT core/config. Let the Pod boot once, then find the actual file:
kubectl exec -n <namespace> deploy/<apmia-deployment> -- sh -c 'find / -name schema.json 2>/dev/null | grep -i mysql'
Typical result:
/opt/apmia/apmia/extensions/mysql-<hash>-<version>/config/schema.json
The base directory and the hash vary by image build - always confirm before mounting.
Step 2: Create the ConfigMap
Build the ConfigMap from your edited local schema.json. For the Galera/wsrep use case, use the flavor-correct variant: performance_schema.global_status for MySQL 8 / Percona, information_schema.GLOBAL_STATUS for MariaDB.
kubectl create configmap apmia-schema-config --from-file=schema.json=./schema.json -n <namespace>
Step 3: Update the Deployment manifest
Add a volume that points to the ConfigMap and a volumeMount that targets the exact file path from Step 0, using subPath. Note: mountPath is the FULL FILE PATH (ending in /schema.json), and subPath is a sibling of name/mountPath.
spec:
template:
spec:
containers:
- name: apmia-mysql-monitor
image: <your-apmia-image>
volumeMounts:
- name: schema-volume
mountPath: /opt/apmia/apmia/extensions/mysql-<hash>-<version>/config/schema.json
subPath: schema.json
volumes:
- name: schema-volume
configMap:
name: apmia-schema-config
items:
- key: schema.json
path: schema.json
Step 4: Apply and roll out
kubectl apply -f deployment.yaml
kubectl rollout restart deployment/<apmia-deployment> -n <namespace>
Step 5: Validate
Confirm the file inside the new Pod:
kubectl exec -it <new-pod> -n <namespace> -- cat /opt/apmia/apmia/extensions/mysql-<hash>-<version>/config/schema.json
Then check the metrics in the SaaS (Galera/wsrep use case):
MySQL Databases | <host> | <instanceName> | Replication | Galera | *
Future updates
subPath mounts do NOT auto-refresh when the ConfigMap changes. To change the schema later, update the ConfigMap and force a rolling restart:
kubectl create configmap apmia-schema-config --from-file=schema.json=./schema.json -n <namespace> --dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deployment/<apmia-deployment> -n <namespace>
SubPath overwrites only the single file. WITHOUT subPath, mounting a ConfigMap at the directory replaces the entire directory contents and breaks the extension.
Boot/unpack ordering: because the extension unpacks at first boot, let the Pod start once before applying the mount, so the target directory and its sibling files already exist. Pre-mounting over a directory that does not exist yet can make the extension skip the unpack and fail to load.
Helm-managed deployments: if the Deployment is managed by Helm, a manual kubectl edit is reverted on the next "helm upgrade".
Rollback: keep the original schema.json. To revert, remove the volume and volumeMount and roll out the deployment again.