A deployment is used to manage the pods that are created to run an application. The deployment ensures that the desired number of pod replicas are running and can handle updates to the application by rolling out new versions of the pods. The deployment creates and manages a replica set, which in turn manages the pods.
Container] Pod2[Pod 2
Container] Pod3[Pod 3
Container] end end Deployment -->|Creates/Manages| Replica_Set Replica_Set -->|Manages| Pod1 Replica_Set -->|Manages| Pod2 Replica_Set -->|Manages| Pod3 style Deployment fill:#90CAF9 style Replica_Set fill:#FFE082 style Pods fill:#FFCCBC
It is also noteworthy that a route provides a URL that can be used to access the application from outside the OpenShift cluster. For example, if the route is configured to use the hostname myapp.mydomain.com, then users can access the application by navigating to http://myapp.mydomain.com. The route will forward the request to the service, which will then forward the request to one of the pods that are running the application.
Container] Pod2[Pod 2
Container] Pod3[Pod 3
Container] end SVC[Service] Route[Route] end USER[External User] --> Route --> SVC SVC --> Pod1 SVC --> Pod2 SVC --> Pod3 style SVC fill:#A5D6A7 style Pods fill:#FFCCBC style USER fill:#CE93D8
There are various ways to deploy an app.
- From GitHub (https://github.com)
- From Docker Hub (https://hub.docker.com)
- From an image
- From an image stream
- From a build
- From a template
- From a JSON or YAML file (templates)
If you are not familiar with the oc command, refer to OpenShift - Getting Started with the oc command.
A YAML file can be used to create an object, such as a config map, a deployment, a project, a pod, a route, a secret, a service, et cetera. These files are known as templates.
In this example, let's say you have a Python FastAPI uvicorn app that contains the following.
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
def home():
return "Hello World"
if __name__ == '__main__':
uvicorn.run(app, host="10.11.12.13", port=8080
And a requirements.txt file that contains the following.
fastapi==0.115.6
uvicorn==0.34.0
And you create a config map named my-config-map in namespace my-project that contains app.py and requirements.txt
]$ oc create configmap my-config-map --namespace my-project --from-file app.py --from-file requirements.txt
configmap/my-config-map created
The config map should now contain app.py and requirements.txt
]$ oc get configmap my-config-map --namespace my-project --output yaml
apiVersion: v1
data:
app.py: |
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
def home():
return "Hello World"
if __name__ == '__main__':
uvicorn.run(app, host="10.11.12.13", port=8080)
requirements.txt: |
fastapi==0.115.6
uvicorn==0.34.0
kind: ConfigMap
metadata:
creationTimestamp: "2025-05-09T01:39:56Z"
name: my-config-map
namespace: my-project
resourceVersion: "517596296"
uid: 92028a99-53c8-4353-9f98-40f7e11569fc
For example, let's say you have a YAML file named deployment.yml that contains the following markup. Notice in this example that the deployment uses Python image registry.redhat.io/ubi8/python-311 (Python version 3.11) and mounts app.py and requirements.txt in the config map in the container and uses pip to install the requirements in the container and then uses python to run app.py.
- use kind: Deployment to create a Deployment > Replica Set > Pods
- use kind: DeploymentConfig to create a Deployment Config > Replication Controller > Pods
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-project
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- command:
- /bin/sh
- -c
- pip install --upgrade pip; pip install --requirement /opt/app-root/src/requirements.txt;
python /opt/app-root/src/app.py
image: registry.redhat.io/ubi8/python-311
name: my-app
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- mountPath: /opt/app-root/src/app.py
name: my-config-map
subPath: app.py
- mountPath: /opt/app-root/src/requirements.txt
name: my-config-map
subPath: requirements.txt
volumes:
- configMap:
defaultMode: 420
name: my-config-map
name: my-config-map
The oc apply or oc create command with the -f or --filename option can be used to create the deployment using the template JSON or YAML file.
The oc replace command can be used to replace a deployment using a new or updated template JSON or YAML file.
The oc edit command can be used to update a deployments template YAML file.
~]$ oc create --filename deployment.yml
deploymentconfig.apps/my-app created
If kind: Deployment was used, the oc get deployments command can be used to list the deployments.
]$ oc get deployments --namespace my-project
NAME READY UP-TO-DATE AVAILABLE AGE
my-app 1/1 1 1 52s
If kind: DeploymentConfig was used, the oc get deploymentconfig (or oc get dc) command can be used to list the deployment configs.
~]$ oc get deploymentconfigs --namespace my-project
NAME REVISION DESIRED CURRENT TRIGGERED BY
my-app 1 1 1 config,image(my-app:latest)
If kind: Deployment was used, the oc get replicaset (or oc get rs) command can be used to list the replica sets.
~]# oc get replicaset --namespace my-project
NAME DESIRED CURRENT READY AGE
my-app-5b9879db6d 1 1 1 205d
If kind: DeploymentConfig was used, the oc get replicationcontroller (or oc get rc) command can be used to list the replication controllers.
Replicas is the number of pods that should be created for the deployment.
~]# oc get replicationcontroller --namespace my-project
NAME DESIRED CURRENT READY AGE
my-app-5b9879db6d 1 1 1 205d
The oc get pods command can be used to determine if the pods are up and running.
~]$ oc get pods --namespace my-project
NAME READY STATUS RESTARTS AGE
my-app-rhz7c 1/1 Running 0 23s
Did you find this article helpful?
If so, consider buying me a coffee over at 