7.3 KiB
Schema — manifests/storageclass/ and manifests/priorityclass/
Cluster-wide singletons. High blast radius — every PVC / scheduling decision in the cluster is affected.
Cross-reference: SANCTITY_RULES R10, coding-guidelines/helm-values.md §persistence.
§StorageClass (manifests/storageclass/*.yaml)
These are repo-global — one StorageClass file is applied to every cluster that consumes it. A wrong reclaim policy or volume-binding mode breaks every new PVC.
Inventory
| File | Backend | Reclaim | Binding | Use case |
|---|---|---|---|---|
pd-standard-retain-dr.yaml |
GCP PD standard | Retain |
WaitForFirstConsumer |
DR-critical state — do not lose data on PVC delete |
sc-pd-ssd.yaml |
GCP PD SSD | Delete |
WaitForFirstConsumer |
Default for write-heavy (etcd, ClickHouse) |
sc-pd-standard.yaml |
GCP PD standard | Delete |
WaitForFirstConsumer |
Default for read-heavy / archival |
sc-filestore-standard.yaml |
GCP Filestore | varies | varies | Shared ReadWriteMany volumes (Jenkins build cache, JFrog filestore) |
Schema
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: sc-pd-ssd # MUST match filename
annotations:
storageclass.kubernetes.io/is-default-class: "false" # exactly one default per cluster
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-ssd
reclaimPolicy: Delete # Delete | Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
| Field | Convention | Notes |
|---|---|---|
metadata.name |
matches filename (without .yaml) |
Helm values reference by name. |
metadata.annotations."storageclass.kubernetes.io/is-default-class" |
"false" for all of these |
Exactly one StorageClass should be "true" per cluster (declared elsewhere, often by Terraform/cluster-bootstrap). |
provisioner |
pd.csi.storage.gke.io (PD) or filestore.csi.storage.gke.io (Filestore) |
GCP CSI drivers. |
parameters.type |
pd-ssd, pd-standard, pd-balanced |
Cost/perf trade-off. |
reclaimPolicy |
Delete (default) or Retain (DR) |
Changing this on an existing StorageClass does not retroactively change PVCs. |
volumeBindingMode |
WaitForFirstConsumer |
Avoids zone-mismatch on multi-zone clusters. Immediate only for ReadWriteMany. |
allowVolumeExpansion |
true |
Required for online resizing. Default false on some classes — set explicitly. |
Hard rules
- Never delete a StorageClass referenced by an existing PVC. New PVCs against the deleted class fail; existing bound PVCs survive but lose the ability to expand.
- Never change
reclaimPolicyfromDelete→Retainas a "safety improvement" without auditing every PVC. Existing bound PVs keep their old policy; new PVs get the new policy. Drift. - Never change
provisioner— that's a delete-and-recreate, not an edit. Existing PVs become orphaned. - Never make a new StorageClass the cluster default without coordinating with the platform team. A wrong default class hijacks every PVC that doesn't pin a class explicitly.
- Validation: every StorageClass referenced by any
helm-overrides/*/persistence.storageClass:must have a corresponding file here.
# Find every PVC reference
grep -rE 'storageClass(Name)?:' helm-overrides | sort -u
# Find every StorageClass file
ls manifests/storageclass/*.yaml
§PriorityClass (manifests/priorityclass/<cluster>/*.yaml)
Per-cluster but cluster-wide — affects scheduling priority for every pod that references the class.
Inventory pattern
manifests/priorityclass/
k8s-central-prd-ase1/
priorityclass-high.yaml
priorityclass-low.yaml
k8s-supply-prd-ase1/
priorityclass-high.yaml
priorityclass-low.yaml
…
Most BU clusters get a high and a low class. Specialty clusters (mqkafka, dsgpu, dataplane db-*) sometimes have additional tiers.
Schema
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000 # higher = more important
globalDefault: false # NEVER true on these — would clash with system defaults
description: "High-priority workloads — promoted ahead of general pods on resource pressure"
preemptionPolicy: PreemptLowerPriority # default; alternative is Never
| Field | Convention | Notes |
|---|---|---|
metadata.name |
high-priority, low-priority, etc. |
Workload pods reference by name. |
value |
High: 1,000,000 / Low: 100 / Critical (rare): >1,000,000,000 | Kubernetes system pods reserve > 2,000,000,000; don't conflict. |
globalDefault |
always false |
A true here applies to every pod that doesn't pin a class — chaos. |
description |
one-line | For audit log. |
preemptionPolicy |
PreemptLowerPriority (default) or Never |
Never for batch workloads that shouldn't kick others out. |
Hard rules
- Never set
globalDefault: trueon any PriorityClass here. The cluster's implicit default is what we want. - Never raise
valueof an existing class without auditing what gets preempted. A bump from 1,000,000 → 10,000,000 changes which pods get evicted under pressure. - Never delete a PriorityClass referenced by any workload — pods that referenced it become invalid.
- The same
namemust mean the same thing across clusters.high-priorityon supply ≠high-priorityon demand at the value level is an audit nightmare. Keep values consistent. - Validation: find every pod-spec reference:
grep -rE 'priorityClassName:' helm-overrides
§The "PV/PVC singletons" — Jenkins / JFrog filestore
Beyond StorageClass and PriorityClass, manifests/ also holds per-env, one-shot PV/PVC pairs:
manifests/jenkins-filestore-caching/
dev/{pv,pvc}.yaml
prd/{pv,pvc}.yaml
manifests/jenkins-gcs-caching/{pv,pvc,sc-gcs}.yaml
manifests/jfrog-filestore-data/
dev/...
prd/...
These are already-created PVs being adopted — typically because the underlying disk (Filestore mount, GCS bucket) was provisioned by Terraform or by hand. The PV file binds the existing disk to the cluster; the PVC file binds a workload to the PV.
| Rule | Why |
|---|---|
Don't change spec.csi.volumeHandle / spec.gcePersistentDisk.pdName without coordinating with Terraform. The handle is the disk identity. |
|
Don't change spec.persistentVolumeReclaimPolicy from Retain to Delete on these. The disk has data on it. |
|
| Don't move dev→prd or vice versa — they reference different physical disks. | |
| Treat as platform-team review. Any change here is a 1:1 disk operation. |
Validation script
# StorageClass: every name in helm-overrides has a file here
for sc in $(grep -rhE 'storageClass(Name)?:' helm-overrides \
| sed -E 's/.*storageClass(Name)?:\s*//' \
| tr -d '"' | sort -u); do
[ -f "manifests/storageclass/${sc}.yaml" ] || echo "MISSING: $sc"
done
# PriorityClass: every name referenced has a file in the matching cluster
grep -rE 'priorityClassName:' helm-overrides
# (cross-reference manually against manifests/priorityclass/<cluster>/)