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 on OpenShift.
- From GitHub (https://github.com)
- From Docker Hub (https://hub.docker.com)
- From an image
- From a build
- From a template
- From a JSON or YAML file (templates)
Let's create a Python file named app.py that contains the following. This is a very simple Python script that returns "Hello World" once every 5 seconds. The reason a never ending while loop is used here is to keep the container Running. Without a while loop, the container would exit after printing Hello World. The while loop keeps the container running.
Python logger is used here so that the stdout is included in the pod logs.
import logging
import sys
import time
logger = logging.getLogger()
logger.setLevel(logging.INFO)
format = logging.Formatter(fmt="[%(asctime)s %(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
consoleHandler = logging.StreamHandler(sys.stdout)
consoleHandler.setFormatter(format)
logger.addHandler(consoleHandler)
int = 0
while int == 0:
logging.info("hello world")
time.sleep(5)
And then let's create a config map that contains app.py
oc create configmap my-config-map --from-file app.py --namespace my-project
Let's use the oc get images command to get the list of Red Hat Python images that can be used. Let's say we want to create our Python app using the registry.redhat.io/ubi9/python-39@sha256:0c2f708b4977469d090719d939778eb95b42c02c1da6476aa95f2e875920652b image, which will create the container using Python version 3.9.
~]$ oc get images | grep -i python
sha256:0c2f708b4977469d090719d939778eb95b42c02c1da6476aa95f2e875920652b registry.redhat.io/ubi9/python-39@sha256:0c2f708b4977469d090719d939778eb95b42c02c1da6476aa95f2e875920652b
sha256:190ea81f2f64ccf7f7c8cb9dc4612eda59eb9e3d2e17f71727a270f078f5114a registry.redhat.io/ubi8/python-27@sha256:190ea81f2f64ccf7f7c8cb9dc4612eda59eb9e3d2e17f71727a270f078f5114a
sha256:4a1d451e1d513115ff54c6e80299e761f60454b5f2f091f3c9ddb9fc1d61f5c4 registry.redhat.io/ubi8/python-38@sha256:4a1d451e1d513115ff54c6e80299e761f60454b5f2f091f3c9ddb9fc1d61f5c4
sha256:971dcd27c3d53f58eb59c946f123223b95662841c1214a394a445380beb75f59 registry.redhat.io/ubi8/python-36@sha256:971dcd27c3d53f58eb59c946f123223b95662841c1214a394a445380beb75f59
sha256:d4e20aa826660f635fad77837b9c6aab8248f0560cd8c3c2283john.doe59e9bb registry.redhat.io/rhscl/python-38-rhel7@sha256:d4e20aa826660f635fad77837b9c6aab8248f0560cd8c3c2283john.doe59e9bb
sha256:e2a461928e82d7da8991f4fdf5496219f013a6e70c4ef30cf5fb93a4cc450eac registry.redhat.io/ubi8/python-39@sha256:e2a461928e82d7da8991f4fdf5496219f013a6e70c4ef30cf5fb93a4cc450eac
Let's create a YAML file named deployment.yaml with the following, using "registry.redhat.io/ubi9/python-39@sha256:0c2f708b4977469d090719d939778eb95b42c02c1da6476aa95f2e875920652b" as the image to run app.py using Python version 3.9.
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
- python /opt/app-root/src/app.py
image: registry.redhat.io/ubi9/python-39@sha256:0c2f708b4977469d090719d939778eb95b42c02c1da6476aa95f2e875920652b
name: my-container
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- mountPath: /opt/app-root/src/app.py
name: my-config-map
subPath: app.py
volumes:
- configMap:
defaultMode: 420
name: my-config-map
name: my-config-map
And then use the oc apply command to create the deployment. If you are not familiar with the oc command, check out my article OpenShift - Getting Started with the oc command
oc apply --filename deployment.py
At this point the oc get all command should return the following, where there is a deployment, a replica set, and a Running pod.
~]$ oc get all --namespace my-project
NAME READY STATUS RESTARTS AGE
pod/my-app-56c98b85f4-fqtc7 1/1 Running 0 6m28s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app 1/1 1 1 6m28s
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-app-56c98b85f4 1 1 1 6m28s
The pod logs should now have Hello World once every 5 seconds. It works!
[john.doe@localhost oadp]$ oc logs my-app-56c98b85f4-fqtc7 --namespace my-project
[2025-05-14 01:47:47 INFO] hello world
[2025-05-14 01:47:52 INFO] hello world
[2025-05-14 01:47:57 INFO] hello world
[2025-05-14 01:48:02 INFO] hello world
[2025-05-14 01:48:07 INFO] hello world
Did you find this article helpful?
If so, consider buying me a coffee over at 