Gateway API for Teleport K8S
If you've been reading some of my mutterings for a bit you know I run Teleport and love it. Over the past couple of years I've been running Teleport within my OpenStack cloud and while that's been great, I've wanted to push Teleport into my Kubernetes cluster, however, I've been reluctant to do it because VM was working so well. That said, with the development of Genestack we've been using the Gateway API and I found a desire to tinker, a need to learn. So I did what any self-respecting nerd would, and decided to break an otherwise stable and perfectly functioning service so that I can redeploy in a new and different way.
Background
In Kubernetes the Gateway API has been released and introduces some much needed functionality that carries it beyond where the basic Ingress provider could. Read more about the Gateway API here. Within Genestack we're using the NGINX Gateway Fabric (by default) to provide access to our API services. This system scalable and able to be used in a lot different ways across the Kubernetes cluster environment.
Teleport provides a Kubernetes deployment model which makes several assumptions about how and where systems are deployed. That said, the core functionality of Teleport is able to be serviced on any Kubernetes environment so long as the basic access features are able to satisfied. This is where the Gateway API comes in, for the purpose of my environment, Teleport will be deployed in the teleport-cluster
namespace via helm
and the Gateway API will service as our "load balancer."
In the following examples you must change your.domain.tld to the domain you wish to use within the teleport cluster.
System Overview
At the time of this writing here's the overview of my environment
- Kubernetes
v1.28.6
- NGINX Gateway Fabric
1.4.0
- The NGINX Gateway Fabric deployment was done with experimental features enabled
- Service deployment is using
apiVersion
v1alpha2
- Teleport 16.4.x
System Setup
I'm not going into the actual deployment of the gateway services or Teleport itself, both of those processes are well documented upstream.
That said, I will share my teleports helm values file because getting this all working is Kind of a nightmare and I wouldn't want anyone to have to go through this discovery adventure...
clusterName: teleport.your.domain.tld
chartMode: standalone
proxyListenerMode: multiplex
#proxyProtocol: "off"
acme: false
publicAddr:
- teleport.your.domain.tld:443
authentication:
type: github
localAuth: true
proxy:
highAvailability:
replicaCount: 1
highAvailability:
replicaCount: 1
podDisruptionBudget:
enabled: true
certManager:
enabled: true
issuerName: "letsencrypt-production"
addCommonName: true
addPublicAddrs: true
ingress:
enabled: false
log:
level: INFO
High level this deployment config is making some assumptions that cert-manger is deployed within the Kubernetes cluster and will be usingletsencrypt
to issue certificates. This is also setup to usegithub
authentication to users. Change these values to suit your needs.
Gateway Setup
This post is all about using the Gateway API for our services in conjunction with Genestack; effectively combining our Kubernetes and OpenStack clusters to serve a greater purpose. So this post is mostly covering the deployment of the routes and listeners I use within those systems to support the workload, Teleport.
Routing
The first setup is to setup our routes. The routes allow Teleport to terminate TLS within the pods on port 443 and ensure that any connection going to the proxy service are redirected to a TLS connection. To do this achieve the goals, create a simple manifest named teleport-tlsroute.yaml
and apply it to the environment.
apiVersion
is set to v1alpha2
. Teleport is running in the teleport-cluster
namespace and our gateway services named flex-gateway
are running in the nginx-gateway
namespace.Certificate Issuer
Here's the certificate issuer I'm using, this is made so that the Gateway API can be used to validate http and dns certificate requests. This file is saved at teleport-issuer-gateway.yaml
.
Take note that this is using the CloudFlare API to validate DNS01 challenges from LetsEncrypt. If you do not use LetsEncrypt or do not use CloudFlare, be sure to adjust this file according to your environment.
To apply the manifest use a simple kubectl
command like so.
kubectl apply -f teleport-tlsroute.yaml teleport-issuer-gateway.yaml
Listener Patches
Next we patch the listeners to include the new TLS protocol and route. To run this patch create a new patch file named teleport-tls-listener.json
with the following content.
Apply the patch to the running gateway instance
kubectl patch -n nginx-gateway gateway flex-gateway --type=json --patch-file=teleport-tls-listener.json
Validate Functionality
Once the patch is applied run a describe on the gateway service to validate functionality.
kubectl -n nginx-gateway describe gateways.gateway.networking.k8s.io flex-gateway
The output will show you all of the listeners running, the output your looking for will be something like so.
Accessing Teleport
Assuming everything is working normally, you should now be able to access Teleport on the domain defined, in the example that would be your.domain.tld
.
There's absolutely no need for an load balancer (AWS or otherwise) now that we have the power of the Gateway API.
From here, simply access Teleport normally. If you're on the setup process, proceed to Step 2/2 to generate some local users.
Client Login
Because Teleport is attempting to use a Proxy, you will need to set the environment variable TELEPORT_TLS_ROUTING_CONN_UPGRADE
with a value of true
. This environment variable can be defined on the command line, or in your terminal environment RC file: .bashrc
, .zshrc
, etc... This export can also be used on the command line at auth runtime, like so:
TLSRoute
. Until then, I'm setting the option accordingly.That's is, That's all
Simply blog post on how I use the Kubernetes Gateway API to run my Teleport environment, now running on the same cluster as my OpenStack Cloud, all powered by Genestack.