Linkerd and the Gateway API

Linkerd and the Gateway API

William Morgan

Aug 22, 2022

In the upcoming 2.12 release, Linkerd will take a first step towards adopting the Gateway API as core configuration framework. While this API was originally designed to handle ingress traffic, we believe it has a lot of potential for service meshes as well. In this blog post we'll cover some of our thinking behind this choice and what, if anything, it means for you.

Standards considered harmful...?

First things first: the Gateway API is a standard, at least in the broad definition of the word, and we on team Linkerd are wary of standards. In the service mesh world, the word "standard" usually means one of the following things is happening:

  1. A vendor is promoting an API that they claim is neutral but actually favors their own implementation, and will soon use their conformance to that standard as a marketing weapon against you.
  2. A potential user is evaluating your project and has been given a checklist of requirements, including "does it follow the X standard?," which they would really, really like to just check off without having to spend too much effort thinking about what it means and how relevant it is to what they're trying to accomplish.
  3. A project is promoting itself as the "de facto standard" in an attempt to gain adoption by FUD rather than technical merit.

We've seen all of those things first-hand. They're all terrible, and none of them have anything to do with the actual benefit of a standard: ensuring interoperability between different implementations.

Interoperability is a great goal, but it's not actually an issue for service meshes. Service meshes are already interoperable! You can put one service mesh on service A and a different one on service B, and A and B can still communicate. The standards that matter for service meshes are things like HTTP and TCP, and, well, we already have those.

What about the interoperability in the sense that a standard could allow service mesh users to swap out one mesh implementation for another? Unfortunately, we don't think that's really a realistic scenario. We've certainly seen people migrate to Linkerd from other meshes, but it takes effort and planning and testing and is very, very far from a matter of just swapping out one implementation for another. The operational concerns are the dominant factor here, not the API used to access the mesh.

In short, we don't really believe today that there's any intrinsic value to a standard API for service meshes, and there are in fact many reasons why such a thing should probably be avoided. 

So given all that, why would we dip our toes into the murky waters of standards (once again!)? Because the case of the Gateway API has something to offer Linkerd that actually is very valuable to the project: configuration machinery that is built into Kubernetes itself, that we can reuse rather than introduce our own.

To CRD or not to CRD

By configuration machinery, we mostly mean Custom Resource Definitions. CRDs are amazing and powerful and give you the ability to have structured and validated configuration for your Kubernetes resources. But from the users' perspective, they are a burden: another specialized object living on the cluster with a special set of rules that must be followed, and which must be upgraded, maintained, and cared for. For that reason, we've been very conservative in adding CRDs to Linkerd. We've introduced something like four CRDs over the years and those only grudgingly.

Unfortunately, our reluctance to add CRDs to Linkerd acts in tension with our desire to, you know, add features to Linkerd. Intelligent defaults are great, but we need the ability for people to tailor Linkerd's behavior to their requirements in structured, cohesive ways.

So the Gateway API gives us an out: since it is part of Kubernetes itself, the more we can rely on it, the less configuration surface area of our own that we need to introduce. In other words, if we can use the CRDs from the Gateway API then we don't have to add those CRDs to Linkerd.

Linkerd remains simple, and Linkerd gets new features. Sounds good, right?

The Gateway API is pretty good

Of course, none of this would make any sense unless the CRDs in the Gateway API make sense for Linkerd. And fortunately, they do! The Gateway API is pretty well designed: even though it was originally meant to handle ingress traffic, only a small portion of it is really ingress-specific. The majority of the Gateway API is a set of CRDs that describe, in fairly general terms, how classes of traffic are routed, transformed, and delivered to services on the cluster—exactly like a service mesh does.

For example:

  • The HTTPRouteMatch object provides a general way to represent classes of HTTP traffic defined by path or header information, useful for a variety of route-based logic.
  • The HTTPRouteFilter object provides a general way of expressing "processing" to be done on traffic, providing a way to parameterize features like rate limiting, per-request authorization, and more.
  • The Policy Attachment model provides a consistent model of policies (such as timeouts) with clear semantics around how defaults and overrides work in hierarchical applications.

Aesthetically, the Gateway API provides a good balance between structure and extensibility and we're optimistic that even Linkerd's advanced features, such as request tapping and zero-config mutual TLS, can be captured by this model.

What will happen in Linkerd 2.12?

Putting that all together: In the upcoming Linkerd 2.12 release, Linkerd will introduce per-route authorization policies, and these policies will be configured via the Gateway API.

Well, sort of. There are bits of the Gateway API today that require things that don't really match up with what Linkerd does. Rather than shipping a non-conformant implementation or adding unnecessary things to Linkerd, for 2.12 we're taking the simple approach and implementing a subset of the API. So for Linkerd 2.12, we will introduce a mirrored set of CRDs as a first step. These CRDs will be published by Linkerd in a package but will otherwise be basically identical to the ones in the Gateway API.

We're optimistic that in the future we'll be able to deprecate these mirrored CRDs and switch users over to the "true" CRDs without non-trivial effort on the part of our users. We'll be participating in the ongoing conversations around enhancing the Gateway API for service mesh use cases (especially the newly-formed GAMMA initiative) to ensure that the Gateway API evolves to serve the needs of Linkerd's users.

What does this mean for Linkerd users?

In the short term, practically nothing. Per-route authorization is coming (yay!) in Linkerd 2.12 and it will involve a bunch of new CRDs which happen to be mirrored from the Gateway API, though where the CRDs come from probably won't make any difference for you. In subsequent releases, features like circuit breaking and header-based routing will also be configured by Gateway CRD types.

Eventually, when the Gateway API is fully ready for Linkerd, you'll need to swap to the "true" CRDs shipped with Kubernetes. This will affect you—you'll have to migrate—but it should be a trivial (regex-able) change that will be similar to any kind of CRD deprecation cycle with plenty of time to fix your YAML. And in exchange, Linkerd itself will be smaller by introducing only the bare minimum of CRDs to your cluster.

Questions? Comments? We'd love your feedback on this. Find us in the Linkerd community Slack or on GitHub and let us know what you think!

Linkerd is for everyone

Linkerd is a graduated project of the Cloud Native Computing Foundation. Linkerd was created by Buoyant and is 100% open source. If you have feature requests, questions, or comments, we’d love to have you join our rapidly-growing community! Linkerd is hosted on GitHub, and we have a thriving community on Slack, Twitter, and the mailing lists. Come and join the fun!

(Photo by Thomas Vogel on Unsplash)