Kubernetes conversations rarely center the developer's perspective. As a result, doing our job in a k8s cluster often requires building complicated YAML resource files, writing custom shell scripts, and understanding the countless options that are available in kubectl
and docker
commands. On top of all of that, we have the learning curve of understanding Kubernetes terminology and using it the way that operations teams do.
To address these challenges, the Red Hat Developer Tools team created odo
(OpenShift Do), a command-line interface (CLI) tool built for developers and designed to prioritize the things that developers care about. In this article, I will use a hands-on example to introduce you to the benefits of using odo
in conjunction with Kubernetes.
Improving the developer workflow
First, let's consider a typical workflow for a developer whose team has adopted Kubernetes. The workflow starts with local development activities and finishes with containers deployed and code running in one or more Kubernetes clusters. To help visualize this flow, you can think of it in terms of an inner loop and an outer loop. The inner loop consists of local coding, building, running, and testing the application—all activities that you, as a developer, can control. The outer loop consists of the larger team processes that your code flows through on its way to the cluster: code reviews, integration tests, security and compliance, and so on. The inner loop could happen mostly on your laptop. The outer loop happens on shared servers and runs in containers, and is often automated with continuous integration/continuous delivery (CI/CD) pipelines. Usually, a code commit to source control is the transition point between the inner and outer loops. Figure 1 illustrates the interplay of these loops in a Kubernetes development process.
Notice that, while you code, you are constantly iterating through various development activities: You code, build, deploy locally, and debug—and you keep going until you achieve a degree of feature completeness. At some point, you will be ready to transition from inner to outer, right? Not so quick.
Deploying from the inner loop
You might think that your job stops at local testing and a Git pull request (or a git push
)—but that's not usually the case. You will still need to ensure that your code functions correctly in containers, runs in the cluster, and plays nicely with other containerized components. Therefore, you will want some iterations of your inner loop to deploy and debug directly into the Kubernetes cluster.
Here's a list of steps you might typically follow to deploy from the inner loop:
- Describe how to configure the OS for your container:
- Write a Dockerfile to set up Linux.
- Describe how to package your app into a container image:
- Update the Dockerfile.
- Create a container image:
- Issue the commands
docker build
anddocker tag
.
- Issue the commands
- Upload the container image to a registry:
- Issue a
docker push.
- Issue a
- Write one or more Kubernetes or OpenShift resource files:
- Write lots of YAML.
- Deploy your app to the cluster:
- Issue the command:
kubectl apply -f my_app.yaml
.
- Issue the command:
- Deploy other services to the cluster:
- Issue the command:
kubectl apply -f svc*.yaml
.
- Issue the command:
- Write the config (or set
ENV
) to allow apps to work together:- Issue a
kubectl create configmap
.
- Issue a
- Configure apps to work together correctly:
- Issue a
kubectl apply -f my_configmap.yaml
.
- Issue a
That's a lot of steps!
Enter, odo
Red Hat OpenShift's oc
CLI tool can help make many of those steps easier; however, oc
is operations focused. Using it requires a deep understanding of Kubernetes and OpenShift concepts. Odo, on the other hand, was designed to be simple and concise:
- Its syntax and design center concepts familiar to developers, such as projects, applications, and components.
- It automates the creation of deployment configurations, build configurations, service routes, and other OpenShift elements.
- It is designed for quick iterations—as an example, it detects changes to local code and deploys to the cluster automatically, giving developers instant feedback to validate changes in realtime.
- It is completely client-based, so no server-side-component setup is required.
Odo also offers:
- Red Hat support for Node.js and Java components.
- Compatibility with other languages such as Ruby, Perl, PHP, and Python.
- Status updates for components and services on the cluster.
Odo works from any terminal on the Windows, macOS, and Linux operating systems, and it supports autocompletion for bash
and zsh
command-line shells.
That's enough overview. Let's see odo
in action.
Hands-on development with Odo
If you want to follow along with this example, start by downloading odo
for your platform of choice.
For macOS, the command is:
> curl -L https://mirror.openshift.com/pub/openshift-v4/clients/odo/latest/odo-darwin-amd64 -o /usr/local/bin/odo && chmod +x /usr/local/bin/odo
For Linux, it's:
> curl -L https://mirror.openshift.com/pub/openshift-v4/clients/odo/latest/odo-linux-amd64 -o /usr/local/bin/odo && chmod +x /usr/local/bin/odo
Next, clone the example source code:
> git clone https://github.com/RedHatGov/openshift-workshops.git > cd openshift-workshops/dc-metro-map
If you aren't already logged in to your cluster with oc
, run this and enter your login info:
> odo login https://api.yourcluster.com:6443
Alternatively, you could use the following link to get a token-based login (note that you must update the URL with your cluster's domain name): https://oauth-openshift.apps.yourcluster.com/oauth/token/display
.
We now have a setup for a sample Node.js application. In the next sections, I'll show you how to use odo
to deploy the app to a Kubernetes cluster; configure and connect the app to other services; and update an environment variable and verify the changes in a web browser. I'll conclude by showing you how to do a simple code change and quickly iterate through the development process before propagating your local code back into the Kubernetes cluster.
Part 1: Deploy the app
The first thing you'll do is set up a new project and deploy it on a Kubernetes cluster.
- Create a project that only you can work in by entering a command similar to the one below:
> odo project create jasons-odo
You should see output similar to mine below:
✓ Project 'jasons-odo' is ready for use ✓ New project created and now using project: jasons-odo
- Create a Node.js component for the new project:
> odo create nodejs
The output should look something like this:
✓ Validating component [61ms] Please use `odo push` command to create the component with source deployed
- Push the changes—in this case, a new component and the example application code—to the cluster:
> odo push
You should see something like this:
Validation ✓ Checking component [116ms] Configuration changes ✓ Initializing component ✓ Creating component [336ms] Pushing to component nodejs-dc-metro-map-zvff of type local ✓ Checking files for pushing [2ms] ✓ Waiting for component to start [1m] ✓ Syncing files to the component [7s] ✓ Building component [32s] ✓ Changes successfully pushed to component
The code is now running in a container on the cluster. But we also want to create a URL route into the code so that we can view the running application in a web browser. Next steps:
- Expose an HTTP route into your Node.js app:
> odo url create --port 8080
Check the output:
✓ URL nodejs-dc-metro-map-zvff-8080 created for component: nodejs-dc-metro-map-zvff To create URL on the OpenShift Cluster, please use `odo push`
- Push the new URL change to the cluster:
> odo push
Check the output:
Validation ✓ Checking component [88ms] Configuration changes ✓ Retrieving component data [107ms] ✓ Applying configuration [107ms] Applying URL changes ✓ URL nodejs-dc-metro-map-zvff-8080: http://nodejs-dc-metro-map-zvff-8080-app-jasons-odo.apps.yourcluster.com created Pushing to component nodejs-dc-metro-map-zvff of type local ✓ Checking file changes for pushing [7ms] ✓ No file changes detected, skipping build. Use the '-f' flag to force the build.
To verify that the deployment has worked, locate the URL in the command output just shown (or run odo url list
) and try opening it in your web browser. You should see something like the map in Figure 2.
Part 2: Configure and connect the app to other services
Next, you'll use odo
to add a database dependency to your Node.js app. For this to work, your cluster will need to have both OpenShift Service Catalog and Template Service Broker installed.
- Create the database and pass-in the defaults for config variables:
> odo service create mongodb-persistent --plan default --wait \ -p DATABASE_SERVICE_NAME=mongodb -p MEMORY_LIMIT=512Mi \ -p MONGODB_DATABASE=sampledb -p VOLUME_CAPACITY=1Gi
Here's the output:
Deploying service mongodb-persistent of type: mongodb-persistent ✓ Deploying service [55ms] ✓ Waiting for service to come up [3m] ✓ Service 'mongodb-persistent' is ready for use
Optionally, link
mongodb-persistent
to your component by running:odo link
. - Provide your Node.js app with the database credentials and other secrets needed to configure and connect to the database:
> odo link mongodb-persistent
You should see something like the following output:
✓ Service mongodb-persistent has been successfully linked to the component nodejs-dc-metro-map-zvff The below secret environment variables were added to the 'nodejs-dc-metro-map-zvff' component: admin_password database_name password uri username You can now access the environment variables from within the component pod, for example: $uri is now available as a variable within component nodejs-dc-metro-map-zvff
Part 3: Update the environment variables
Let's say you need to update some env vars
for your containerized Node.js app. Doing that with odo
is really straightforward.
- Tell
odo
whatenv var
to add or update:> odo config set --env BEERME=true
You should see something like the following output:
✓ Environment variables were successfully updated Run `odo push --config` command to apply changes to the cluster.
- Push the changes with the new
env var
to the cluster:> odo push --config
You should see something like this:
Validation ✓ Checking component [84ms] Configuration changes ✓ Retrieving component data [96ms] ✓ Applying configuration [40s] Applying URL changes ✓ URL nodejs-dc-metro-map-zvff-8080 already exists
Now refresh the page in your web browser. You'll see that the new env
has taken effect. Your map icons should now look like pint glasses, as shown in Figure 3.
Part 4: Iterate the inner loop
In this last part, I'll show you how to do a simple code change with odo
. I'll also demonstrate how iterating on your inner loop easily propagates local code into the cluster deployment.
- Edit the local file
public/assets/stations.geojson
to add a new bus stop. Append it to the bottom of the file, right after Ronald Reagan Washington National Airport:> vim public/assets/stations.geojson { "type": "Feature", "properties": { "name": "Presidential Metro Stop", "marker-color": "#ffd700", "marker-symbol": "rail-metro", "line": "blue" }, "geometry": { "type": "Point", "coordinates": [ -77.0365, 38.8977 ] } }
- Push changes to the cluster:
> odo push
You should see the following output:
Validation ✓ Checking component [86ms] Configuration changes ✓ Retrieving component data [96ms] ✓ Applying configuration [114ms] Applying URL changes ✓ URL nodejs-dc-metro-map-zvff-8080 already exists Pushing to component nodejs-dc-metro-map-zvff of type local ✓ Checking file changes for pushing [3ms] ✓ Waiting for component to start [23ms] ✓ Syncing files to the component [1s] ✓ Building component [3s] ✓ Changes successfully pushed to component
Now, refresh the web page. You should see that there's a new transit stop for the White House, as shown in Figure 4.
Conclusion
In this article, I showed you how to use odo
for a variety of day-to-day development activities (what I call the inner loop of a Kubernetes-based development process). I also showed you how to deploy and debug iterations of your inner loop directly into the Kubernetes cluster.
We completed all of the tasks required to develop and deploy the example application without writing any YAML, without bash
scripts, and without needing to understand the deep concepts of Kubernetes operations. Instead, we used the CLI and just a handful of commands—odo
, project
, create
, push
, service
, url
, link
, config
.
Odo can do a few things I didn't cover in this article. See the official odo documentation to learn more about its full capabilities.
Also, if you liked the concepts in this article but really don't like using a CLI, Red Hat has you covered. We've embedded odo
into a VS Code plugin and a JetBrains plugin, so that you can get the same capability directly in an IDE.
Odo is just one of the awesome tools that Red Hat has been working on to make it easier for developers to build modern applications with open source software. Stay tuned for more articles introducing these tools that are tailored just for developers.
Last updated: March 30, 2023