oc (OpenShift CLI) and kubectl share most commands. oc extends Kubernetes with OpenShift-specific features — cluster login, projects, routes, builds, image streams, DeploymentConfig, and oc adm administration. Where a command works identically in both tools, a single block is shown. All commands validated against official docs: OCP 4.18 CLI reference and kubectl quick-reference.
Also see: Docker & Podman Cheatsheet
- Installation
- Version & Help
- Login & Authentication
- Context & Config
- Namespaces / Projects
- Viewing Resources
- Nodes
- Pods
- Deployments
- Services
- Routes (OCP) / Ingress (K8s)
- Storage — PV & PVC
- ConfigMaps
- Secrets
- Labels & Annotations
- Environment Variables
- RBAC & Access Control
- Security Context Constraints (OCP)
- Scaling & HPA
- Events & Troubleshooting
- OCP — Applications, Builds & Templates
- OCP 4 — Cluster Administration
- Resource Definition Basics
Installation
oc:
# Download from the cluster web console (? menu → Command-line tools)
# or from mirror.openshift.com
# RHEL / Fedora
sudo dnf install openshift-clients
# macOS
brew install openshift-cli
kubectl:
# Linux (latest stable)
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
# RHEL / Fedora
sudo dnf install kubernetes-client
# macOS
brew install kubectl
Version & Help
oc:
oc version # client and server versions
oc help
oc <command> --help
oc explain <resource> # API docs for a resource type
oc explain pod.spec.containers # docs for a nested field
oc types # list all OCP resource types and concepts
kubectl:
kubectl version
kubectl version --client # client version only
kubectl version -o yaml
kubectl cluster-info
kubectl help
kubectl <command> --help
kubectl explain <resource>
kubectl explain pod.spec.containers
kubectl explain deployment --recursive
kubectl api-resources # list all available resource types
kubectl api-resources --namespaced=true
kubectl api-resources --api-group=apps
kubectl api-versions # list all API versions
Login & Authentication
oc login is OCP-specific. kubectl uses kubeconfig directly.
oc:
oc login <cluster-url> # prompt for user/pass
oc login <cluster-url> -u <user> -p <password>
oc login <cluster-url> --token=<token>
oc login <cluster-url> --insecure-skip-tls-verify
oc logout
oc whoami # current user
oc whoami -t # current OAuth token
oc whoami --show-server # API server URL
oc whoami --show-console # web console URL
kubectl — check current identity:
kubectl auth whoami # user, groups, and extra attributes (k8s 1.28+)
Context & Config
oc:
oc config view
oc config get-contexts
oc config current-context
oc config use-context <name>
kubectl:
kubectl config view
kubectl config view --raw
kubectl config get-contexts
kubectl config get-contexts -o name
kubectl config current-context
kubectl config use-context <context-name>
kubectl config set-context --current --namespace=<namespace>
kubectl config set-context <name> --namespace=<ns> --cluster=<c> --user=<u>
kubectl config rename-context <old> <new>
kubectl config delete-context <name>
kubectl config delete-cluster <name>
kubectl config delete-user <name>
kubectl config set-credentials <name> --token=<token>
kubectl config unset users.foo
Namespaces / Projects
OpenShift Projects wrap Kubernetes namespaces with added metadata, quota defaults, and network policy.
oc:
oc projects # list all projects (note: plural)
oc project <name> # switch to a project
oc new-project <name>
oc new-project <name> --display-name='Name' --description='text'
oc status
oc status -v
oc adm (admin only):
oc adm new-project <name>
oc adm new-project <name> --admin=<user>
oc adm new-project <name> --node-selector=<selector>
kubectl:
kubectl get namespaces # alias: ns
kubectl create namespace <name>
kubectl delete namespace <name>
kubectl config set-context --current --namespace=<name>
Viewing Resources
Both tools share the same verbs: get, describe, edit, delete, patch, apply.
oc get all # all common resources in current project
kubectl get all -n <namespace>
# Output formats
kubectl get pods -o wide # extra columns: node, IP
kubectl get pods -o yaml
kubectl get pods -o json
kubectl get pods -o name # resource/name pairs
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase
# Filtering
kubectl get pods --show-labels
kubectl get pods -l app=nginx
kubectl get pods -l 'env in (production,staging)'
kubectl get pods --selector=app=nginx
kubectl get pods --field-selector=status.phase=Running
kubectl get pods --field-selector=spec.nodeName=node1
kubectl get pods --no-headers
# Watching & scope
kubectl get pods -w # watch for changes
kubectl get pods -A # all namespaces (--all-namespaces)
kubectl get pods -A -o wide
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
Nodes
oc:
oc get nodes
oc get nodes --show-labels
oc get nodes -L region -L env # show specific labels as columns
oc get node/<node-name> -o yaml
oc describe node <node-name>
oc adm cordon <node-name>
oc adm uncordon <node-name>
oc adm drain <node-name> --ignore-daemonsets --delete-emptydir-data
oc adm drain <node-name> --force
oc adm drain <node-name> --timeout=120s --grace-period=30
oc adm taint nodes <node-name> key=value:NoSchedule
oc adm taint nodes <node-name> key=value:NoExecute
oc adm taint nodes <node-name> key=value:PreferNoSchedule
oc adm taint nodes <node-name> key:NoSchedule- # remove taint (trailing -)
kubectl:
kubectl get nodes
kubectl get nodes --show-labels
kubectl describe node <node-name>
kubectl cordon <node-name>
kubectl uncordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
kubectl drain <node-name> --force
kubectl drain <node-name> --timeout=120s --grace-period=30
kubectl taint nodes <node-name> key=value:NoSchedule
kubectl taint nodes <node-name> key=value:NoExecute
kubectl taint nodes <node-name> key=value:PreferNoSchedule
kubectl taint nodes <node-name> key:NoSchedule- # remove taint (trailing -)
Pods
oc:
oc get pods
oc get pods -n <project> -o wide
oc get pods --show-labels
oc get pods -l app=myapp
oc describe pod <pod-name>
oc logs <pod-name>
oc logs <pod-name> -c <container>
oc logs <pod-name> --previous
oc logs -f <pod-name>
oc logs <pod-name> --tail=100
oc logs <pod-name> --since=1h
oc logs <pod-name> --timestamps
oc rsh <pod-name> # remote shell (OCP-specific)
oc rsh -c <container> <pod-name>
oc exec <pod-name> -- <command>
oc exec <pod-name> -c <container> -it -- /bin/bash
oc cp <pod-name>:/remote/path ./local
oc cp ./local <pod-name>:/remote/path
oc cp -c <container> <pod-name>:/remote/path ./local
oc port-forward <pod-name> 8080:80
oc port-forward svc/<name> 8080:80
oc debug pod/<pod-name>
oc debug node/<node-name>
oc debug deployment/<name> --as-root
oc delete pod <pod-name>
oc delete pod <pod-name> --grace-period=0 --force
kubectl:
kubectl get pods
kubectl get pods -n <namespace> -o wide
kubectl get pods --show-labels
kubectl get pods -l app=myapp
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl logs <pod-name> -c <container>
kubectl logs <pod-name> --previous
kubectl logs -f <pod-name>
kubectl logs <pod-name> --tail=100
kubectl logs <pod-name> --since=1h
kubectl logs <pod-name> --since-time=2024-01-01T00:00:00Z
kubectl logs <pod-name> --timestamps
kubectl logs -l app=nginx --all-containers=true
kubectl exec <pod-name> -- <command>
kubectl exec <pod-name> -c <container> -- <command>
kubectl exec -it <pod-name> -- /bin/bash
kubectl exec -it <pod-name> -c <container> -- /bin/sh
kubectl cp <pod-name>:/remote/path ./local
kubectl cp ./local <pod-name>:/remote/path
kubectl cp ./local <pod-name>:/remote/path -c <container>
kubectl port-forward <pod-name> 8080:80
kubectl port-forward <pod-name> 8080 # host port same as container port
kubectl port-forward deployment/<name> 8080:80
kubectl port-forward svc/<name> 8080:80
kubectl port-forward <pod-name> 8080:80 --address 0.0.0.0
kubectl debug <pod-name> -it --image=busybox
kubectl debug <pod-name> --copy-to=debug-pod --image=busybox
kubectl debug <pod-name> -it --target=<container>
kubectl debug node/<node-name> -it --image=ubuntu
kubectl delete pod <pod-name>
kubectl delete pod <pod-name> --grace-period=0 --force
kubectl delete pods -l app=myapp
kubectl delete pods --all
Static Pods — managed by kubelet directly from a manifest file:
kubectl run static-pod \
--restart=Never \
--image=busybox \
--dry-run=client -o yaml \
-- sleep 3600 \
> /etc/kubernetes/manifests/static-pod.yaml
Deployments
oc — DeploymentConfig (OCP-specific resource):
oc get dc # list DeploymentConfigs
oc describe dc <name>
oc rollout latest dc/<name> # trigger a new deployment (DC equivalent of restart)
oc rollout status dc/<name>
oc rollout history dc/<name>
oc rollout undo dc/<name>
oc rollout undo dc/<name> --to-revision=2
oc rollout pause dc/<name>
oc rollout resume dc/<name>
oc rollout cancel dc/<name>
oc set image dc/<name> <container>=<image>:<tag>
oc scale dc/<name> --replicas=3
oc & kubectl — Deployment (standard Kubernetes):
oc get deployments
kubectl get deployments # alias: deploy
kubectl create deployment myapp --image=nginx:1.27
kubectl apply -f deployment.yaml
kubectl replace -f deployment.yaml
kubectl replace --force -f deployment.yaml
kubectl set image deployment/<name> <container>=<image>:<tag>
kubectl rollout status deployment/<name>
kubectl rollout status daemonset/<name>
kubectl rollout history deployment/<name>
kubectl rollout history deployment/<name> --revision=2
kubectl rollout undo deployment/<name>
kubectl rollout undo deployment/<name> --to-revision=2
kubectl rollout restart deployment/<name> # Deployment / DaemonSet / StatefulSet ONLY
# NOT valid for DeploymentConfig
kubectl rollout pause deployment/<name>
kubectl rollout resume deployment/<name>
kubectl delete deployment <name>
kubectl run nginx --image=nginx # creates a Deployment
kubectl run nginx --image=nginx --restart=Never # creates a Pod (not Deployment)
kubectl run -it busybox --image=busybox -- sh
kubectl run nginx --image=nginx --dry-run=client -o yaml
Services
oc get svc
kubectl get services # alias: svc
kubectl expose deployment myapp --port=80 --target-port=8080
kubectl expose deployment myapp --port=80 --type=NodePort
kubectl describe svc <name>
kubectl delete svc <name>
Routes (OCP) / Ingress (K8s)
oc — Routes:
oc expose svc/<name>
oc expose svc/<name> --hostname=myapp.apps.example.com --port=<port>
oc expose dc/<name>
oc get routes
oc describe route <name>
oc delete route <name>
# A/B traffic splitting
oc set route-backends <route> app-v1=80 app-v2=20
kubectl — Ingress:
kubectl get ingress # alias: ing
kubectl describe ingress <name>
kubectl apply -f ingress.yaml
kubectl delete ingress <name>
Storage — PV & PVC
oc get pv # PersistentVolumes (cluster-wide)
kubectl get pv
oc get pvc -n <project> # PersistentVolumeClaims
kubectl get pvc -n <namespace>
oc get storageclass
kubectl get storageclass # alias: sc
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
kubectl describe pvc <name>
kubectl delete pvc <name>
Add a PVC to a deployment (oc):
oc set volumes deployment/<name> \
--add \
--name my-pv-storage \
--type pvc \
--claim-class nfs-storage \
--claim-mode rwo \
--claim-size 10Gi \
--mount-path /var/data \
--claim-name my-pv-claim
ConfigMaps
# Create
kubectl create configmap <name> --from-literal=key1=value1
kubectl create configmap <name> --from-literal=key1=val1 --from-literal=key2=val2
kubectl create configmap <name> --from-file=app.properties
kubectl create configmap <name> --from-env-file=./env.txt
oc create configmap <name> --from-literal=key1=value1 --from-file=config.txt
# View
kubectl get configmap # alias: cm
kubectl get configmap <name> -o yaml
kubectl describe configmap <name>
# Delete
kubectl delete configmap <name>
# Mount as volume on a DC (oc)
oc set volumes dc/<name> \
--add \
--type configmap \
--mount-path /etc/config \
--configmap-name <configmap-name> \
--name app-config
# Set as env vars
oc set env dc/<name> --from=configmap/<configmap-name>
kubectl set env deployment/<name> --from=configmap/<configmap-name>
Secrets
# Create
kubectl create secret generic <name> --from-literal=username=admin --from-literal=password=s3cr3t
kubectl create secret generic <name> --from-file=./secret.txt
kubectl create secret docker-registry <name> \
--docker-server=myregistry.example.com \
--docker-username=myuser \
--docker-password=mypassword
kubectl create secret tls <name> --cert=tls.crt --key=tls.key
oc create secret generic <name> --from-literal=key=value
# View (values are base64-encoded)
kubectl get secrets
kubectl get secret <name> -o yaml
kubectl describe secret <name> # does not reveal values
# Delete
kubectl delete secret <name>
# Reference in a pod spec — at same level as 'containers'
# imagePullSecrets:
# - name: <secret-name>
# Mount as volume (oc)
oc set volumes dc/<name> \
--add \
--type secret \
--secret-name <secret-name> \
--mount-path /etc/secrets \
--name my-secret-vol
# Set as env vars
oc set env dc/<name> --from=secret/<secret-name>
kubectl set env deployment/<name> --from=secret/<secret-name>
Labels & Annotations
# Add / update labels
kubectl label pod/<name> key=value
kubectl label pod/<name> key=value --overwrite
kubectl label node/<name> disktype=ssd
kubectl label pod/<name> key- # remove label (trailing -)
oc label <resource> <name> key=value --overwrite
oc label pod <name> env- # remove label
# Filter by label
kubectl get pods -l env=dev
kubectl get pods -l 'env in (dev,staging)'
kubectl get pods --show-labels
# Patch
kubectl patch node <node-name> -p '{"metadata":{"labels":{"project":"myapp"}}}'
kubectl patch pod <pod-name> --type='json' \
-p='[{"op":"replace","path":"/spec/containers/0/image","value":"nginx:1.27"}]'
# Annotations
kubectl annotate pod/<name> description="my pod"
kubectl annotate pod/<name> description="my pod" --overwrite
kubectl annotate pod/<name> description- # remove annotation
oc annotate <resource> <name> key=value --overwrite
oc annotate <resource> <name> key- # remove annotation
Environment Variables
oc:
oc set env dc/<name> KEY=VALUE
oc set env dc/<name> KEY1=VAL1 KEY2=VAL2
oc set env dc/<name> KEY- # remove (trailing -)
oc set env dc/<name> --from=configmap/<name>
oc set env dc/<name> --from=secret/<name>
kubectl:
kubectl set env deployment/<name> KEY=VALUE
kubectl set env deployment/<name> KEY-
kubectl set env deployment/<name> --from=configmap/<name>
kubectl set env deployment/<name> --from=secret/<name>
RBAC & Access Control
# Create roles
kubectl create role <name> --verb=get,list,watch --resource=pods -n <ns>
kubectl create clusterrole <name> --verb=get,list,watch --resource=pods,services
# Create bindings
kubectl create rolebinding <name> --role=<role> --user=<user> -n <ns>
kubectl create rolebinding <name> --role=<role> --serviceaccount=<ns>:<sa> -n <ns>
kubectl create clusterrolebinding <name> --clusterrole=<role> --user=<user>
kubectl create clusterrolebinding <name> --clusterrole=<role> --group=<group>
kubectl create clusterrolebinding <name> --clusterrole=<role> --serviceaccount=<ns>:<sa>
# View
kubectl get rolebinding -n <namespace>
kubectl get clusterrolebinding
kubectl describe rolebinding <name> -n <namespace>
# oc adm policy shortcuts
oc adm policy add-role-to-user <role> <user> -n <project>
oc adm policy add-role-to-group <role> <group> -n <project>
oc adm policy remove-role-from-user <role> <user> -n <project>
oc adm policy add-cluster-role-to-user <cluster-role> <user>
oc adm policy add-cluster-role-to-group <cluster-role> <group>
oc adm policy remove-cluster-role-from-user <cluster-role> <user>
oc adm policy remove-cluster-role-from-group <cluster-role> <group>
oc adm policy who-can <verb> <resource> -n <project>
oc adm policy who-can <verb> <resource> --all-namespaces
oc get serviceaccounts # alias: sa
oc get clusterrole
# Check access
kubectl auth can-i create pods
kubectl auth can-i create pods --as=user1
kubectl auth can-i create pods -n <namespace>
kubectl auth can-i '*' '*'
kubectl auth can-i list secrets --as=system:serviceaccount:default:my-sa
kubectl auth reconcile -f rbac.yaml
Security Context Constraints (OCP)
OCP-specific. Kubernetes equivalent is Pod Security Admission (PSA).
oc get scc # list all SCCs
oc describe scc <scc-name>
oc adm policy add-scc-to-user <scc> <user>
oc adm policy add-scc-to-user <scc> -z <serviceaccount> -n <project>
oc adm policy remove-scc-from-user <scc> <user>
Scaling & HPA
oc:
oc scale dc/<name> --replicas=3
oc scale deployment/<name> --replicas=3
oc scale --replicas=0 -f file.yaml
oc autoscale dc/<name> --min=2 --max=10 --cpu-percent=80
oc autoscale deployment/<name> --min=2 --max=10 --cpu-percent=80
oc get hpa
oc describe hpa <name>
kubectl:
kubectl scale deployment/<name> --replicas=3
kubectl scale replicaset/<name> --replicas=3
kubectl scale statefulset/<name> --replicas=3
kubectl scale -f manifest.yaml --replicas=3
kubectl scale deployment/<name> --current-replicas=2 --replicas=3
kubectl scale deployment/<name> --replicas=0 # scale to zero
kubectl autoscale deployment/<name> --min=2 --max=10 --cpu-percent=80
kubectl autoscale replicaset/<name> --max=5
kubectl get hpa
kubectl describe hpa <name>
kubectl delete hpa <name>
Events & Troubleshooting
# Events
kubectl events -n <namespace> # k8s 1.26+
kubectl events --for=pod/<pod-name>
kubectl events --for=deployment/<name>
kubectl events --types=Warning
kubectl events --watch
kubectl get events --sort-by=.lastTimestamp # older form, always works
oc get events
# Resource usage
kubectl top nodes
kubectl top pods
kubectl top pods --all-namespaces
kubectl top pods -l app=myapp
kubectl top pod <pod-name> --containers
oc adm top nodes
oc adm top nodes --selector=<label>
oc adm top pods -n <project>
oc adm top pods --all-namespaces --containers
# Resource quotas
kubectl describe resourcequota -n <namespace>
kubectl get quota -n <namespace>
oc describe quota -n <project>
oc get quota -n <project>
# Limit ranges
kubectl get limitrange -n <namespace>
kubectl describe limitrange -n <namespace>
oc get limits -n <project>
# Cluster resource quotas (OCP)
oc get clusterresourcequota
oc describe clusterresourcequota <name>
# Dry run
kubectl apply -f resource.yaml --dry-run=client
kubectl apply -f resource.yaml --dry-run=server
oc apply -f resource.yaml --dry-run=client
# Verbose output
kubectl get pods -v=6
oc get pods --loglevel=6
# Must-gather (OCP) — collect diagnostic data
oc adm must-gather
oc adm must-gather --image=<custom-image>
oc adm must-gather --dest-dir=./must-gather-output
OCP — Applications, Builds & Templates
Creating Applications
oc new-app <image>
oc new-app <image> -e KEY=VAL --strategy=docker
oc new-app <repo-url> --name=<name>
oc new-app --template=<template-name> -p PARAM=value
BuildConfigs & Builds
oc get bc # list BuildConfigs
oc get builds
oc new-build <repo> --name=<name> --strategy=docker
oc new-build <repo> --name=<name> --strategy=source
oc start-build <bc-name>
oc start-build <bc-name> --follow --wait
oc start-build <bc-name> --from-file=<local-file>
oc cancel-build <build-name>
oc logs bc/<name> -f
oc logs build/<build-name>
oc set env bc/<name> BUILD_LOGLEVEL=5
Image Streams
oc get is # list image streams
oc describe is <name>
Templates
oc process <template-name> -p KEY=VAL | oc apply -f -
oc process -f template.yaml -p KEY=VAL
oc process --parameters <template-name>
oc get template -n openshift # cluster templates
OCP 4 — Cluster Administration
oc get clusterversion # cluster version and update history
oc get clusteroperators # status of all cluster operators
# Node logs via oc adm
oc adm node-logs <node-name>
oc adm node-logs <node-name> --unit=kubelet
oc adm node-logs <node-name> --unit=crio
oc adm node-logs <node-name> --tail=50 --since=1h
# Debug a node
oc debug node/<node-name>
# Inside the shell:
# chroot /host
# systemctl is-active kubelet
# toolbox # start toolbox container for host tools
# Cluster network configuration
oc get network/cluster -o yaml # pod network, service network, SDN plugin
Resource Definition Basics
Every Kubernetes/OCP resource shares the same top-level structure:
apiVersion: v1 # group/version — use 'kubectl api-versions' to list
kind: Service
metadata:
name: my-service
namespace: my-project
labels:
app: myapp
spec: # resource-specific spec — use 'kubectl explain' to browse
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Create / update / delete:
kubectl apply -f resource.yaml # create or update (preferred)
kubectl create -f resource.yaml # create only — fails if already exists
kubectl replace -f resource.yaml # replace existing resource
kubectl delete -f resource.yaml
kubectl edit <resource> <name> # live edit in $EDITOR
oc apply -f resource.yaml
oc create -f resource.yaml
oc delete -f resource.yaml
Export a live resource to YAML:
kubectl get deployment myapp -o yaml > myapp.yaml
oc get deployment myapp -o yaml > myapp.yaml
References: oc developer commands · oc administrator commands · kubectl quick-reference



