Typical actions in Kubernetes
There's a handful of operations that show up over and over when running a cluster: running scheduled tasks, controlling where pods land and granting permissions to a ServiceAccount. This guide collects the patterns we use day to day, with copy-pasteable syntax.
Running CronJobs
A CronJob runs a Job on a cron-style schedule. It's useful for backups, cleanup, reports, syncs, etc.
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
spec:
schedule: "0 2 * * *" # 02:00 every day
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: yourcompany/backup:1.2
args: ["/scripts/backup.sh"]
Sidecar pattern
If your pod's main application already ships with the dependencies you need for the task (database CLI, credentials, VPN connection…), you can reuse that same image as a sidecar inside the CronJob:
containers:
- name: app
image: yourcompany/app:1.2
- name: cron-runner
image: yourcompany/app:1.2 # same image, different command
command: ["/bin/sh", "-c", "/app/run-maintenance.sh"]
This avoids maintaining two images with redundant configuration.
Topology Keys and pod placement
Nodes carry labels (kubernetes.io/hostname, topology.kubernetes.io/zone, node-role.kubernetes.io/worker, etc.). Those keys are the topology keys the scheduler uses to decide where to place pods.
Three typical uses:
Spread across zones with
topologySpreadConstraints:topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: apiPrevent two replicas from landing on the same node with anti-affinity:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels: { app: api }
topologyKey: kubernetes.io/hostnameForce a pod to run next to another with affinity, using the same
topologyKey(same node, same zone, etc.).
Mental rule: topologyKey defines the grouping unit (node, zone, rack). The label selector defines who the rule applies to.
RoleBinding from the command line
To bind an existing Role to a ServiceAccount without writing YAML:
kubectl -n <ns> create rolebinding <binding-name> \
--role=<role-name> \
--serviceaccount=<ns>:<sa-name>
Real example: grant process-sa the permissions of the processor Role inside the data namespace:
kubectl -n data create rolebinding process \
--role=processor \
--serviceaccount=data:process-sa
Useful variants:
# Bind a ClusterRole to a user inside a namespace
kubectl -n app create rolebinding admin-binding \
--clusterrole=admin \
--user=[email protected]
# Bind a ClusterRole to a group cluster-wide
kubectl create clusterrolebinding view-all \
--clusterrole=view \
--group=auditors
Remember to add --dry-run=client -o yaml to save the manifest instead of applying it directly; that way you can version it in git.
Final cheatsheet
| I want to… | Command |
|---|---|
| Schedule periodic tasks | kubectl create cronjob name --image=img --schedule="..." |
| See node labels | kubectl get nodes --show-labels |
| Top resources per node | kubectl top nodes |
| Top resources per pod | kubectl top pods -A |
| Sort by CPU | kubectl top pods -A --sort-by=cpu |
| Validate permissions | kubectl auth can-i <verb> <res> --as=... |
Mastering these actions covers maybe 80% of the day-to-day work on a cluster.