Designing a DIY PaaS (Platform as a Service)

Aimed at those looking to create a DIY PaaS to simplify deployment workflows, this is the first post in a series on PaaS architecture, implementation and deployment.

What is a PaaS?

Platform as a Service, or PaaS, refers to a platform and environment abstraction over underlying infrastructure (public cloud providers are referred to as Infrastructure as a Service,IaaS, providers), making it easier for developers to deploy applications and services.

PaaS platforms are typically hosted in the cloud, either as part of a shared/dedicated infrastructure pool maintained by the provider (e.g. Heroku, Bluemix) or as a set of platform tools that can deployed on infrastructure owned by users (e.g. Pivotal Cloud Foundry, Openstack).

For the Hasura k8s platform, you can choose between a hosted version or a self-hosted version. You can also migrate seamlessly from one to the other.

A new trend is certain large organisations building their own PaaS (also known as DIY PaaS) so that their tooling is tailored to their specific requirement. In this post, aimed at those wishing to setup their own PaaS like tooling, we go over the problems that a PaaS should aim to solve, potential approaches to solve these problems and considerations that should inform any design choice you make.

What problems does a PaaS need to solve?

As an abstraction layer over infrastructure, a PaaS needs to primarily solve the following problems:

  1. Make code independent from the machine it runs on.
  2. Provide tooling to help developers with software deployment and scaling.

Several abstractions are needed to support a typical code-machine interaction workflow:

Abstractions needed in a PaaS
  1. Provision infrastructure
  2. Install dependencies on the infrastructure
  3. Install code/binaries on the provisioned machines
  4. Edit configuration files
  5. Run the code under a supervisor
  6. Update the frontend server/API gateway

Let’s take a look at each of the above problems and potential solutions in more detail:

1) Provision infrastructure

Problem: A LOT of entities need to be created, installed or configured as shown here:

Solution: The following options form a potential solution to the problem:

1) Use virtualized infrastructure.
2) Use CoreOS for:

  • Updates with full rollback
  • Decouples OS from application level concerns

3) Use Infrastructure providers’ APIs to automate the lifecycle of VMs:

  • Create a VM
  • Update a VM
  • Delete a VM
  • Add a VM to cluster
  • Remove VM from cluster

2) Install dependencies on the infrastructure

Problem: A PaaS needs to handle both system and application dependencies.

Solution: Simple — Just use containers (Docker, Containerd or rkt). Containers help package all dependencies along with code inside a single image and the responsibility of packing them is offloaded to the developer.

3) Install code/binary on the machine

Problem: Code is frequently updated. For every update, latest code needs to be installed on the VM.

Solution: Once again, containers come to the rescue! An elegant solution to this problem is to build a new container image for every code update. A git-based pipeline, that is triggered on every update to a code repo, copies the code to the VM and automates the process of building the image on the VM itself massively improves the developer experience.

A ‘git-push’ based CD pipeline

4) Edit configuration files

Problem: The following configurations need to be handled for every deployment or change in environment:

  • Configuration arguments and conf files
  • The IP/Port for addressing deployed services
  • Passwords and secret keys

The complexity of handling this gets significantly worse on a cluster.

Solution: Most configuration should be a part of the container. A container orchestration tool that handles service discovery via an internal DNS and provides a cluster wide configuration management system can then inject the arguments to these parameters.

Kubernetes based solution to managing configuration and service discovery

5) Run code under a supervisor

Problem: A supervisor is needed for handling the following:

  • Logs, log-rotation
  • Restart services/containers on init
  • Restart services/containers on crash

Solution: While, as of now, custom tooling may be required for managing logs, container orchestration tools can handle the latter two. Most orchestrators provide primitives that manage the state of the underlying resources.

6) Update the frontend server / API gateway

Problem: The API gateway needs to be reconfigured and redeployed every time there are changes in the system. For e.g. each new deployment causes a new upstream IP/Port.

A reactive gateway with a distributed key-value store and an operator agent

Solution: A reactive API gateway needs a cluster operator agent that watches on changes and, then reconfigures and redeploys the gateway. The operator will have to rely on a distributed database that supports watching on changes and is updated when new containers are deployed.

A complete PaaS, incorporating solutions listed above, may then look something like this:

Having said that, there are a few other problems that a PaaS needs to address like having a standardised deployment methodology, figuring out the levels of transparency into underlying components (and providing a secure method to access them if choosing to go the developer-friendly route), managing stateful services etc.

In our next post, we will take a look at a sample implementation using Docker and Kubernetes as our choices for container and orchestration technologies respectively and address the problems listed above.

Hasura is an open-source engine that gives you realtime GraphQL APIs on new or existing Postgres databases, with built-in support for stitching custom GraphQL APIs and triggering webhooks on database changes.