I use Ingress-nginx and I need to rewrite the Host
header sent to the proxied Kubernetes Service based on the path
of the original request. This must happen based on some variable or regular expression. I cannot hard code paths because this needs to work for any path automatically.
Basically I need something like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: my-ns
annotations:
# below what's commented out almost works but adds a leading "/" to header
# nginx.ingress.kubernetes.io/upstream-vhost: $request_uri.example.com
nginx.ingress.kubernetes.io/upstream-vhost: $PATH.example.com
spec:
ingressClassName: nginx
rules:
- host: 'example.com'
http:
paths:
- backend:
service:
name: my-svc
port:
number: 80
path: /$PATH
pathType: Prefix
I wonder if this is somehow possible to implement with annotation nginx.ingress.kubernetes.io/configuration-snippet
or nginx.ingress.kubernetes.io/server-snippet
but I don’t understand these annotations well enough. I’ve tried out these annotations by passing in a location
and also attempted to use map
module with no luck so far.
Context: This reverse proxy is set up in front of Knative and Knative’s routing works through Host
header.
2
Answers
Generally, setting the
Host
header depending on thepath
can be achieved like this:So we need
nginx.ingress.kubernetes.io/server-snippet
and also it must be addedproxy_http_version 1.1;
, otherwise it won't work.Note that apparently
server-snippet
overrules what is defined asservice
in the specs - the value ofbackend.service.name
is ignored. So be careful when usingserver-snippet
annotation as it may break the Ingress configuration is some way.Then… considering NGINX Ingress annotation snippets contain LUA code execution (which can be a security issue, by the way), you might consider using Lua through a custom Lua plugin.
A simple Lua script would be enough to capture the first segment of the request path and sets it as the
Host
header suffixed with.example.com
.Create a
dynamic-host-header/main.lua
: (inspired from the official example)Before building a custom
ingress-nginx
image, you can start with testing that plugin into theingress-nginx
pod:Create a ConfigMap with the content of your plugin:
And modify the
ingress-nginx
deployment to mount this ConfigMap to/etc/nginx/lua/plugins/dynamic-host-header
(as mentioned in the "installing plugin" section):Add the volume and
volumeMounts
as follows:Now, you need to enable the plugin by updating the
nginx-ingress-controller
‘s ConfigMap:Edit the ConfigMap:
Add (or update) the
plugins
configuration setting:Finally, restart the ingress-nginx pods to pick up the changes:
With this Lua plugin enabled, the
Host
header should be dynamically set based on the request path, as required.