Objects and namespaces¶
Objects, namespaces and labels, and the kubectl commands you will use every day.
Overview¶
Kubernetes has one idea underneath everything: you declare the state you want as an object, and controllers continuously work to make reality match it. A Deployment, a Secret, a Service and the radar's own PostgresWatch are all objects, and they all follow the same shape. Once that shape is familiar, so is every command in the rest of this section.
The shape of an object¶
Every object has the same four top-level fields:
apiVersion: radar.pgregressionradar.io/v1alpha1 # which API group and version defines this kind
kind: PostgresWatch # the type of object
metadata: # identity: name, namespace, labels, annotations
name: orders
namespace: pgrr-lab
spec: # what YOU want (desired state)
clusterName: orders
dsnSecretRef:
name: postgres-credentials
key: dsn
status: # what IS (observed state), written by a controller
phase: Running
Two rules matter more than any other:
- You write
spec; a controller writesstatus. Do not editstatusby hand. When you want to know whether the radar accepted yourPostgresWatch, you read itsstatus. apiVersion+kind+metadata.name+metadata.namespaceidentify the object. Applying the same YAML twice updates the object instead of creating a second one.
In pg-regression-radar
The things you write are PostgresWatch (what database to watch and how sensitively) and DeploySource (where deploy events come from). The things the radar writes are status on both of those, and whole PerformanceRegression objects, one per detection. See CRDs and operators.
Namespaces¶
A namespace is a named partition of a cluster. Most objects live in exactly one namespace, and two objects of the same kind can share a name only if they are in different namespaces. Namespaces are how teams, environments and tools share a cluster without colliding.
kubectl get namespaces
kubectl create namespace pgrr-lab
kubectl get pods -n pgrr-lab # one namespace
kubectl get pods -A # all namespaces
Some objects are cluster-scoped and belong to no namespace: nodes, CustomResourceDefinitions, ClusterRoles, and the radar's PostgresRadarCluster. You find out which is which with:
kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=false
Why namespaces matter for the radar¶
References between the radar's objects are by name, within a namespace. That is a rule you will trip on once if you do not know it:
| Reference | Where it is looked up |
|---|---|
DeploySource.spec.postgresWatchRef |
the PostgresWatch of that name in the same namespace as the DeploySource |
PostgresWatch.spec.dsnSecretRef |
the Secret of that name in the same namespace as the PostgresWatch (unless you use a remote cluster) |
DeploySource with sourceType: kubernetes, appName |
the Deployment or StatefulSet of that name in the same namespace as the DeploySource |
So the radar and the app you are watching can live in different namespaces, but the PostgresWatch, its DeploySource and the Secret holding the DSN are created together in one namespace, and a kubernetes deploy source watches workloads in that same namespace.
Set the namespace once
Typing -n <ns> on every command gets old. Pin it for your current context instead: kubectl config set-context --current --namespace=<ns>. Check what you are pinned to with kubectl config view --minify | grep namespace.
Labels, selectors and annotations¶
Labels are key/value pairs on an object's metadata that Kubernetes uses to select things. Annotations are key/value pairs that carry information but are never used for selection.
metadata:
labels:
app.kubernetes.io/name: orders-api
app.kubernetes.io/component: api
annotations:
deployment.kubernetes.io/revision: "2"
A selector matches labels. A Service sends traffic to the pods whose labels match its selector; a Deployment manages the pods whose labels match its selector. That is the only glue between those objects, so a typo in a label is a silent failure: the Service exists and routes to nothing.
kubectl get pods -n <ns> --show-labels
kubectl get pods -n <ns> -l app.kubernetes.io/component=manager
kubectl label secret my-dsn -n <ns> some-key=some-value
kubectl label secret my-dsn -n <ns> some-key- # trailing dash removes it
Two metadata fields the radar relies on¶
- The consent label.
pg-regression-radar.io/allow-postgreswatch-access: "true"on a Secret says "the owner of this Secret agrees that aPostgresWatchmay read it". The radar refuses to use a Secret without it. The full reasoning is in RBAC and access; the how-to is in Config and Secrets. - The revision annotation. For a Deployment,
deployment.kubernetes.io/revisionis a counter Kubernetes bumps on every rollout. ADeploySourcewithsourceType: kubernetesuses it as the deploy'srevision. See Pods and Deployments.
The Helm chart also puts the conventional app.kubernetes.io/name, app.kubernetes.io/instance and app.kubernetes.io/component labels on everything it creates, which is why -l app.kubernetes.io/component=manager selects the manager's objects.
The kubectl commands you will use¶
| You want to | Command |
|---|---|
| List objects of a kind | kubectl get <kind> -n <ns> |
| Watch a list change live | kubectl get <kind> -n <ns> -w |
| See one object in full, as stored | kubectl get <kind> <name> -n <ns> -o yaml |
| See an object plus its recent events | kubectl describe <kind> <name> -n <ns> |
| Pull one field out | kubectl get <kind> <name> -n <ns> -o jsonpath='{.status.phase}' |
| Learn what fields a kind accepts | kubectl explain postgreswatch.spec |
| Create or update from a file | kubectl apply -f file.yaml |
| Delete | kubectl delete -f file.yaml or kubectl delete <kind> <name> -n <ns> |
| Read a pod's logs | kubectl logs <pod> -n <ns> (see Troubleshooting toolkit) |
Three of these deserve a second look:
describevsget -o yaml.get -o yamlis the raw object;describeis a human summary that also lists Events, the short log Kubernetes keeps about what happened to the object. When something is stuck,describeis usually the first thing to run.explainworks for the radar's kinds too, because their schemas are published in the cluster:kubectl explain postgreswatch.spec.alertingshows every field and its description without leaving the terminal.-o jsonpathis how you script against status, for example waiting for a watch to be ready:kubectl get postgreswatch orders -n <ns> -o jsonpath='{.status.phase}'.
apply, not create¶
kubectl create -f file.yaml fails if the object exists. kubectl apply -f file.yaml creates it if it does not and updates it if it does, which is what lets you edit a manifest and re-apply it. Every manifest in this documentation is meant for apply.
kubectl apply -f my-watch.yaml
# edit my-watch.yaml
kubectl apply -f my-watch.yaml # updates the same PostgresWatch in place
kubectl apply also accepts a URL or a directory, and a file with several objects separated by ---, which is how the lab installs its whole stack in one command.
Order matters for custom resources¶
Objects of a custom kind (like PostgresWatch) can only be created after their definition exists in the cluster. That is why the lab waits for the CRDs between steps:
kubectl wait --for=condition=Established --timeout=60s \
crd/postgreswatches.radar.pgregressionradar.io
If you ever see no matches for kind "PostgresWatch" in version "radar.pgregressionradar.io/v1alpha1", the definition is not installed yet. CRDs and operators explains why.
See also¶
- Pods and Deployments: the objects that actually run the radar and your app.
- CRDs and operators: how
PostgresWatchand friends come to exist. - Troubleshooting toolkit:
describe, events and logs in practice. - Configuration Reference: every field of
PostgresWatchandDeploySource.