zero-scale-bootstrap #1

Open
steve wants to merge 0 commits from zero-scale-bootstrap into master
Owner
No description provided.
steve added 10 commits 2026-10-27 07:24:59 -04:00
- internal/appname: one naming rule (first label, lowercased, [a-z0-9] only)
- internal/registry: host -> app cache built from zero-scale-app ConfigMaps
  (hosts key), with direct and legacy-name fallbacks and a 10s TTL
- gateway: units, binaries and config keyed by the app's canonical host, so
  secondary hostnames share one process and one config
- reaper reads app config from the registry instead of the API every tick
- zero-scale-ctl writes a hosts key and uses the shared naming rule
- internal/platform: detect and grade storage classes (Longhorn, Ceph, Mayastor,
  LINSTOR, Portworx, GKE/Azure/AWS, NFS, local), Postgres operators (CNPG,
  Zalando, Crunchy, Percona, StackGres), MySQL operators (InnoDB Cluster, PXC,
  MariaDB, legacy shared-mysql), ingress classes, gateways and Redis
- Choose picks HA candidates (default class wins, ambiguity is an error with
  the flag to resolve it) and stores them as flat zero-scale-platform keys
- zero-scale-ctl doctor (read-only) and init (diff, confirm or --yes)
- DB provisioning goes through per-operator adapters; SQL travels on stdin,
  the MySQL admin password is read from a Secret and sent on stdin, and
  identifiers and passwords are validated
- Postgres endpoint now names the namespace the cluster is in (was the app's)
- Redis service, ingress class and config-file DB hosts come from the platform
- Legacy fallback with a warning when no platform ConfigMap exists
- Plans are printed first and applied only with --yes; Helm when available,
  otherwise the pinned release manifests (Longhorn 1.9.1, CNPG 1.26.0 /
  chart 0.24.0, all overridable)
- Replica counts follow schedulable nodes (max 3) with an HA warning below 3
- Longhorn: longhorn-ha (RWO) and longhorn-ha-rwx StorageClasses with Retain,
  optional default-class flag, optional backup target with daily snapshot and
  weekly backup RecurringJobs; existing installs only get the classes
- Postgres: CNPG operator (skipped when present) and a Cluster with pod
  anti-affinity, superuser access for provisioning, and a Ready wait
- Both record their result in the zero-scale-platform ConfigMap
- gateway install/upgrade renders an HA gateway (2 replicas, RollingUpdate,
  PDB, hostname spread, downward-API namespace, RWX /opt/apps on the platform
  class); a Helm-managed gateway is recorded and left alone
- gateway status shows which apps run on which replica
- ingress add-host/remove-host/list: one Ingress per host or wildcard, TLS
  from a Secret or a cert-manager ClusterIssuer (wildcards require DNS-01),
  upstream-hash-by $host pinning; hosts stored in the platform ConfigMap
- apply skips the per-app Ingress when routed hosts already cover the app
  in the gateway's namespace and no OAuth is used; per-app Ingresses also pin
  by host
- status, logs and binary updates reach every gateway replica
- delete-app --purge [--drop-database]; Postgres drops only databases whose
  owner comment matches; apply records database_engine for later cleanup
Apps declare volumes: name:/path[:ro] (mounts: still accepted). The gateway
binds /srv/zero-scale-volumes/<app>/<name> into the unit, running it as a
fixed zs-<app> dynamic user so ownership is stable. gateway install creates
zero-scale-volumes-pvc; delete-app --purge --delete-volumes removes the data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uKdmp7tLySXvQXALz2x9V
env create/delete/gc/list manage a namespace per environment, labelled
zero-scale.io/env, with a ResourceQuota, its own gateway and an optional
wildcard route. A zero-scale-env ConfigMap records the env and may override
the platform's database clusters. Hosts use ${ENV_SUFFIX}; databases in a
non-primary env are named db_<env>_<app>_<hash> and carry an owner comment,
so env delete drops only what the env owns. oauth-setup --auth-host serves
every app's login from one callback host. deploy/ manifests no longer
hardcode a namespace; deploy/kustomization.yaml sets it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uKdmp7tLySXvQXALz2x9V
install postgres --env <name> creates the CNPG cluster inside the
environment's namespace (without re-applying the namespace, which would
drop its labels) and records it in that env's zero-scale-env ConfigMap
instead of the platform ConfigMap. The default env quota now leaves room
for a two-instance cluster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uKdmp7tLySXvQXALz2x9V
The gateway runs as a systemd service, so it never saw the pod's
POD_NAMESPACE or IDLE_TIMEOUT: a gateway in qa read app ConfigMaps from
default and started apps without volumes, database env or their idle
timeout. The unit now passes those variables on, and the gateway falls
back to PID 1's environment and the service account namespace. The
effective default idle timeout stays 10s.

A one-replica gateway gets maxUnavailable: 1 instead of a PDB that blocks
node drains. status, logs, list-apps and delete-app accept -n/--namespace
(logs keeps a numeric -n as the line count). --expand is documented as
writing YAML alongside a real apply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uKdmp7tLySXvQXALz2x9V
List every Ingress backend whose running pods sit on one node (or have
none), Services whose externalIPs claim a node's own address (which
steals that node's ingress traffic, as kourier does with .134 today),
and more than one default StorageClass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uKdmp7tLySXvQXALz2x9V
StorageClasses that keep data on one node's disk (hostpath, local-path,
OpenEBS local PV, Longhorn with 1 replica and strict-local) are now
marked node-local:

- init never records one as platform storage, even with --allow-non-ha.
- doctor lists PVCs on node-local classes that running pods mount. One
  annotated zero-scale.io/data=temporary is a note; one whose workload
  runs on 2+ nodes (a database cluster with a local volume per member)
  is accepted; any other is a failure, and pins its Ingress backend.
- doctor warns when a node-local class is a default StorageClass and
  prints the annotate command that removes the default.
- App volumes take a :tmp mode: scratch space on the gateway pod's own
  disk instead of the shared RWX volume.

doctor also now reports Ingress backends whose Service does not exist,
host+path routed by several Ingresses to different Services, Knative
DomainMappings with no Ingress rule, and judges recorded platform
choices instead of asking for them again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch is already included in the target branch. There is nothing to merge.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin zero-scale-bootstrap:zero-scale-bootstrap
git checkout zero-scale-bootstrap
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: open-cream-cheese/zero-scale-platform#1