Host-less TLS Ingress resources in BKPR

First of all, let me state that what is described in this article is a proof of concept (PoC) intended for Bitnami Kubernetes Production Runtime (BKPR). As such, I am describing ideas and a plausible implementation for them while, at the same time, seeking feedback to understand whether this could be a useful feature.

The Bitnami Kubernetes Production Runtime (BKPR) is a collection of services that make it easy to run production workloads in Kubernetes. The services are ready-to-run and pre-integrated with each other, so they work out of the box.

One of the goals of BKPR is reducing the complexity required to deploy and run not just Kubernetes itself, but the applications and services running on top of it.

One such idea I have always missed from a plain Kubernetes cluster is simpler Ingress resources. Take for instance the simplest descriptor for a TLS-protected Ingress in Kubernetes, which may look like this:

The rules section consists of a list of paths that are front-ended (and protected by TLS) by this Ingress. From this manifest: /tea and /coffee.

The tls section contains two relevant fields:

  • secretName: references the Kubernetes Secret which holds the private key to the X.509 certificate that will be used to protect this resource over TLS.
  • hosts: a list of fully-qualified DNS domain names that the Ingress Controller will accept in order to front-end the resources described in the rules section.

The combination of the tls and rules sections produces a routing map that allows you to reach the Kubernetes Service named tea-svc under and the Kubernetes Service named coffee-svc under

Now imagine that your company manages two production Kubernetes clusters: and Next, imagine that you want to deploy this simple Web application in these two productions clusters. The manifest showed before can be deployed on the Kubernetes Kubernetes cluster, but can’t be deployed as-is on the cluster. For more complex applications, this problem becomes more apparent.

It would be great if BKPR could add the correct hostnames for you, automatically, as BKPR already has configuration related to your domain. That would allow us to (re-)write a simplified version of the previous manifest as:

Note that the hostnames are gone now, removing cluster-specific information from it. In theory, you can deploy this manifest unmodified onto the and clusters. In reality, if you ever tried to deploy this manifest on a plain Kubernetes cluster, you would get an error from the Kubernetes API:

I had a look to mutating admission webhooks and thought they might be a good fit for this use case.

A mutating admission webhook is part of the cluster control-plane and is essentially an HTTP callback that receives admission requests and may change them to enforce custom defaults. A mutating admission webhook requires that the Kubernetes cluster:

  • Runs v1.9 or newer
  • Has MutatingAdmissionWebhook and ValidatingAdmissionWebhook admission controllers enabled
  • Has API is enabled.

So I wrote a mutating admission webhook that is called back for every API request to create or update a Kubernetes Ingress resource. For such requests, it ensures that valid, fully-qualified DNS hostnames are automatically inferred and the request modified accordingly.

When my mutating admission webhook is deployed on my BKPR cluster, configured to use as its domain name, you can deploy this manifest just fine:

And if you describe the Ingress resources:

You can see that the Ingress resource was automatically patched to have the Ingress resource configured to terminate requests for, which has been inferred from the Ingress name and BKPR’s DNS suffix.

Beautiful, isn’t it?

Now, about the inner workings.

When I mentioned that the Ingress resource was automatically patched, what happens under the surface is that its create request is dispatched to a mutating admission webhook. This webhook is deployed automatically when BKPR is installed and is configured to intercept all API requests that update or create an Ingress resource. For every such request, this webhook inspects the Ingress object and applies the following logic:

  • When there are no hosts specified in the tls section, the webhook will patch in a hosts entry that consists of a single entry, derived from the Ingress name and BKPR’s DNS suffix.
  • When there are hosts specified, each item is inspected and any unqualified name is qualified by appending BKPR’s DNS suffix.

This webhook is associated with a MutatingWebhookConfiguration object that describes what API operations will be intercepted and how to deliver those to a Kubernetes Service that will handle them:

The Kubernetes Service:

And finally, the Deployment:

The tlsCertFile and tlsKeyFile command-line arguments to the webhook are required because the actual webhook implementation is an HTTP server that listens for API requests that pass the MutatingWebhookConfiguration over HTTP/S.

The code that handles the process of mutating a create or update request for an Ingress resource lives in:

The return value states that the API request is allowed — after all, a mutation admission webhook is a superset of a validating admission webhook — and returns the serialized patch that has to be applied to the original API request.

As you can see, mutation admission webhooks are an extremely powerful way of extending and customizing Kubernetes. In the specific case of BKPR, as illustrated above, they remove complexity by inferring certain attributes from BKPR’s configuration.

The entire source code for this is available here:

Bitnami Perspectives

Loved by devs, Trusted by ops: Bitnami makes easy to use…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store