Performance tuning for PHP has always been a problem for every infrastructure engineers. How do you make the application load faster? How do you make the latency lower?
I had my fair share of deploying PHP applications since I first started coming in contact with Wordpress (a blogging software) and Laravel (a PHP framework) back in 2011. Back then, dockers didn't exist yet and Public Clouds were not popular back then, we had to deploy the PHP application in virtual machines or dedicated servers. It was easy setting up Apache and Mod_PHP to setup our PHP applications. Our only option to scale our application is to clone the virtual machines or dedicated servers and load balance between the applications.. (that sucks right?)
Fast forward 10 years ahead to where we are right now in time, we have an abundance of Public Clouds, technologies available to allow us to scale freely and as automated as possible. I shall not elaborate on Kubernetes and containers as that is not the focus of this post.
Now, how can we design highly scalable PHP applications in Kubernetes?
First, we have to understand how PHP requests work starting from the user's request to https://example.alexlogy.io/index.php and how it traverse through the servers.
If you refer to the diagram above, you will realise every single request for a PHP file have around 6 steps to complete (without accounting for any database or other connections such as redis/kafka/etc).
Let's break down the important factors before we dive into designing the architecture for Kubernetes.
- Web Server and PHP-FPM must have the same data store to find the PHP file requested. Thus, we will need to have a Persistent Volume (PV) to store our PHP files.
- The Web Server behaves like a proxy server sending request to PHP-FPM and transferring the response from PHP-FPM to the user. Thus, the processing load is definitely going to be heavier on the PHP-FPM process.
- Since PHP is an interpreted language like Python, it's definitely going to be slower than compiled languages like C++, Golang, C#, etc. Do we need to reduce the load on PHP-FPM?
With the above points, I can design the architecture in the below illustration:
As such, we can setup the containers this way:
- Varnish Deployments with HPA. Varnish will be used primary as a caching layer to minimise the requests going to PHP-FPM unless necessary to speed up the overall request latencies
- NGINX Deployments with HPA as fastcgi_pass to PHP-FPM service URL and Port
- PHP-FPM Deployments with HPA
- PV with Read-write Many (RWM) access mode such as AWS EFS
To complete the setup, we can setup the CI/CD process with the following method:
- CI/CD tool to trigger Kubernetes Job to rsync PHP files after pulling from Git and completing any preparation commands (for eg. artisan commands for Laravel framework). We don't even have to restart the containers above as each request will look for the PHP file in the PV.
With the above design, you can have a highly scalable architecture design for PHP applications in Kubernetes as each deployment will have HPA to scale as necessary.