Automating Kubernetes Deployments with Postman
5 min read
Kubernetes is the most widely used container-based orchestration platform today. Practitioners are often segmented by specialty:
- Application Developer
- Security Specialist
According to the currently in-progress Kubernetes Usage Report 2021, one relevant discovery is that Kubernetes deployments do not live in isolation. Most organizations are running a combination of bare metal, VMs, and Kubernetes.
Due to the persistent need to manage heterogeneous infrastructure, Kubernetes specialists are often tasked with other job responsibilities. How do we wrangle the dissonance in application deployments, administration, security, and orchestration? The reality is that we're saddled with the necessity of integration.
Today, the communication and interaction possibilities are endless:
- B2B partner services
- Data migration
- Legacy system reuse
APIs are not just glue code. They enable value chain optimizations through platform ecosystems. (blah blah blah) APIs are the raw materials we piece together to make this magic happen. This is what's driving so much adoption of quirky mashup delights. It's not just shiny object obsession, though if we're honest with ourselves, our little raccoon paws have a wandering mind of their own. 🦝
Here's what we're going to accomplish:
- Get a Kubernetes cluster up and running
- Build a server to fetch local Kubernetes resource files
- Run a proxy to the Kubernetes API Server
- Use Postman to deploy our application
Okay, okay, okay... Let's get to it. Here's our inventory:
Here's what we're looking to accomplish:
Kubernetes is an API-driven container orchestration platform. Most people are
familiar with using the
kubectl CLI to send commands to their cluster. Fun
kubectl is just using APIs under the hood. Don't believe me? Tack
to the tail end of any
kubectl command, and let the HTTP wash over us. 🌊
Now that we know we can make API calls to pull the strings of Kubernetes, let's see what we can do in Postman. Here's a public workspace to follow along!
Let's step through what's going on here.
First and foremost, we'll need a Kubernetes cluster. Cloud providers offer managed options that are relatively quick and easy to get up and running. For this walkthrough, we'll be using Amazon Elastic Kubernetes Service (Amazon EKS). One of the easiest ways to get an Amazon EKS cluster up and running is to use the Amazon EKS Quickstart CloudFormation template.
Once our cluster is up and running, we'll need to create an SSH tunnel to our
bastion host. Using default security options with the Amazon EKS Quickstart
template, only the bastion host
has access to
kube-apiserver. This prevents outside access to our precious
Pods. However, we'd like to use
kubectl on our own workstations so we can test
our integrations. Scott Lowe has an easy-to-follow blog post on how to do this:
Using kubectl via an SSH Tunnel.
Before we get started with local testing, there are a couple of servers we need to run. If the Postman collection is going to deploy Kubernetes resources, it needs a way to access those resources. Furthermore, we need a way of accessing the Kubernetes API. These will require setup for both local testing and testing in our CI/CD pipeline.
kube-apiserver validates and configures data for the cluster.
It's exposed via a REST API and is the front door by which we'll enter. The
kubectl CLI has
a built-in way to run a local proxy,
and we'll utilize the default URL
http://localhost:8001 for our local testing.
When we run our Postman collection in our CI/CD workflow, we'll be
accessing the API from a Pod
where we'll use a different URL,
https://kubernetes.default.svc. Don't worry.
These URLs can be set as variables in Postman and changed depending on our
We're going to run a local server in our CI/CD pipeline that's going to conveniently serve the Kubernetes resources over HTTP! One benefit of this is that we can actually use this server when testing our collection run in Postman. Here's a quick implementation in Node.js. After initializing a new Node.js application, be sure to install a couple of dependencies.
After we have our new Node.js application and our dependencies, let's write a basic HTTP server that will aggregate Kubernetes resource YAML files and return them as JSON. Our Postman collection will use these JSON representations to deploy to Kubernetes.
Now let's start this server before we begin testing.
Remember the URL for the kube-resource-server (default:
http://localhost:3001). We'll need it later. This one stays the same whether
running locally or in our CI/CD workflow.
While we're at it, let's run that Kubernetes proxy, too.
Next, we'll walk through each part of the Postman collection. Then we'll work on actually running it!
This step is only necessary when running in the Postman Collection Runner. With Postman, we want to enable both a real-time developer experience and a way to automate collection runs via the command line. To do that, we'll use Newman. For now, let's see if we can make some API calls!
This step resets all collection variables that are required for the collection run. When running in Newman, we'll skip this step by only running the Run folder from this collection.
Finally, we get to use our nifty little Node.js server! If it isn't already running from the instructions earlier, go ahead and fire it up now.
In order for this to be successful, we need to add a couple of Kubernetes YAML
files to our
And the service...
Once we've got everything in place, we're ready to hit the Kubernetes API and deploy our application! The Kubernetes API can be fairly complex at times. Luckily, we already have these requests ready in Postman, and we can re-use them across all of our projects.
Now that we have an understanding of the collection workflow, let's take a look at the variables that make this all work.
Required to access the Kubernetes server and the resource server that will run in the CI/CD pipeline.
kubeBaseUrl- The URL for Kubernetes. If you're testing locally, you should have
kube proxyrunning, and the URL should be
http://localhost:8001. If you're running this collection in Kubernetes, the URL should be
kubeNamespace- The default namespace to create/update resources. If the resource has a
metadata.namespacefield, that takes precedence.
resourceBaseUrl- The URL to the service that will run in your CI/CD environment. It can return resources that can be deployed (e.g., deployment and service YAML files stored in your code repository).
fieldManager- Kubernetes server-side apply requires field management.
forceUpdates- Only needed if resources were previously created/updated by something other than Postman, such as
kubectl. More information here: Server-Side Apply.
These can all be overridden in an environment. Here's a snapshot for a local configuration.
And finally, cue the drum roll... 🥁
When we run the collection, not only do we see all the API calls being made, we also see test execution happening for each call. The test results we see are verifying the success of our application deployment.
Now, if everything worked correctly, the service should be accessible via the proxy at http://localhost:8001/api/v1/namespaces/default/services/jsonplaceholder-svc/proxy/posts/.
We did it! Finally, we have API testing for our integrated deployment environment.
To put a bow on all this, we can actually automate Postman collection runs in our CI/CD pipelines using an open source CLI called Newman. All we need to do is integrate our Git repository with an API version in Postman.
Here's an example of running this same collection from within a Pod in our Kubernetes cluster! There's a lot more to this, but that's a whole 'nother post.
This just scratches the surface of what's possible with API-driven deployments. Here are some ideas for upgrading our workflow:
- Canary deployments with manual job approval.
- More complex orchestration with databases and message brokers.
- Environment promotion with Slack notifications and the CircleCI API.
API-driven automation allows us to use existing tools and infrastructure, leveraging the investments we've already made. This isn't shiny object syndrome. It's perseverance.
Still, it probably wouldn't hurt to just try the next shiny thing... 'Til next time! ✨
Disclaimer: This post mentions Postman. I work there. 🚀