Search code examples
nginxkuberneteskubernetes-helmkubernetes-ingressnginx-ingress

kubernetes nginx ingress error with configuration-snippet


I have following ingress.yaml file

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
    name: nginx-configuration-snippet
    annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
        nginx.ingress.kubernetes.io/configuration-snippet: |
          location /base/path/v1/api/update {
              deny all;
              return 404;
            }
spec:
  rules:
    - http:
        paths:
          - path: /base/path(/|$)(.*)
            backend:
              serviceName: myApi
              servicePort: 8080

But when I send a request to https:///base/path/v1/api/update it succeeds and I got following error in nginx ingress controller

Error: exit status 1
2020/08/06 18:35:07 [emerg] 1734#1734: location "/base/path/v1/api/update" is outside location "^/base/path(/|$)(.*)" in /tmp/nginx-cfg008325631:2445
nginx: [emerg] location "/base/path/v1/api/update" is outside location "^/base/path(/|$)(.*)" in /tmp/nginx-cfg008325631:2445
nginx: configuration file /tmp/nginx-cfg008325631 test failed

Can somebody help?


Solution

  • The configuration-snippet is to add configs to locations.

    If you want to add a custom location to the server context, you should use the server-snippet instead:

    Using the annotation nginx.ingress.kubernetes.io/server-snippet it is possible to add custom configuration in the server configuration block.

    You also need to use some modifiers and regex to make it work (~* and ^).

    The following config should work:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
        name: nginx-configuration-snippet
        annotations:
            nginx.ingress.kubernetes.io/rewrite-target: /$2
            nginx.ingress.kubernetes.io/server-snippet: |
              location ~* "^/base/path/v1/api/update" {
                  deny all;
                  return 403;
                }
    spec:
      rules:
        - http:
            paths:
              - path: /base/path(/|$)(.*)
                backend:
                  serviceName: myApi
                  servicePort: 8080
    

    The final nginx.config should end like this:

    $ kubectl exec -n kube-system nginx-ingress-controller-6fc5bcc8c9-chkxf -- cat /etc/nginx/nginx.conf
    
    [...]
    
    location ~* "^/base/path/v1/api/update" {
                deny all;
                return 403;
            }
            
    location ~* "^/base/path(/|$)(.*)" {
    [...]           
    }