1

I have the following kubernetes ingress configuration (nginx ingress controller) which works fine.

kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
  name: test01-api-ingress
  namespace: test01
spec:
  rules:
  - host: www.example.com
    http:
      paths:
      - backend:
          serviceName: test01-new-api-1
          servicePort: 80
        path: /test01/api1
      - backend:
          serviceName: test01-new-api-2
          servicePort: 80
        path: /test01/api2

The above creates the following configuration (mostly omitted)

                location ~* "^/test01/api2\/?(?<baseuri>.*)" {

                        set $namespace      "test01";
                        set $ingress_name   "test01-api-ingress";
                        set $service_name   "test01-new-api-2";
                        set $service_port   "80";
                        set $location_path  "/test01/api2";

                        rewrite "(?i)/test01/api2/(.*)" /$1 break;
                        rewrite "(?i)/test01/api2$" / break;
                        proxy_pass http://upstream_balancer;

                        proxy_redirect                          off;

                }

                location ~* "^/test01/api1\/?(?<baseuri>.*)" {

                        set $namespace      "test01";
                        set $ingress_name   "test01-api-ingress";
                        set $service_name   "test01-new-api-1";
                        set $service_port   "80";
                        set $location_path  "/test01/api1";

                        rewrite "(?i)/test01/api1/(.*)" /$1 break;
                        rewrite "(?i)/test01/api1$" / break;
                        proxy_pass http://upstream_balancer;

                        proxy_redirect                          off;

                }

For the upgrade of the nginx ingress controller, the following configuration should change (somehow). But when I apply it the ingress configuration:

kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite "(?i)/test01/api1/(.*)" /$1 break;
      rewrite "(?i)/test01/api1$" / break;
      rewrite "(?i)/test01/ap21/(.*)" /$1 break;
      rewrite "(?i)/test01/ap21$" / break;
  name: test01-api-ingress
  namespace: test01
spec:
  rules:
  - host: www.example.com
    http:
      paths:
      - backend:
          serviceName: test01-new-api-1
          servicePort: 80
        path: /test01/api1
      - backend:
          serviceName: test01-new-api-2
          servicePort: 80
        path: /test01/api2

I get the following, which doesn't work properly, because it adds api1/api2 at both locations.

                location ~* "^/test01/api2" {

                        set $namespace      "test01";
                        set $ingress_name   "test01-api-ingress";
                        set $service_name   "test01-new-api-2";
                        set $service_port   "80";
                        set $location_path  "/test01/api2";

                        rewrite "(?i)/test01/api1/(.*)" /$1 break;
                        rewrite "(?i)/test01/api1$" / break;
                        rewrite "(?i)/test01/ap21/(.*)" /$1 break;
                        rewrite "(?i)/test01/ap21$" / break;

                        proxy_pass http://upstream_balancer;

                        proxy_redirect                          off;

                }

                location ~* "^/test01/api1" {

                        set $namespace      "test01";
                        set $ingress_name   "test01-api-ingress";
                        set $service_name   "test01-new-api-1";
                        set $service_port   "80";
                        set $location_path  "/test01/api1";

                        rewrite "(?i)/test01/api1/(.*)" /$1 break;
                        rewrite "(?i)/test01/api1$" / break;
                        rewrite "(?i)/test01/ap21/(.*)" /$1 break;
                        rewrite "(?i)/test01/ap21$" / break;

                        proxy_pass http://upstream_balancer;

                        proxy_redirect                          off;

                }                

Any ideas of how will the configuration should be? How can I split it into the relevant locations? thank you.

user515576
  • 65
  • 6
  • Hello. To have your `configuration-snippets` in specific locations you can split the `Ingress` resources based on `annotations` used. I will follow-up with an answer on how this could be achieved. – Dawid Kruk Jan 06 '21 at 10:44

1 Answers1

0

TL;DR

I'd reckon the post ask the following question:

How can I set certain annotations like configuration-snippet per path.

This specific setup could be resolved in either way:

  • By splitting the Ingress resources per Annotations used.
  • By configuring Ingress resource that would route accordingly on both paths.

Splitting the Ingress resource:

You can split your Ingress resource on multiple objects (which will work together).

Annotations can only be set on the whole kubernetes resource, as they are part of the resource metadata. The ingress spec doesn't include that functionality at a lower level.

-- Stackoverflow.com: Questions: Apply nginx-ingress annotations at path level

Extending on the answer to give an example of how such setup could be created:

  • ingress-01.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite "(?i)/test01/api1/(.*)" /$1 break;
      rewrite "(?i)/test01/api1$" / break;
  name: test01-api-ingress-01
spec:
  rules:
  - host: example.com 
    http:
      paths:
      - path: /test01/api1
        backend:
          serviceName: test01-new-api-1
          servicePort: 80
  • ingress-02.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite "(?i)/test01/api21/(.*)" /$1 break;
      rewrite "(?i)/test01/api21$" / break;
  name: test01-api-ingress-02
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /test01/api2
        backend:
          serviceName: test01-new-api-2
          servicePort: 80

Some side notes!

Check if you have a potential misstype in your snippet:

  • rewrite "(?i)/test01/ap21/(.*)" /$1 break; <-- ap21 instead of api21
  • rewrite "(?i)/test01/ap21$" / break; <-- ap21 instead of api21

After applying above resources you will have 2 Ingress resources:

  • $ kubectl get ingress
NAME                    CLASS    HOSTS                        ADDRESS     PORTS   AGE
test01-api-ingress-01   <none>   example.com                  localhost   80      42s
test01-api-ingress-02   <none>   example.com                  localhost   80      42s

Configuring Ingress resource that would route accordingly on both paths.

As said you can use following example to set the routing scheme for your paths:

The example of such setup would be following:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test01-api-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: test01-new-api-1
          servicePort: 80
        path: /test01/api1(/|$)(.*)
      - backend:
          serviceName: test01-new-api-2
          servicePort: 80
        path: /test01/api2(/|$)(.*)

I highly encourage you to check the official documentation about path matching:

Additional resources:

Dawid Kruk
  • 8,982
  • 2
  • 22
  • 45
  • @Dawid Kruk why do I have to use the ```kubernetes.io/ingress.class: "nginx"``` ? is this complatible with Kubernetes 1.13.4 ? – user515576 Jan 08 '21 at 09:56
  • @user515576 I rewrote this paragraph. I included this annotation in case there were multiple `Ingress` controllers in your setup. Here you can read more about it: https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/. Please consider if it's possible to upgrade your `Kubernetes` cluster as it's 7 major versions behind the latest (1.20). – Dawid Kruk Jan 08 '21 at 10:36
  • @Dawid Kruk the one ingress with two paths configuration worked fine, but when I updated the Ingress controller from 0.20.0 to 0.30.0, this configuration broke the controller functionality. Is there any other configuration that I can try? – user515576 Jan 08 '21 at 19:02
  • You may want to check the changes happened from 0.20.0 to 0.30.0 and beyond. https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md There are some more changes in ingress syntax in recent versions. Ingress concept page tells more about it: https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types – VAS Jan 13 '21 at 11:00