Deploy a laravel project to kubernetes at scale

Behrouz hasanbeygi
4 min readMay 10, 2019

--

https://learnk8s.io/blog/kubernetes-deploy-laravel-the-easy-way/

laravel is popular and known for rapid development but deploying php frameworks and scale them in kubernetes is a little bit tricky.

Sessions

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‍‍‍‍‍

    nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"

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.

Logs

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

Persistent storage

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.

Other things

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.

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.

Dockerfile

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.

Application architecture

I will assume you are familiar with kubernetes and architecture.

This is what we want to do

Deploying Laravel application to K8S workflow

MariaDB Template

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 Kubernetes/DataBase/MariaDB.yaml file

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.

so applying

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

--

--