Reimplementing the AWS EKS API with Clojure using BigConfig, Rama, and Pedestal

The world of cloud infrastructure often involves interacting with complex APIs. While services like AWS EKS provide robust management for Kubernetes clusters, there might be scenarios where you need a more tailored or localized control plane. This article will guide you through reimplementing the AWS EKS API using a powerful Clojure stack: Pedestal for the API, BigConfig to wrap Terraform and Ansible in a workflow, and Rama for state and jobs.
Why Reimplement?
Section titled “Why Reimplement?”Before we dive into the how, let’s consider the why. K8s, Spark, ClickHouse, Postgres, and so on are all good candidates for an in-house software as a service. Reimplementing a cloud API might seem counterintuitive, but it can be beneficial for:
- Avoiding vendor lock-in: This can be relevant for some companies.
- Multi-cloud strategy: You need an EKS-like solution in multiple cloud providers and you need a generic API.
- Saas: You have an open source software and the Saas is your source of revenue.
- Metal: You cannot use the cloud but you want to provide the same developer experience in your company.
- Integration costs: Buying EKS and integrating it with the rest of your infrastructure is not feasible or very expensive. Building an EKS-like solution is cheaper.
Disclaimer: This is a simplified blueprint for educational and experimental purposes. It will not cover the full breadth and complexity of the actual AWS EKS API.
The Clojure Stack
Section titled “The Clojure Stack”Here’s a quick overview of the tools we’ll be using:
- BigConfig: A workflow and a template engine that enables us to have a zero-cost build step before running any devops tool like Terraform or Ansible.
- Rama: A distributed stream processing and analytics engine that can also function as a durable, highly concurrent data store. We’ll use Rama to manage our cluster definitions and state.
- Pedestal: A comprehensive web framework for Clojure that emphasizes data-driven development and offers excellent support for both synchronous and asynchronous request handling. It will serve as our API gateway.
Let’s imagine the core entities we want to manage: EKS Clusters. For simplicity, we’ll focus on creating and describing clusters.
First principles
Section titled “First principles”- Reuse GitOps: Building a single K8s cluster with GitOps should be reuseable. Replacing GitOps with an API should not require to reimplement everything from scratch. The solution should contain a more generalized version of the GitOps one for one cluster.
- Declerative when possible: Terraform should be used to create resources instead of the AWS APIs whenever it is possible.
Sequence diagram
Section titled “Sequence diagram”Deliverables
Section titled “Deliverables”- Pedestal API: to create and describe clusters.
- Rama Module: to store the desired state, clone the repo, and invoke BigConfig with the desired state.
- BigConfig Module: this is where the heavy lifting is happening:
- Workflow: achieved the desired state will require multiple steps.
- Lock: to be sure that changes are ACID.
- Build: to generate the configuration files for Terraform based on the desired state.
- Apply: to run
terraform apply
programmatically.
Perks of the solution
Section titled “Perks of the solution”- Modularity: Every deliverable can be developed in parallel by adopting contracts.
- Uniformity: BigConfig, Rama, and Pedestal deliverables are written in Clojure.
- Declerative: Creating an EC2 instance programmatically can be done faster with Terraform and we don’t need to worry about the life cycle management.
- Reusability: The GitOps code can be reused. This is a killer feature. The code to provision one resource with GitOps or multiple resources with an API, doesn’t require to change from Terraform to the AWS SDK. The API is just a virtual admin.
The code
Section titled “The code”I’m working on the code right now. Stay tuned, I will update the blog post as soon as I have the first version.
Further Enhancements
Section titled “Further Enhancements”This is a basic example, but you can extend it significantly:
- More EKS Features: Implement more aspects of the EKS API, such as node groups, Fargate profiles, or update operations.
- Authentication and Authorization: Integrate with a robust authentication system to secure your API.
- Error Handling: Implement more sophisticated error handling and meaningful error messages by adopting OpenTelemetry.
Conclusion
Section titled “Conclusion”By combining BigConfig, Rame, and Pedestal, we’ve built a foundation for a custom EKS-like API in Clojure. This approach provides a high degree of control, flexibility, and the ability to tailor your infrastructure management precisely to your needs. This project serves as an excellent starting point for exploring the potential of building custom cloud-native services with Clojure.
Would you like to have a follow-up on this topic? What are your thoughts? I’d love to hear your experiences.