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 login with 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 project is the habit; -n still 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 oc has 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 login and 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 kubectl explicitly.
  • 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 whoami and oc project at the start of an incident — paste them in the ticket.
  • Use explicit -n in runbooks even when the project is set; copy-paste should not hit production by accident.
  • Prefer oc describe over 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-i before 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.