This article assumes you have a basic understanding of Docker and Kubernetes, Gitlab CI and that you have already set up a Kubernetes Cluster.
Start a Laravel Project
The first thing you’ll need is a Laravel application, use composer to start a new project.
composer create-project --prefer-dist laravel/laravel blog
Dockerize your Laravel Project
There’s a number of ways to dockerize your Laravel project. You may use the official Nginx and PHP images form dockerhub, but I found it’s a bit troublesome to set them up.
To build a production-ready image, we will use
thecodingmachine/php:7.3-v2-slim-apache as our base image. The Dockerfile looks like this:
We will configure Gitlab CI to build the docker image automatically later.
Create Kubernetes Deployment Files
Here are all the yaml files we need to deploy our Laravel Application.
Out deployment.yaml contains two deployments actually. One is for our main Laravel application, while the other one is for Laravel Horizon. If you do not plan to use Horizon, you can simply remove it.
There’s an init container to optimize configuration and route loading. To share the application code between init container and app container, it uses an emptyDir.
There’s also affinity setting to tell Kubernetes to try it best to schedule the pods among different nodes as to avoid downtime.
We use cronjob.yaml that leverage Kubernete’s CronJob to run
php artisan schedule:run every minute. We feel like this is a more robust way of scheduling cron by fine-tuning
startingDeadlingSeconds to make sure our cron gets scheduled.
ConfigMap, Ingress & Service
Our ingress.yaml and service.yaml is pretty standard, we use CloudFlare DNS verification to obtain HTTPS certificates from Let’s Encrypt (It’s commented).
As for configmap, it’s recommended to use secret to store sensitive information like the database password.
Here’s a GitHub Repo in case you would like to clone it. Merge request is also appreciated!
Contribute to mkhmylife/laravel-k8s development by creating an account on GitHub.github.com
Set up Gitlab CI
Now that we have our app and kubernetes config ready, we can go ahead to setup Gitlab CI to automate our deployment. (We assume you are using Kubernetes token authentication)
Setup CI/CD Environment Variables
Within Repo > Settings > CI / CD, we need to store our Kubernetes Cluster credentials into Gitlab CI’s environment variables.
Dockerfile to your project’s root directory, then create a folder called
k8 and store all the kubernetes yaml files inside. Create a file called
.gitlab-ci.yml that contains the folllowing.
The CI/CD script contains two steps. First is to build our Laravel Application and push to Amazon ECR (you may configure it to another Docker Image Repo as you like). Then it moves on to deploy our Laravel Application image to our Kubernetes cluster.
In line 36 and 37, the
$KUBE_TOKEN are the two environment variables that we set up above.
In line 40, we ask kubectl to apply our k8s configuration files.
In line 41, it a hack to trigger redeployment of pods. Since we have set the
always, Kubernetes will automatically re-pull our docker image to the latest version. Combine with our deployment’s rolling update strategy, there’s should be no downtime in deployment updates.
In production, we actually use Kustomize to maintain deployment of multiple Git branches and environment. But we are looking to switch to Helm as it seems to be an easier and more popular deployment method.