I found it rather tricky to set up a Traefik TCP ingress for connecting directly to a PostgreSQL server running inside Kubernetes. There are a few moving parts, and they all need to be right for the ingress to work, but most resources I found on the internet left out one (or more), so here they all are in one place. While I’ve only tried this with PostgreSQL, it’s likely that other database ingresses will work the same way.
Two additions are needed:
entryPoint
for the port that PostgreSQL listens on so that it will route traffic entering on that portadditionalArguments:
- "--entryPoints.postgresql.address=:5432/tcp"
ports:
postgresql:
expose: true
port: 5432
exposedPort: 5432
protocol: TCP
On k3s, Traefik is installed in the kube-system
namespace via Helm, so if you use Helm to modify the values above, make sure you use the same namespace. I didn’t want to risk changing whatever values Rancher had used by default, so I specified the full set:
rbac:
enabled: true
ports:
websecure:
tls:
enabled: true
podAnnotations:
prometheus.io/port: "8082"
prometheus.io/scrape: "true"
providers:
kubernetesIngress:
publishedService:
enabled: true
priorityClassName: "system-cluster-critical"
image:
name: "rancher/mirrored-library-traefik"
tag: "2.6.2"
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
service:
ipFamilyPolicy: "PreferDualStack"
I used Terraform to install the Helm release, but if you use the CLI, run:
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm upgrade --install traefik traefik/traefik \
-n kube-system -f values.yaml
HostSNI
needs to match *
, apparently most database protocols - and especially PostgreSQL - don’t support SNI over TLS. Additionally, TLS needs to be disabled since the protocol used by the client and server use their own TLS, so Ingress doesn’t need to handle or terminate it. That’s why there needs to be no tls
section in the spec.namespace
needs to be the same as the one in which you installed PostgreSQL and its service.apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: postgresql-ingress
namespace: postgresql
spec:
entryPoints:
- postgresql
routes:
match: HostSNI(`*`)
services:
- name: postgresql
port: 5432
With both sets of changes, you should be able to connect to the PostgreSQL instance on port 5432 of your control node’s IP, or any hostname that resolves to that IP. If you want to run other databases and expose them on the same host, they’ll need to listen on a different port.