'kubernetes nginx ingress http-snippet annotation not taking effect

I am using a regex to extract only the IP from $http_x_origin_forwarded_for, because it comes together with the port, and I only need the IP for my header. So I am using the ingress like this.

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/backend-protocol: https
    nginx.ingress.kubernetes.io/http-snippet: |
      map $http_x_origin_forwarded_for $forwarded-for-ip {
       ~^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+):[0-9]+ $1;
       default '';
      };

    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header X-Forwarded-For $http_x_forwarded_for;

And the output on the server-side is

Header 'x-forwarded-for' = IP:PORT

And with based on it, my spring boot application returns this error:

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Aug 13 06:55:21 UTC 2021
There was an unexpected error (type=Internal Server Error, status=500).
Failed to parse address IP: PORT

I also tried like this

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/backend-protocol: https
    nginx.ingress.kubernetes.io/configuration-snippet: |
      map $http_x_forwarded_for $real_ip {
        ~^(\d+\.\d+\.\d+\.\d+) $1;
        default $remote_addr;
      }
      proxy_set_header X-Forwarded-For $real_ip;

But I got this error

2021/08/14 11:58:54 [emerg] 19862#19862: "map" directive is not allowed here in /tmp/nginx-cfg920601764:940
nginx: [emerg] "map" directive is not allowed here in /tmp/nginx-cfg920601764:940
nginx: configuration file /tmp/nginx-cfg920601764 test failed


Solution 1:[1]

Depending on your k8s version, after Ingress came out from beta(apiVersion: networking.k8s.io/v1v1beta1 -> apiVersion: networking.k8s.io/v1)

It is possible to achieve what you want by configuring the configmaps. With v1; ingresses use another namespace in this case it is called ingress-nginx.

Add the following configmaps:

apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
data:
  proxy-set-headers: "ingress-nginx/custom-headers"
  http-snippet: |
    map $http_x_forwarded_for $real_ip {
        ~^(\d+\.\d+\.\d+\.\d+) $1;
        default $remote_addr;
      }
--
apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-headers
  namespace: ingress-nginx
data:
  X-Forwarded-For: ${updated_x_trace_id}

Then all of the ingress-nginx controllers will get effected by this change

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Berk