Being an API-first organization is becoming a must as organizations need to build APIs to enable consumers (internal or external) to extend the functionality of their systems, share data across organizations and build customized experiences.
The microservices architecture — building services that perform only one function, as opposed to covering an entire area of functionality — provides the agile and efficient building workflows needed to deliver seamless customer experiences.
Finally, Kubernetes, a container orchestration system, has been an extremely popular choice for orchestrating those microservices. It has helped adopt the organizational agile structure into the API development process, but has inherently introduced a new set of challenges.
Current API development processes require developers to adhere to an organizational set of best practices — if they even exist and assuming that developers have read those best practices and are implementing them — that can only recommend, but not enforce the best practices, giving turn to inconsistent API quality, (slow) developer experience and configuration control.
In this article we will discuss how you can address these challenges by implementing a design-first approach in your APIs and automating their deployment.
Most developers have been following a code-first approach to build their APIs. That is, implement the API first, and everything from documentation — usually code-generated OpenAPI specifications used with Swagger — to the organization’s policy requirements (security, etc) have come after the fact.
The code-first approach has increased the speed of the development itself, but it has compromised the consistent experience between the organization’s APIs and their quality.
To introduce consistency and quality to a code-first approach, organizations have usually introduced blockers in the deployment process (for example, requiring an API team approval) and in turn slowing down going to production.
Going design-first means you start by designing your API — writing how your APIs should behave and translating that to the OpenAPI specification — and, once it has been agreed upon, you would then start writing the code to implement the designed behavior of the API.
Design-first approach enables you to include multiple stakeholders from your organization early in the API design process. Additionally, there are tools that can validate the designed specification, which reduces risks of failure, improves consistency and enforces required aspects of the APIs.
A lot of companies have tried design-first methodologies, but have failed to maintain them after a while because they either could not set up the right process, or it was extremely time consuming or tedious.
In the following walkthrough, we will use three tools to help us set up the process required to go from design to implementation with little overhead. Our design-first approach will be the following:
We’ll use SwaggerHub to create our OpenAPI document which allows us to automatically validate the designed API against our standardization rules. The design-time validation ensures that the new API will be consistent with other APIs across the organization. Additionally, we can specify validation rules, to ensure operational consistency across our microservices landscape.
After that, the designed spec would go into a git repository that will help having a single source of truth of our APIs. This git repository will be connected to ArgoCD, which can then ensure that the cluster is up-to-date with the repository.
Finally, ArgoCD will use Kusk-gateway, an OpenAPI driven Kubernetes gateway, to deploy the API so developers can start implementing the services.
Enough talk — let’s see this in action — here comes a step-by-step walkthrough to get this in place for the automated deployment and execution of OpenAPI specifications in your cluster of choice!
Let’s start with setting things up for our APIOps-powered development!
1. Setting up a Github repository
Create a Github repository that we will use to put our OpenAPI specifications in and synchronize them with the deployed API in the cluster.
After the repository is created, create a new folder in the repository with the name api. This is where we will put our OpenAPI spec.
For that, run the following commands
mkdir api # folder where the OpenAPI spec will go to
git add . git commit -m “Initial commit”
git push origin main
2. Create a new API in SwaggerHub
In SwaggerHub, on the top left menu, click on “Create New API”
Fill in the form as shown below:
Once the API is created, let’s write an example API to deploy. Copy the spec below and paste it in your SwaggerHub editor.
OpenAPI allows extending the spec by use of decorators. To extend the OpenAPI specification, you just need to create a new section in the spec that starts with “x-”. In the spec above, you can see that we have used x-kusk to add Kusk-gateway’s configurations.
3. Connect SwaggerHub to your Github repository
To deploy it to our Github repository you will need to hover on the Sync button as seen below and click on Setup Integration.
Choose the Github Sync integration and click on Next.
In the next window, click on Connect to Github and follow the procedure to connect it. Remember to choose the right repository (the one we just created in the first step).
Now fill out the rest of the form as seen below. After that click on the Create and Execute button and click on Done in the next window.
To check if the integration works, click on the Sync button as seen below, Push the changes and you should see the updates in your Github repository!
4. Install Kusk-gateway in your Kubernetes cluster
Follow the Kusk-gateway installation guide.
5. Install ArgoCD in your Kubernetes cluster
Follow the ArgoCD installation guide.
6.Configure ArgoCD to use Kusk-gateway
ArgoCD allows the use of plugins that we will use to install Kusk’s CLI tool with, so that when our Github repository is updated, ArgoCD can run the CLI tool to generate the YAML manifests from the OpenAPI specification and apply them to the cluster.
Create a deployment patch manifest patch.yaml, this will be of type JSON-patch:
And apply it with the following command:
kubectl patch deployments.apps -n argocd argocd-repo-server --type json --patch-file patch.yaml
Now let’s add Kusk CLI to ArgoCD’s plugin ConfigMap. Create the file
As you can see here, we’re using the command
kgw api generate which creates the Custom Resources (manifests) that ArgoCD will then add to our cluster. Apply the patch with the command:
kubectl patch -n argocd configmaps argocd-cm --patch-file argocd-plugin.yaml
Finally, create the ArgoCD application that will manage your API’s gateway deployment.
Create the file
Notice that we have defined
path: api which is the folder in the Github repository with the
api-spec.yaml from the steps earlier. We have also defined the
.destination.namespace to be
default, which is where the gateway should be deployed in the cluster. And apply it with
kubectl apply -f kusk-gateway-application.yaml
7. Run the initial ArgoCD sync and check your cluster
On ArgoCD’s dashboard, we will now see the newly created application. Let’s click to get into it and sync our API.
And now click on Sync to create the gateway for the first time.
And voilà, there’s our newly created gateway created and managed by ArgoCD with every new update on the OpenAPI spec in the Github repository!
8. Consuming the Deployed API
In our API we have configured Kusk-gateway to mock our single endpoint, so we can have a testable endpoint before implementing the service. It uses OpenAPIs example section to use as a response mock of the API.
For that we will have to get the Kusk-gateway API endpoint, which you can find by running
kubectl get svc -l "app.kubernetes.io/component=envoy-svc" --namespace kusk-system
Copy the External IP from the result and query the /hello path defined in our OpenAPI spec:
$ curl 127.0.0.1/hello
And we are set to start implementing the API!
This flow of programmatic API design we call it the APIOps, which combined with GitOps philosophy (having your repository as a single source of truth, combining it with CI/CD pipeline) provide a powerful alternative to a more traditional code-first approach not so closely aligned with the lifecycle of Kubernetes applications.
Let us know what you think about this method, we’re open to hearing your feedback in our Discord server!
You can also check the webinar on this article if you want to see the action yourself!