Your kubectl muscle memory, translated
Day one on a work OpenShift cluster: someone asks you to "deploy the new image, give Ana edit rights in the project and check why the route is down". You know how to do each of those in Kubernetes. This lesson is the cheat sheet that turns each habit into its OpenShift form, plus the few commands that only exist here.
What you need to know already: kubectl and kubeconfig (15.1, 15.3), Deployments, Services and Ingress (15.16, 16.1, 16.19), RBAC role bindings (17.30), Helm (25.19); from this chapter: oc login and projects (30.2, 30.4), SCCs (30.7, 30.9), Routes (30.13, 30.15), builds and ImageStreams (30.18), operators (30.23) and cluster operations (30.26).
Most of what you type is still kubectl - through oc, which contains all of kubectl. The table below is the part that changes. Left column: the job; middle: how you did it in chapters 15-19 and 22-24; right: the OpenShift way.
| task | on the kubeadm lab / AKS | on OpenShift | ||
|---|---|---|---|---|
| get credentials | az aks get-credentials, copy admin.conf | oc login https://api.<cluster>:6443 (or Copy login command in the console) | ||
| who am I | kubectl auth whoami | oc whoami; -t token, --show-context, --show-console | ||
| new namespace | kubectl create ns x (cluster rights) | oc new-project x (self-service, you become admin) | ||
| switch namespace | kubectl config set-context --current --namespace=x | oc project x | ||
| list my namespaces | kubectl get ns | oc projects / oc get projects (only yours) | ||
| deploy an image | kubectl create deployment | same, or oc new-app --image=... (adds ImageStream + Service) | ||
| deploy from Git | build in CI, push, apply | oc new-app builder~repo (BuildConfig + ImageStream + Deployment + Service) | ||
| expose over HTTP | Ingress YAML + ingress class | oc expose svc/x (Route), `oc create route edge | passthrough | reencrypt` |
| TLS for a Service inside the cluster | cert-manager | annotate the Service for the service CA | ||
| shell | kubectl exec -it pod -- sh | oc rsh pod (or deploy/x) | ||
| debug a crash-looping pod | kubectl debug --copy-to | oc debug deploy/x (a copy with sh as the command; not simulated in the lab) | ||
| node shell | kubectl debug node/x -it --image=busybox, SSH | oc debug node/x, then chroot /host | ||
| grant a role in a namespace | kubectl create rolebinding ... | oc policy add-role-to-user edit alice | ||
| why is my pod not allowed | PSA warnings | SCC: `oc get pod -o yaml | grep openshift.io/scc, oc adm policy scc-subject-review` | |
| what is running here | kubectl get all | oc status (+ oc get all) | ||
| install an add-on | helm install | an Operator from OperatorHub (Subscription), or Helm | ||
| upgrade the cluster | kubeadm, node by node | oc adm upgrade --to=... | ||
| support bundle | kubectl cluster-info dump | oc adm must-gather |
Everything in the right column that is not an OpenShift API (the kubectl verbs, jsonpath, --dry-run=client -o yaml, auth can-i, rollout, top) works exactly as in chapters 15-19. A few right-column commands are new here:
oc rsh pod- "remote shell": opensshin the pod's first container, the same askubectl exec -it pod -- shwith less typing.oc policy add-role-to-user edit alice- creates a RoleBinding (17.30) giving useralicethe built-ineditClusterRole in the current project.oc adm policy scc-subject-review -f pod.yaml- asks "which SCC would admit this pod?" without creating it.- The service CA: annotate a Service with
service.beta.openshift.io/serving-cert-secret-name=<name>and OpenShift writes a TLS certificate (9.15) for it into that Secret, signed by a cluster-internal CA.
oc status
The fastest overview of a project. Where kubectl get all prints flat lists, oc status draws the chain Route -> Service -> Deployment -> BuildConfig, and lists what is broken:
$ oc status
In project shop on server https://api.ocp.lab:6443
https://web-shop.apps.ocp.lab (redirects) to pod port http (svc/web)
deployment/web deploys istag/web:latest <-
bc/web source builds https://github.com/sclorg/nodejs-ex.git on openshift/nodejs:22-ubi9
deployment #3 running for 2m - 2 pods
svc/legacy - 10.96.141.22:80
deployment/legacy deploys docker.io/library/nginx:1.27
deployment #1 running for 12m - 0/2 pods growing to 2
1 error, 0 warnings, 1 info identified, use 'oc status --suggest' to see details.
Reading it: line 1 is the project and API server. Then one block per app: the Route URL ((redirects) = edge TLS with HTTP redirected to HTTPS, 30.15) pointing at svc/web; the Deployment it feeds, which deploys the ImageStreamTag web:latest (<- = an image change trigger, 30.18); the BuildConfig that builds that tag from a repository on a Node.js builder image; and "deployment #3 ... 2 pods" (third rollout, healthy). legacy has no Route and is stuck at 0/2 pods. The last line counts the problems.
--suggest expands the errors. For a crash-looping image it prints the famous advice to grant anyuid - read it as "this image needs root" and fix the image (30.9).
oc get all is not all
$ oc get all
It looks like it lists everything in the project. It does not: all is a category (a group name some resource types sign up to): pods, services, deployments, replicasets, statefulsets, daemonsets, jobs, cronjobs, and on OpenShift also routes, buildconfigs, builds, imagestreams and deploymentconfigs. It never includes ConfigMaps, Secrets, PVCs, RoleBindings, NetworkPolicies, ServiceAccounts or operator CRs. When you clean up or copy a project, list those explicitly: oc get cm,secret,pvc,rolebinding,networkpolicy,sa.
Templates
Before Helm (25.19) and operators, OpenShift packaged apps as Templates (template.openshift.io): a list of objects with ${PARAMETER} placeholders.
The three commands below: list the templates the cluster ships (in the openshift namespace); render a template file, filling two parameters with -p NAME=value, and pipe the YAML into oc apply -f - (- = read stdin, 1.7); or let oc new-app do both in one step from a template already on the cluster.
$ oc get templates -n openshift | head -3
$ oc process -f postgres-template.yaml -p DATABASE_NAME=orders -p VOLUME_CAPACITY=5Gi | oc apply -f -
$ oc new-app --template=postgresql-persistent -p POSTGRESQL_DATABASE=orders
oc process renders a template to plain YAML (a poor man's helm template). You will find them in older projects and in the openshift namespace; new work uses Helm charts or operators. (simulator) Templates and oc process are not in the lab.
The console
Every cluster has a web console (oc whoami --show-console). Worth knowing its Developer perspective (topology view of your project, build logs, a pod terminal) and Administrator perspective (OperatorHub, cluster settings and upgrades, the Observe > Alerting and Metrics pages backed by the built-in Prometheus). Anything you click creates the same objects you would write as YAML - the YAML tab on every page shows them, which is a good way to learn the fields. Treat the console as a viewer and keep changes in Git.
Monitoring you get for free
openshift-monitoring runs Prometheus (27.2), Alertmanager (28.7), the node exporter and Thanos Querier (a front end that queries several Prometheus servers as one) for the platform. User workload monitoring (enabled by an admin in the cluster-monitoring-config ConfigMap) lets your ServiceMonitors (27.4) in your projects be scraped by a second Prometheus in openshift-user-workload-monitoring, and the console's Observe pages query both. Chapters 27-29's PromQL works there unchanged.
What to practise on a real cluster
The lab covers the behaviour; a real cluster adds the scale and the console. On the free Developer Sandbox (a project on a shared cluster - no admin rights) you can do:
oc loginwith the console's Copy login command,oc whoami -t,oc projects.- Deploy
nginx:1.27and watch it crash-loop; read the logs; redeploynginxinc/nginx-unprivilegedon 8080. Seeopenshift.io/scc: restricted-v2and your UID. oc new-app nodejs~https://github.com/sclorg/nodejs-ex.git, follow the build, expose it, curl it,oc start-buildagain and watch the trigger.- Routes: edge with Redirect, a path route, a Route with a 503 you caused on purpose.
- Read-only:
oc get csvin your namespace (operators installed cluster-wide show up as copied CSVs),oc get clusterversion(often allowed read-only).
At work, ask for a project on the non-production cluster and repeat 2-4 there; then read the platform team's project template (oc get project <yours> -o yaml, oc get quota,limits)
- the ResourceQuota and LimitRange of 17.9 - and their SCC and Route policies: those are
the local rules this chapter's defaults get tightened with.
What you can now do
- Translate any kubectl habit into its
ocform, and know which commands exist only on OpenShift (new-project,new-app,expose,rsh,policy,adm upgrade). - Read
oc statustop to bottom, and list whatoc get allleaves out. - Recognise a Template and
oc processin an older project.