Exposing External Services in Contour

Alex Turner
2 min readMar 14, 2021

Like many, I run a home server for storage, media delivery and other other such exciting things. As a very hands on learner, I decided a little while back that I’d redeploy my server (running Ubuntu with a single docker-compose file) to instead run a VM hypervisor platform (Proxmox) with Kubernetes on top. It’s been a wonderful exercise in decreasing uptime but as a good mate explained the other day, even 0.99% uptime still has some 9s in it.

Kubernetes is a fantastic tool for service deployment especially given the ease of which you can consolidate your certificate generation / secret storage and HTTP routing to a single endpoint or load balancer. I have a wildcard domain record that I point to my cluster endpoint and I create HTTPProxy objects (because Contour is awesome) for each of my Kubernetes services. But what if I want to route to a service that’s outside of my cluster? Say, proxmox.mydomain.com? Kubernetes doesn’t exactly make this simple (or finding out about it simple).

The first part makes sense, we define HTTPProxy manifests as we would with any other service; I like to split my HTTPProxy across namespaces:

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: proxmox
namespace: projectcontour
spec:
virtualhost:
fqdn: proxmox.mydomain.com
tls:
secretName: wildcard
includes:
- name: proxmox
namespace: default
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: proxmox
namespace: default
spec:
routes:
- services:
- name: proxmox
port: 8006

Simple enough, but more critically we need to define a headless service which will allow us to define our Endpoint, pointing to our cluster resolvable IP address:

apiVersion: v1
kind: Service
metadata:
labels:
run: proxmox
name: proxmox
namespace: default
annotations:
projectcontour.io/upstream-protocol.tls: "8006"
spec:
ports:
- name: app
port: 8006
protocol: TCP
targetPort: 8006
type: ClusterIP
clusterIP: None
---
apiVersion: v1
kind: Endpoints
metadata:
name: proxmox
subsets:
- addresses:
- ip: 192.168.2.254
ports:
- name: app
port: 8006
protocol: TCP

Critically here is the projectcontour annotation should upstream TLS be required. Validated your service is correct but inspecting your HTTPProxy object:

$ kubectl get httpproxy proxmox -n projectcontour                                                
NAME FQDN TLS SECRET STATUS STATUS DESCRIPTION
proxmox proxmox.mydomain.com wildcard valid Valid HTTPProxy

Given the HTTPProxy is valid, we should now be able to visit http://proxmox.mydomain.com and see a 301 redirect to the SSL endpoint, and the service being transparently reverse proxied behind the domain. Nothing quite like clean URLs for internal services and avoiding remembering IPs and ports.

--

--