‘Running Service’ Blueprint for a Kubernetes Developer Portal
Internal developer portals exist to provide developers with a product-like experience that’s free of cognitive load, allowing developers to stay in the flow and be productive. They are set up by platform engineering teams to help developers serve themselves within guardrails and internal quality standards.
With portals, developers can simply and easily set up an ephemeral environment, restart a Kubernetes cluster, redeploy an image tag or scaffold a microservice. Platform engineering will make those actions reusable in the platform, and the internal developer portal will act as the interface to the platform and then reflect the changes in the software catalog.
But internal developer portals are more than loosely coupled product-like user interfaces that make developer lives easier. The internal developer portal also has a valuable software catalog that includes everything application-related in your engineering, from CI/CD metadata through cloud resources, Kubernetes, services and more.
The value of the software catalog is much greater than the metadata it contains (which is pretty neat, too) and goes way beyond showing who owns a service or where its logs are. In addition to being a single source of truth, its value comes from the way it provides context, especially in case of runtime data. It can quickly answer questions such as, “What is the current running version of service x in environment y?” even in cases that contain feature flags, canary or blue/green deployments.
Context and runtime data are the focus of this article. We will provide a detailed example of an internal developer portal for Kubernetes objects. We will then show the power of the software catalog and the fact that it can support workflow automation — anything from time to live (TTL) termination through service locking, triggering automated actions when services degrade, etc. — as a result of its combination of metadata and runtime data.
Spotify’s Backstage C4 Model for Internal Developer Portals
Software catalogs need a data model, and before you begin, you need to define it. It’s nothing too complex, but you do need a schema identifying what needs to be inside your software catalog. Software catalogs need to be unopinionated and completely flexible, so the best option is to let you define the data model yourself.
In Port, the schema for a type of entity (let’s say a K8s cluster) is called Blueprint. The actual entity (the actual cluster in this case) is called an entity. In Spotify’s backstage, the Blueprint is called “kind.”
Backstage, a leading open source internal developer portal and the third most popular Cloud Native Computing Foundation (CNCF) project, recommends beginning with a certain data model consisting of six blueprints (or kinds).
As Spotify’s senior engineer Renato Kalman and staff engineer Johan Wallin explain here, in designing Backstage they had a software visualization challenge: They needed a “standardized software metadata model to create a common language for communicating software architecture.” What they came up with was the C4 model. You can see an example of a Backstage C4 model here.
But this data model misses one point: the “running service” blueprint.
What Is a Running Service?
Your code is not your app. The code that lives in your repo or in a container image isn’t the app. In real life, your app exists on an environment and serves something (api/other services/users) within an ecosystem of tools and dependencies. It behaves differently depending on where it is.
The running-service blueprint, or as we sometimes call it “service in environment,” reflects the fact that the a single “service” is usually deployed to many different environments. Services can live in a variety of environments, staging, development, production. Services can also live in many different customer environments, especially in the case of single-tenant architectures.
This simple fact that the service lives in many different environments is reflected by the idea of the “running service” blueprint in Port. The “running service” entity lets us see the service “in the wild” — in the specific environment it actually lives in. Only this provides us with the correct and actionable context to understand what is going on.
Sticking to a static software catalog with a static data model that only includes metadata and not runtime data doesn’t provide the context we need. Insights exist only if you look at the real instance of the running microservice.
A Kubernetes Internal Developer Portal: The ‘Running Service’ Blueprint
Some argue that the growth of Kubernetes is one of the core drivers behind platform engineering. Kubernetes complexity, the expertise required of its practitioners and the recent movement of many developers to cloud native development all created increased load and friction between developers and DevOps.
Internal developer portals abstract Kubernetes away for developers. They let developers understand Kubernetes by showing them the relevant data, in context. They also support developer self-service actions. It’s important to ensure that these Kubernetes internal developer platforms include:
- All Kubernetes objects in the software catalog, not just microservices
- Multicluster support
- CRD support
Let’s look at how to set up blueprints (the data model) for a Kubernetes internal developer portal and then at how and when we include the running service blueprint for Kubernetes.
This is the basic set of blueprints for Kubernetes:
Workload is the “running service” for Kubernetes. It is a generic name for stateful sets, deployments, daemon sets and any other workload running in the cluster.
- A cluster represents a Kubernetes cluster in the infrastructure, providing the high-level connection between the different objects in the Kubernetes cluster.
- A node is a server that hosts and provides the runtime for the different applications and microservices in the Kubernetes cluster.
- A namespace is meant to group together many resources inside the same Kubernetes cluster, giving you the option to view how a complete environment hosted from the same Kubernetes cluster is connected.
- The workload is meant to be the focal point that provides the most relevant context to a developer about how their app is doing. The workload entity provides the developer with an abstract view of their different workloads. They can see the current status of the workload, such as instance count and health. By going upstream in the dependency tree, the developer can see what other applications and microservices are running next to their own workload, letting the developer understand if there are any connectivity or functionality issues.
- A pod is an instance of the workload, giving us visibility into the health of the pieces that make up the complete workload, as well as the ability to understand if there are any specific issues in the availability of the service provided by the workload.
You Should Begin Using a Running Service or Workload Blueprint
We’ve seen that the runtime blueprint, regardless of whether we call it “running service,” “workload” or even the literal “service in environment,” is useful. It reflects the reality in which a single service usually exists in several environments at the same time, such as development, staging, etc. It can also be deployed in many different customer environments. The running service provides the runtime data so we can understand the service in the context of its environment and deployment, as well as its real-time information, from uptime to status.