2

My nginx ingress is as follows:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "gcloud-ip"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"
spec:
  backend:
    serviceName: nginx
    servicePort: 80
  rules:
  - http:
      paths:
      - path: /?(.*)
        backend:
          serviceName: client
          servicePort: 3333
      - path: /api/?(.*)
        backend:
          serviceName: hasura-svc
          servicePort: 8080

And i'm getting:

googleapi: Error 400: Invalid value for field 'resource': '{ "name": "k8s2-um-zhm30g1t-default-nginx-ymq8cimb", "hostRule": [{ "host": ["*"], "pathMatc...'. Invalid path pattern, invalid

Have looked at a lot of resources and this doesnt make sense, as the regexp is valid and annotations are correct i believe can anyone help?

Happy Machine
  • 987
  • 8
  • 30
  • Did you setup nginx ingress controller on your cluster? That error seems like GKE attempted to handle the ingress using its own ingress controller which does not support regexp. – Lukman Nov 22 '20 at 14:22
  • Hey, yes ive got nginx running, and the annotation to register the ingress with nginx – Happy Machine Nov 22 '20 at 22:35

1 Answers1

0

You are mixing annotations from 2 Ingress Controlles. GCP Ingress and Nginx Ingress.

Annotation kubernetes.io/ingress.global-static-ip-name: is GCP Ingress specific, and cannot be used with different Ingress controller like Nginx Ingress. You will not find this annotation in Nginx Ingress Annotation List.

In the same Ingress object you are using rewrite annotation which is Nginx Ingress specific.

To sum up, you are getting this error as you are using 2 annotations from 2 different controllers. Similar issue can be found here.

To resolve your issue, you have to decide which Ingress Controller you will use. Please find both options below:

GCP INGRESS

If you would like to use GCP Ingress you have to use path without rewrite feature of NGINX Ingress controller.

Instead of:

paths:
      - path: /?(.*)
      ...
      - path: /api/?(.*)

Use:

paths:
      - path: /
      ...
      - path: /api/

Your services that are exposing your apps are required to be of NodePort type. Also you will need to remove both annotations:

  • nginx.ingress.kubernetes.io/rewrite-target: /$1
  • kubernetes.io/ingress.class: "nginx"

NGINX INGRESS

As annotation kubernetes.io/ingress.global-static-ip-name is Google Cloud specific, you cannot use it with kubernetes.io/ingress.class: nginx.

If you have Static IP reserved in GCP, you should apply this IP as loadBalancerIP in Nginx Ingress Controller, not in Ingress resource.

I have already described how to deploy Nginx Ingress Controller with reserved static IP. You can find it by following below link:

Please keep in mind that answer is several months old and repo has been changed since then. For up-to-date option you should use below commands. Please remember to change <YourGlobalIP> to your ReservedIP.

$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm repo update
$ helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.service.loadBalancerIP=<YourGlobalIP>,rbac.create=true

Helm will deploy Nginx Ingress Controller with ReservedIP. Later you will need to remove kubernetes.io/ingress.global-static-ip-name annotation and deploy Ingress.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - http:
      paths:
      - path: /?(.*)
        backend:
          serviceName: first-service
          servicePort: 81
      - path: /api/?(.*)
        backend:
          serviceName: second-service
          servicePort: 82

Side Note

Please remember that reserved address must be Network Service Tier: Premium and must have Region same as your cluster. The services that traffic from nginx-ingress-controller is sent from, should be either: ClusterIP or NodePort.

I have tested this scenario with 2 hello world applications v1, v2 and IP reserved was: 35.222.174.237 on us-central1

$ kubectl get ing
NAME      HOSTS   ADDRESS          PORTS   AGE
ingress   *       35.222.174.2377   80      27s
$ curl 35.222.174.237/api/something
Hello, world!
Version: 2.0.0
Hostname: second-deployment-5b5bbb7f4-tzsd4
$ curl 35.222.174.237/test
Hello, world!
Version: 1.0.0
Hostname: first-deployment-85b75bf4f9-rtbn9
PjoterS
  • 12,841
  • 1
  • 22
  • 54