OpenShift is Kubernetes with a platform layer on top. The API still speaks Pods, Deployments, and Services. The day-to-day CLI is oc, not plain kubectl. If you already know kubectl, most of that knowledge transfers. What changes is authentication, how namespaces are presented, and a set of OpenShift-specific resources you will touch sooner than you expect.
This post is a practical starter kit for oc: how it relates to kubectl, how to log in and pick a project, the commands that cover most routine work, when to reach for which tool, and a debugging order that stays calm under pressure. No attempt to list every subcommand.
oc and kubectl: cousins, not clones
oc embeds kubectl-compatible commands. Under the hood, many oc verbs call the same client libraries kubectl uses. That is why oc get pods feels familiar and why kubectl cheat sheets mostly still apply.
The differences matter in three places:
- Authentication — OpenShift clusters expect
oc loginwith tokens or credentials tied to the platform identity provider. kubeconfig still exists, but you usually obtain it through login rather than hand-editing a file. - Projects — OpenShift maps projects to Kubernetes namespaces with extra metadata and default policies.
oc projectis the habit;-nstill works on both tools. - Platform resources — Routes, ImageStreams, BuildConfigs, DeploymentConfigs (legacy), and Templates are OpenShift extensions. kubectl can read some of them if the API is exposed, but
ochas first-class support and friendlier defaults.
You can often alias or symlink mentally: oc = kubectl + OpenShift login + platform objects. Portable automation sometimes still uses kubectl with a kubeconfig exported from oc login. Day-to-day on the cluster console, oc is the default.
Check what you are running:
oc version
oc api-resources | head -20
If oc version shows a client but cannot reach the server, the problem is login or network — not your Deployment YAML.
Login, context, and project
Before get or describe, confirm where you are connected and which project is active. OpenShift makes this explicit; skipping it is the fastest way to debug the wrong environment.
Log in to a cluster (typical interactive flow):
oc login https://api.cluster.example.com:6443
oc login --token=sha256~YOUR_TOKEN --server=https://api.cluster.example.com:6443
The first form prompts for credentials or opens a browser flow depending on cluster configuration. The second is common in CI and when copying a token from the web console.
After login, inspect identity and access:
oc whoami
oc whoami --show-token=false
oc auth can-i get pods
oc auth can-i create deployments
whoami answers which user the session represents. auth can-i clarifies RBAC without guessing from forbidden errors.
Projects are the OpenShift-facing name for namespaces you work in:
oc projects
oc project shop-staging
oc project
oc projects lists what you can see. oc project shop-staging switches the active project for subsequent commands. Bare oc project prints the current one — the line worth checking when results make no sense.
Kubeconfig context still exists. OpenShift often names contexts after users and clusters:
oc config current-context
oc config get-contexts
oc config use-context my-user/api-cluster-example-com:6443/shop-staging
Treat project switches like changing runways at the same airport. The procedures look similar; the traffic is not the same.
Common oc commands for daily work
Most routine work repeats a small set of verbs. These mirror kubectl but use OpenShift defaults where it helps.
Inspect workloads
oc get pods
oc get deploy,svc,route
oc get all
oc get pods -o wide
oc get pods --show-labels
oc get all includes Routes and some OpenShift types kubectl’s all bundle omits. -o wide adds node and Pod IP. --show-labels helps when Services have no endpoints because selectors drifted.
Describe and events
oc describe pod web-7d4f8c9b6-xk2jp
oc describe deployment web
oc describe route web
Events at the bottom of describe output remain the fastest clue for Pending, CrashLoopBackOff, and ImagePullBackOff.
Logs and follow
oc logs deployment/web --tail=100
oc logs deployment/web -f
oc logs web-7d4f8c9b6-xk2jp -c web --previous
The --previous flag reads the last crashed container — useful when restarts happened before you opened the terminal.
Apply and rollouts
oc apply -f deployment.yaml
oc apply -f . --dry-run=server
oc rollout status deployment/web
oc rollout restart deployment/web
Prefer rollout restart over deleting Pods when you own a Deployment and only need fresh containers.
Routes and external access
Routes are the OpenShift-native way to expose HTTP(S) services outside the cluster:
oc get route
oc describe route web
oc expose svc web --hostname=web-shop-staging.apps.cluster.example.com
Ingress exists on many OpenShift versions too, but teams on the platform often standardize on Routes for edge TLS and hostname conventions.
ImageStreams and builds (first touch)
You will meet platform objects beyond core Kubernetes:
oc get imagestream
oc get buildconfig
oc get builds
oc describe buildconfig web
These commands do not replace understanding ImageStreams — they tell you whether a build failed before a Deployment ever saw a new tag.
Convenience wrappers
OpenShift adds shortcuts kubectl lacks:
oc status
oc get pod -w
oc rsh deployment/web
oc port-forward deployment/web 8080:8080
oc status summarizes project health at a glance — not a replacement for describe, but a good orientation step. oc rsh opens a remote shell when policy allows; treat it as a last resort after logs and describe, not the first move.
When to use oc vs kubectl
Both tools talk to the same API server when credentials are valid. The choice is about features, portability, and team convention.
Prefer oc when:
- Logging in, switching projects, or using OpenShift-specific resources (Routes, ImageStreams, BuildConfigs, Templates).
- Running
oc new-app,oc start-build, or other platform workflows documented for OpenShift. - Following runbooks written for OpenShift operators who assume
oc loginand project context. - Using
oc status,oc rsh, or integrated build and deploy helpers.
Prefer kubectl when:
- Writing scripts meant to run unchanged on vanilla Kubernetes and OpenShift.
- Using third-party tooling that shells out to
kubectlexplicitly. - Debugging subtle client behavior — some edge cases differ between oc-wrapped and upstream kubectl versions.
- Your kubeconfig was exported and you deliberately avoid oc-specific flags.
In practice, many engineers use oc interactively and kubectl in portable CI with the same kubeconfig. That is fine as long as everyone agrees which context and namespace the pipeline uses.
A portable check that works with either binary:
kubectl get pods -n shop-staging
oc get pods -n shop-staging
Same objects; different login ergonomics.
Debugging workflow on OpenShift
The order matters more than the tool brand. When something is wrong in a project, this sequence avoids restarting healthy Pods or reading logs from a container that never started.
1. Confirm cluster, user, and project
oc whoami
oc project
oc cluster-info
Wrong project is the OpenShift equivalent of wrong namespace on upstream Kubernetes.
2. Headline status
oc get pods
oc get deploy,svc,route
oc status
Note CrashLoopBackOff, ImagePullBackOff, Pending, and whether Routes exist for the Service you expect.
3. Describe before logs
oc describe pod web-7d4f8c9b6-xk2jp
oc describe deployment web
Read Events first. Image pull errors, quota violations, probe failures, and SCC denials often appear here.
4. Check builds and image references
OpenShift apps frequently pull from ImageStreams, not only public registries:
oc get buildconfig,builds
oc describe buildconfig web
oc get imagestream web -o yaml
A Deployment waiting on ImagePullBackOff may trace back to a failed build or a tag that never updated.
5. Route and Service alignment
oc get svc web -o yaml
oc get route web -o yaml
oc get endpoints web
External users hit Routes; Pods must match Service selectors; endpoints must be non-empty.
6. Logs after the Pod is running
oc logs deployment/web --tail=200
Skipping straight to logs when status is ImagePullBackOff wastes time. Skipping describe when status is Pending misses scheduling and quota Events.
7. Platform-specific denials
Security Context Constraints and project limits show up as clear Events:
oc describe pod web-7d4f8c9b6-xk2jp | grep -i scc
oc describe quota
oc describe limitrange
If Pods never start and Events mention SCC or forbidden capabilities, the fix is policy or Pod spec — not another rollout restart.
Small habits that compound
- Run
oc whoamiandoc projectat the start of an incident — paste them in the ticket. - Use explicit
-nin runbooks even when the project is set; copy-paste should not hit production by accident. - Prefer
oc describeover restarting Pods when Events explain the failure. - Check BuildConfigs and ImageStreams when image tags look stale or pulls fail on internal names.
- Use
oc auth can-ibefore blaming application code for forbidden errors. - Export kubeconfig for automation only after confirming context and namespace in the pipeline config.
Final thought
oc is not a different Kubernetes — it is the same API with OpenShift login, projects, and platform resources wired in. Fluency in a handful of verbs matters more than memorizing every flag. The engineers who settle in quickly are usually not the ones who run the longest command first. They confirm project and user, read Events before restarting things, and know when a failed build explains a Deployment that never rolled forward. Build that order early; Routes and ImageStreams become part of the story instead of surprises.