Deploy a laravel project to kubernetes at scale
laravel is popular and known for rapid development but deploying php frameworks and scale them in kubernetes is a little bit tricky.
Since HTTP driven applications are stateless, sessions provide a way to store information about the user across requests, for example when you get login in a laravel website your session data is caching in files by default and when you have 3 laravel backend for example 3 replica in kubernetes when you request another webpage you may login or not because your session is not shared among pods.
For solving session problem we have two ways :
- using sticky session in loadbalancer
- sharing sessions among pods
Fortunately, nginx ingress support sticky sessions you can simply add this annotation in your ingress
One of the problems of this method is the opposite of using round-robin user always use the first pod she or he connected.
Sharing sessions among pods another way that I prefer. you can change default session driver and using Redis driver for caching sessions.
Laravel logs and coordinating them is important when you have multi-instance in this post I completely explained how it can happen in kubernetes.
but in summary you have multiple options:
- using sentry as a bug reporter
- coordinate logs with EFK or ELK stack
- using laravel logs drivers and send directly log messages to fluentd or elasticsearch
Most of laravel developers prefer using the default storage path
storage/app/public so persisting this data is important.
Kubernetes for persisting data have many options you can choose.
Small business uses php or MariaDB in default but scaling php application tragically depends on your resources and configurations. this articles and tools about performance tuning MariaDB and php help you.
MySQLTuner is a script written in Perl that will assist you with your MySQL configuration and make recommendations for…
Optimizing PHP-FPM for High Performance
PHP is everywhere and is arguably the language most widely deployed on the Internet Web. However, it's not exactly…
Make your Laravel App Fly with PHP OPcache
Easy guide to enable and optimize OPcache for a faster application
Finally deploying the project to kubernetes
Before deploying the application to k8s you need to ensure that application is worked so for you the better option is using docker-compose for Development and Kubernetes for Production.
In this GitHub repository, I will put all docker-compose and BaseImage and Kubernetes templates that need for deploying laravel to k8s.
Example Project For Deploying Laravel Application To Kubernetes - behroozam/Laravel-kubernetes-example
First of all, we have to create a proper multi-stage Dockerfile and BaseImage.
Docker introduces multi-stage build in 17.05 version, using laravel cache layers and change the only app layer help reduce the image size, for me 1GB to 200MB 😲.
This is a BaseImage and a script for fixing project permissions.
Dockerfile for production depending on using nodejs modules or not.
I will assume you are familiar with kubernetes and architecture.
This is what we want to do
By default, Laravel using MySQL as Database but I will prefer using MariaDB.
Before deploying MariaDB we need to create password Secret, I prefer imperative or command line mode for creating Secrets but in complicated scenarios, we have to use Declarative YAML files.
The first step is to create namespace:
kubectl create namespace laravel
The second step is to create a secret password
kubectl -n laravel create secret generic laravel-mariadb-pass --from-literal=password=laravel
The third step is to labeling node as in this tutorial I am using host path persistent storage
kubectl get nodes
kubectl label nodes <your-node-name> database=true
And finally, apply
kubectl apply -f Laravel-kubernetes-example/Kubernetes/DataBase/MariaDB.yaml
Laravel application deployment
after create, tag and push your image to registry its time to deploy the project
As you saw in the image above we most create configmaps and persistent storage.
kubectl apply -f Laravel-kubernetes-example/Kubernetes/configmaps.yamlkubectl apply -f Laravel-kubernetes-example/Kubernetes/Storage.yaml
Note that I am using NFS as the persistent volume you can change it depending on your need.
applying services and deployment and ingress are in the last step complete your journey to create a kubernetes laravel project
kubectl apply -f Laravel-kubernetes-example/Kubernetes/Application-Deployment.yamlkubectl apply -f Laravel-kubernetes-example/Kubernetes/Service.yamlkubectl apply -f Laravel-kubernetes-example/Kubernetes/ingress.yaml