Search code examples
kubernetes-ingress

Kubernetes ingress rewrite


I'm currently porting a PHP monolith into Kubernetes, and I'm having some trouble with the URL rewriting in nginx-ingress.

The system uses phroute and that's working all fine. The problem is setting up the nginx ingress to play nice.

The old system had the following rewrite rules:

try_files $uri $uri/ @rewrite;

location @rewrite {
  rewrite ^/(.*)$ /index.php?_url=/$1;
}

location / {
  try_files $uri $uri/ =404;
}

location ~ \.php$ {
  try_files $uri =404;
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  fastcgi_pass 1.2.3.4:9000;
  fastcgi_index index.php;
  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  fastcgi_param PATH_INFO $fastcgi_path_info;
}

location ~* \.(js|css|png|jpg|jpeg|gif|svg)$ {
  expires max;
  log_not_found off;
  rewrite "/[a-z0-9]{40}/([^.]+)\.(js|css|png|jpg|jpeg|gif|svg)$" /assets/$1.$2;
}

I've tried the following annotations for my nginx ingress:

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /index.php?_url=/$1
  hosts:
    - site.kube
  paths: [
    /(.*),
    /[a-z0-9]{40}/([^.]+)\.(js|css|png|jpg|jpeg|gif|svg)$
  ]

The below are my questions:

  • phroute doesn't use the $_GET['_url'] parameter, but rather $_SERVER['REQUEST_URI']. How do I set it? If I set the rewrite-target to /$1, the routes work, but:

  • How do I implement the path for the assets?

Please tell me if I can provide any more information. Thanks.


Edit

In response to questions in comments, here's some version output.

Kubernetes (latest Minikube, at the time of writing):

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.3", GitCommit:"b3cbbae08ec52a7fc73d334838e18d17e8512749", GitTreeState:"clean", BuildDate:"2019-11-14T04:24:29Z", GoVersion:"go1.12.13", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:09:08Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}

nginx-ingress (built in to minikube):

$ kubectl describe pod nginx-ingress-controller-6fc5bcc8c9-qnmz2 -n kube-system
{
    [ ... ]
    Image:         quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1,
    [ ... ]
}


Solution

  • I found the solution!

    The reason was that the root server { ... }-block's try_files isn't handled. This has to do with the following line being required to properly propagate the request from the nginx ingress to the nginx pod in my deployment, this line is required as an ingress annotation:

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

    To get it to work, all I did was the following:

    1. In my config map for the nginx config, I removed the try_files from the server { ... }-block.

    2. In the location / { ... }-block, I changed the try_files from:

      try_files $uri $uri/ =404;
      

      to:

      try_files $uri $uri/ @rewrite;
      

    This solved the problem, because the rewrite-target made all requests incoming to nginx end up in the location / { ... }-block and thus bypass the server's try_files.