Kubernetes storage and ownership
Mobilis generates a project once. Its YAML, Dockerfiles, application source and build plans then belong to the user. No Mobilis registry, running process, reconciliation loop, pruning policy or upgrade system is involved.
Storage declarations
Realized resources declare logical storage with declare_storage(name, path, size: "1Gi", fs_group: nil). Names and paths must be unique per resource. The path is the same in all environments; existing Compose bind mounts are unchanged. The generator uses the existing realized test environment to choose emptyDir; development and production use ReadWriteOnce PVCs with no explicit StorageClass. The optional filesystem group supports images running as non-root users.
Declarations currently cover PostgreSQL, MySQL, Redis's on-disk data, SeaweedFS, GoAWS, Grafana, Loki, Prometheus, and Alloy's collector state. Jaeger continues to use its upstream in-memory backend; its historical traces are not durable. App and OTEL Collector receive no unnecessary state claims. Storage durability preserves committed files; it does not change an application's flush/commit rules.
Claims are named <project>-<environment>-<service>-<storage>, for example initial-dev-app-db-data. Ambiguous derived claim identities are rejected before artifact emission. Generated Rails master keys are resolved into container environment values, so production boot does not require files on the generator host. As with the existing demo database passwords, keep the generated YAML private. Database and telemetry configuration remains embedded in ConfigMaps. No required data is mounted from the generator host.
Actual Devastation / Kind boundary
Inspection of the running kind-devastation cluster on 2026-10-09 found:
- Default StorageClass
standard, provisionerrancher.io/local-path, binding modeWaitForFirstConsumer, reclaim policyDelete. - Provisioner data directory
/var/local-path-provisionerinside the Kind node. - The node's
/varis an anonymous Docker local volume, stored under/var/lib/docker/volumes/…/_dataon the laptop. It is not remote storage. - The provisioner creates directories with mode 0777 and removes a volume's directory during teardown. The current node restart policy is
on-failure:1. - Devastation's optional extraMounts include separate application storage; they do not relocate this default provisioner directory.
| Operation | dev/prod declared state | test emptyDir state |
|---|---|---|
| Container restart in the same pod | Preserved | Preserved |
| Pod deletion/recreation | Preserved while claim/PV survive | Discarded |
| Deployment rollout | Preserved while claim/PV survive | Discarded |
| Restart the existing Kind node/container | Preserved with the same Docker volume | No durability promise; depends on whether the pod survives |
| Laptop reboot | Preserved if Docker storage and the same node survive; runtime may need starting | No durability promise |
| Kind cluster recreation | Not guaranteed; claims, bindings and node identity are destroyed | Discarded |
| Namespace deletion | Claims deleted; default Delete policy removes backing data | Discarded |
| PVC deletion | Default Delete policy removes backing data | Not applicable |
| Underlying Docker volume/disk deletion | Lost | Lost |
A surviving Docker directory after cluster destruction is not a supported restore contract. Mobilis does not preserve data across deliberate storage destruction, provision StorageClasses, manage disks, or provide backups.
Ownership and independent deployment
Every emitted object, including Namespace, PVC and Istio objects, has app.kubernetes.io/managed-by=mobilis, mobilis.io/project, and mobilis.io/environment. Service-owned objects and pod templates also have mobilis.io/service. The namespace and shared Gateway belong to the environment. Provisioner-created PVs and Istio-created objects are substrate/controller output, not objects generated by Mobilis.
Shared Compose service fragments also carry project and service ownership labels; Compose supplies its own environment-scoped project labels at runtime. Existing Compose mounts, ports, dependencies and image naming remain unchanged.
Mobilis-built Dockerfiles carry org.opencontainers.image.vendor=Mobilis, mobilis.project, and mobilis.service. Kubernetes build plans additionally declare mobilis.environment and pass those labels to ordinary Docker builds. Third-party images are neither rebuilt nor relabeled. Project-scoped registry repositories remain registry.deva.station/<project>/<service>:<environment>.
For a generated initial project, from its root:
docker build --label mobilis.environment=dev -t registry.deva.station/initial/app:dev ./app
docker push registry.deva.station/initial/app:dev
kubectl --context kind-devastation apply -f kubernetes/dev/resources.yml
kubectl --context kind-devastation -n initial-dev rollout status deployment --timeout=300s
kubectl get namespaces,deployments,services,configmaps,serviceaccounts,roles,rolebindings,pvc,gateways.networking.istio.io,virtualservices.networking.istio.io -A -l mobilis.io/project=initial
kubectl get namespaces,deployments,services,configmaps,serviceaccounts,roles,rolebindings,pvc,gateways.networking.istio.io,virtualservices.networking.istio.io -A -l mobilis.io/project=initial,mobilis.io/environment=dev
docker image inspect registry.deva.station/initial/app:dev --format '{{json .Config.Labels}}'kubectl get all covers workloads/services, but does not enumerate all the kinds above. Use explicit kinds for complete discovery. The shared Devastation DNS, Istio ingress, registry trust, and default provisioner must already exist.
Demo verification
The updated initial demo adds PostgreSQL as Rails's primary database and a DurabilityRecord model and explicit migration artifact. No database needs to run to scaffold that model. Existing public endpoint, trace, metric, log and private infrastructure checks remain in the read-only verifier. Ownership checks compare the generated YAML with project-only and environment-specific Kubernetes queries.
MOBILIS_ARTIFACT_ROOT=/path/to/generated/project ruby scripts/kubernetes/verify.rb
ruby scripts/kubernetes/verify_storage.rb --replace-pod
MOBILIS_ENV=test ruby scripts/kubernetes/verify_storage.rb --replace-podThe separate storage experiment explicitly writes a marker and replaces only the selected demo database pod. Dev/prod must retain the marker; test must start with an empty schema. It does not deploy artifacts, patch resources, run migrations, or repair the test database afterward. Perform telemetry verification before discarding the test database. Recreating a disposable test universe is the user's standard-tooling lifecycle.
For an intentional rollout or restart of the shared local runtime, bracket the operation with verify_storage.rb --write and verify_storage.rb --check. A Kind node restart affects every workload on the shared node; it is not part of the automatic verifier. Laptop reboot and destructive cluster/storage tests are not automated. MOBILIS_DEMO_PROJECT allows a fresh demo identity without upgrading an existing universe; its default remains initial and feeds the same DSL project argument. MOBILIS_ENV selects the environment for both verifiers.
The dated verification record includes observed results and the limits of the live tests.