Kubernetes Ingress NGINX for Laravel via fast-cgi

11/20/2020

I am using Ingress NGINX in my Kubernetes cluster: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/

Since Ingress NGINX supports Fast CGI as direct backend, I run a container with a Laravel app serving through php-fpm on port 9000. Now I tried to use Ingress NGINX as proxy with FCGI as backend, but I am not able to configure it.

According to the Laravel documentation, a nginx configuration should look like this (https://laravel.com/docs/8.x/deployment):

server {
    listen 80;
    server_name example.com;
    root /srv/example.com/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Unfortunately, it looks like not able to create the locations for / and for ~ \.php$ since Ingress NGINX does reserve the location / without any reason.

My configuration looks like this:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-fastcgi
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
    kubernetes.io/ingress.allow-http: "false"
    cert-manager.io/cluster-issuer: "letsencrypt-production"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "FCGI"
    nginx.ingress.kubernetes.io/fastcgi-index: "index.php"
spec:
  tls:
    - hosts:
        - api.abcxyz.cloud
      secretName: api-cert-secret
  rules:
    - host: api.abcxyz.cloud
      http:
        paths:
          - path: /
            backend:
              serviceName: laravel
              servicePort: 9000

How can I handle the requirements coming from Laravel with Ingress NGINX and FCGI?

-- floflock
kubernetes
kubernetes-ingress
nginx
nginx-ingress
php

2 Answers

9/15/2021

No, you cannot map a service to port 9000 as port 9000 is in php-fpm fast cgi, which is not a webservice. To make it work, you need to set the script_filename, so that kubernetes understand which script to run through php-fpm. Ref: https://kubernetes.github.io/ingress-nginx/user-guide/fcgi-services/

In case you just need to run only one backend that is what you need. However, if you are trying to map multiple path, one with php-fpm and other with normal http mode, that is not support. Because kubernetes ingress in fastcgi mode will run for all it's path.

-- Roy Anon
Source: StackOverflow

2/21/2021

I think the listening port of your nginx configuration should be 9000.

My guess, what you have is:

  • a container with PHP app served by Nginx at port 9000.
  • a ClusterIP service at service port 80, mapped to you port 9000 container port.
  • then you are trying expose your service to outside world using ingress

So you need the following k8 declarations

  • Deployment/Statefulset - to create your container.
  • Service - to map your service port 80 to container port 9000
  • Ingress - to expose your service to outside work at port 80

here is an example (although I use ambassador ingress.class for minikube but the principle is the same) https://github.com/francisfueconcillo/k8-geektalk/blob/master/wp-deployment.yaml

-- user1046762
Source: StackOverflow