Building a micro-services application with PHP, Kubernetes and Skaffold
By: Ben Osborne
Tags: Skaffold, Kubernetes, Minikube, Laravel, PHP

Writing our Kubernetes manifest

To deploy our application as a service on Kubernetes we will need to write a Kubernetes manifest file, we will create a simple Deployment and Service as described below.

Create the following file at services/hello-world/service.yaml this file will contain both our deployment and service spec.

apiVersion: apps/v1

kind: Deployment

metadata:

name: hello-world

spec:

replicas: 2

strategy:

rollingUpdate:

maxSurge: 2

maxUnavailable: 50%

selector:

matchLabels:

app: hello-world-app

template:

metadata:

labels:

app: hello-world-app

spec:

containers:

- name: hello-world

image: hello-world

imagePullPolicy: IfNotPresent

ports:

- name: http

containerPort: 80

---

apiVersion: v1

kind: Service

metadata:

name: hello-world

spec:

type: NodePort

ports:

- name: http

targetPort: 80

selector:

app: hello-world-app

I won’t go into much detail regarding every part of the above 2 manifest specs as it is outside the remit of this guide but for my next guide I will show you how to add resource limits, horizontal pod scaling and more to Kubernetes Deployment specs.

The above is a very simple Deployment followed by a Service that forwards traffic onto port 80.

The image is called hello-world, you may be wondering why it is not a full name and version etc, this is because Skaffold will take care of injecting the image name for us when it builds each image, the name hello-world is just a reference.

Skaffold

Skaffold is a piece of software that handles building, pushing and deploying your application. Head over to https://skaffold.dev/ and download the binary.

Once installed you will need Kubectl too, head over to https://kubernetes.io/docs/tasks/tools/install-kubectl/ and following the instructions depending on your OS.

Right! Once that’s all done let’s create our Skaffold configuration file, create a new file in the root of our project at ./skaffold.yaml.

apiVersion: skaffold/v2beta7

kind: Config

metadata:

name: php-and-k8s

build:

artifacts:

- image: hello-world

context: services/hello-world

deploy:

kubectl:

manifests:

- services/hello-world/service.yaml

Great, now that’s done we are almost at the stage where we can run the cluster locally and hit our service.

Notice the image name above, hello-world this is the reference I referred to earlier in the Kubernetes deployment spec, if you change it in the deployment spec then you’ll also need to update it in skaffold.yaml.

We need one more thing to create a local cluster for testing purposes, head over to https://minikube.sigs.k8s.io/docs/start/ and install Minikube dependant on your OS.

4. Bringing up your Cluster

Sweet! You’ve have made it this far now for the big turn on ;)

Open up a terminal and start a local cluster with minikube, the following command can be used:

minikube start

It may take a minute or two to bring up the cluster, you should see an output similar to the following:

minikube v1.13.1 on Ubuntu 20.04

✨ Automatically selected the docker driver

👍 Starting control plane node minikube in cluster minikube

🔥 Creating docker container (CPUs=2, Memory=3900MB) ...

🐳 Preparing Kubernetes v1.19.2 on Docker 19.03.8 ...

🔎 Verifying Kubernetes components...

🌟 Enabled addons: default-storageclass, storage-provisioner

🏄 Done! kubectl is now configured to use "minikube" by default

Once Minikube has started you can now run the following command in a new terminal window, this will rebuild each service when your files change.

skaffold dev

You should see output similar to the below:

Listing files to watch...

- hello-world

Generating tags...

- hello-world -> hello-world:latest

Some taggers failed. Rerun with -vdebug for errors.

Checking cache...

- hello-world: Not found. Building

Found [minikube] context, using local docker daemon.

Building [hello-world]...

Skaffold will now build each of our services, in our case just the one hello-world.

Once the above has finished you should see some output from Apache, run the following command to see our pods statuses.

kubectl get pods

You should see something similar to the below output:

NAME READY STATUS RESTARTS AGE

hello-world-85fbbb7ffb-88wj5 1/1 Running 0 29s

hello-world-85fbbb7ffb-wk6gw 1/1 Running 0 29s

As you can see we have 2 pods running our hello world service, this is because we specified replicas: 2 in our Deployment spec earlier on.

Sending a request to the service

Now our service is up and running we can send a request to the service by using the kubectl port forward command, this will forward all traffic from our local host to the service running in our cluster.

Run the following command in a new terminal window, replacing hello-world-85fbbb7ffb-88wj5 with whatever one of your pods name is.

kubectl port-forward hello-world-85fbbb7ffb-88wj5 8000:80

Now you can open http://localhost:8000/ in your browser and you should be presented with:

Lumen (8.2.1) (Laravel Components ^8.0)

That’s it

You have now built and deployed successfully a Laravel Lumen application on Kubernetes using Skaffold and Minikube!

I hope you have enjoyed this guide, feel free to ask me any questions/feedback.

This guide only touches on the basic fundamentals but we can expand on this foundation and explore more into:

Adding an Ingress Controller

Adding a router such as Envoy or Traefik.

Setting up a workflow for continuous integration/continuous delivery.

You can find this complete project over at my GitHub, check out the repository https://github.com/mrbenosborne/php-laravel-k8s-skaffold.

Thanks for reading :)