Platform Delivery Basics
This section covers how platform changes differ from app deploys, and the basic building blocks - SLOs, error budgets, change windows, and GitOps - that keep cluster changes from breaking the teams on top.
Search across all documentation pages
This section covers how platform changes differ from app deploys, and the basic building blocks - SLOs, error budgets, change windows, and GitOps - that keep cluster changes from breaking the teams on top.
kubectl configured (containerd is the node runtime via CRI).kubectl install on Debian/Ubuntu:# install kubectl matching the cluster minor
curl -LO "https://dl.k8s.io/release/v1.36.2/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --clientApp teams deploy many times a day; platform changes are rarer and higher blast radius.
# an app deploy: rolls one Deployment, affects one team
kubectl set image deployment/checkout web=registry.example.com/checkout:1.8.3
# a platform change: rotates node pool, affects every pod on those nodes
kubectl drain node-pool-a-xyz --ignore-daemonsets --delete-emptydir-dataStart with API server request latency, a signal every team feels.
# fraction of API reads served under 1s over 30 days
sum(rate(apiserver_request_duration_seconds_bucket{verb="GET",le="1"}[30d]))
/
sum(rate(apiserver_request_duration_seconds_count{verb="GET"}[30d]))apiserver_request_duration_seconds is exported by the API server itself.Write the objective down so it is a contract, not a vibe.
# a plain-text SLO record kept in the platform repo
slo:
name: apiserver-read-availability
sli: fraction of GET requests < 1s
target: 0.999 # 99.9% over a 30-day rolling window
window: 30d
owner: platform-teamDeliver platform changes declaratively so they are reviewable and revertible.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-baseline
namespace: argocd
spec:
project: platform
source:
repoURL: https://github.com/example/platform-config.git
targetRevision: main
path: baseline
destination:
server: https://kubernetes.default.svc
namespace: platform
syncPolicy:
automated:
prune: true
selfHeal: trueselfHeal reverts drift; prune removes objects deleted from Git.git revert, not a frantic manual edit.Platform add-ons need the same resource hygiene you expect from apps.
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
readinessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10Decide when disruptive platform work is allowed before you need it.
change-window:
routine: "Tue-Thu 10:00-16:00 UTC" # low-risk, business hours
freeze: "Fri 12:00 - Mon 09:00 UTC" # no risky platform changes
emergency: "any time, with incident approval"Measure delivery health so you know if the platform is helping.
# deployment frequency: successful app rollouts per day
sum(increase(deployment_rollout_success_total[1d]))Let policy, not gut feel, decide whether a change ships.
# pseudo-gate in a pipeline: block sync if budget is nearly gone
BUDGET_REMAINING=$(curl -s "$PROM/api/v1/query?query=slo_error_budget_remaining_ratio" \
| jq -r '.data.result[0].value[1]')
if (( $(echo "$BUDGET_REMAINING < 0.10" | bc -l) )); then
echo "Error budget below 10% - freezing platform changes"
exit 1
fi
argocd app sync platform-baselineNever skip minor versions; Kubernetes supports upgrading one minor at a time.
# check current version, then upgrade the control plane one minor up
kubectl version
# on a kubeadm control-plane node:
sudo kubeadm upgrade plan
sudo kubeadm upgrade apply v1.36.2
# then drain, upgrade kubelet, and uncordon each node in turn
kubectl drain node-1 --ignore-daemonsetsQuotas and priority keep one team from burning everyone's budget.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: team-checkout
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
pods: "150"ResourceQuota caps how much of the shared cluster one namespace can claim.PriorityClass so platform-critical pods win under pressure.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026