Outline: How To Install Development Setup

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

Outline

- Why

- How to install development setup


- - Install docker

- - Install minikube

- - Install kubectl

- Using Kubernetes and docker


- - Use docker to build your own container

- - Run and access a basic container

- - - Pushing containers to Minikube’s docker registry

- - - Using container from local registry

- How to run a Laravel application


- - Php-fpm container

- - Nginx container

- Into Production

- Optional Services
- - Mysql

- - Redis

- - Horizon

- - Cron worker

- Going Live
- SSL

- Deployment strategies

Why use Kubernetes


A large scale Laravel application needs a few di erent services to operate
properly. Kubernetes allows us to horizontally scale each of the services.
We can achieve massive scale without any code changes while
maintaining full control over our infrastructure.

Your infrastructure is stored in code allowing it to be easily upgraded or


recreated.

1 of 22
ff
Getting Started
We’ll start out by learning how to run a miniature cluster on our own
computer. Then we’ll move to a production setup using a cloud provider.

First you’ll need to install docker for working with containers. Docker
includes a container runtime and tools to build containers. Head over to
https://www.docker.com and install the latest stable version.

Next, install Minikube. Minikube is a development focused Kubernetes


cluster that you can run locally. It’s not production ready but it’s perfect for
learning and testing. Available here: https://minikube.sigs.k8s.io. After
installing, start it with ‘minikube start --vm=true’

And nally install kubectl. Kubectl is a command line tool that allows you
to interact with a Kubernetes cluster. You’ll use it in production and
development. A cluster and the authentication details needed to access it
are collectively known as a context.

After installing kubectl, try running ‘kubectl con g get-contexts’. You should
see your minikube cluster.

Building a basic container


I prepared a very basic nginx docker image available here: GitHub.

The 3 les are Docker le, nginx.conf, and index.html.

Docker le contains the instructions to build the image.

The nginx.conf has a basic con guration to serve the index.html le and
the index.html is the content that will be displayed.

2 of 22
fi
fi
fi
fi
fi
fi
fi
cd into the directory and run the command ‘docker build . --tag=basic-nginx’.

Next run ‘docker run -p 8787:80 basic-nginx’ to start the container. Direct your
browser to http://localhost:8787 to see the output of index.html.

We’ve successfully built and run a container in docker, next we’ll run it on
Kubernetes.

Running the container in Kubernetes


Now to run the container in Kubernetes, we’ll start to touch the surface of
infrastructure as code

We need to create a deployment le which instructs Kubernetes on how to


run our application.

— — insert basic_deployment.yaml here —

The important parts are the image name which needs to match the tag we
gave in docker build, the imagePullPolicy, and the selector’s matchLabels
which will be used for networking later.

ImagePullPolicy ‘Never’ tells Kubernetes that the image exists locally, i.e.
not on docker hub.

Run ‘kubectl apply -f basic_deployment.yaml’ to create the deployment.

You should see a message that the deployment was created.

3 of 22
.

fi

Start the Minikube dashboard by running ‘minikube dashboard’. That will


open your browser to the Kubernetes dashboard.

Everything is red, this doesn’t look good. Click one of the small red dots to
reveal the message about what went wrong.

Failed to pull image "nginx-basic": rpc error: code = Unknown desc = Error
response from daemon: pull access denied for nginx-basic, repository
does not exist or may require 'docker login': denied: requested access to
the resource is denied

This message is a little deceptive, access wasn’t actually denied, the


image doesn’t exist in Minikube’s docker repository. That’s right, we’re
running docker inside of docker.

So how do we get our image in there? We have to switch our command


line’s environment to access the Minikube docker. Run ‘minikube docker-
env’ then run ‘eval $(minikube -p minikube docker-env)’.

4 of 22
Now we can build our image with ‘docker build . --tag=basic-nginx’. Since
we’ve switched docker environments, now it’ll be available to Kubernetes.

Delete the old deployment then run the same deploy command again. We
should have all green lights in the Kubernetes dashboard now.

Accessing the container


Our container is running but we need to create a service and an ingress to
be able to access it. We’re building from the ground up, so we’ll start with
services.

Service

A service is how we expose a set of pods to the network.

—— insert nginx_service.yaml —

The service knows where to route by matching its selector to the


deployment’s matchLabels.

In this example, the port routes tra c internally to the same port it
exposes externally. Di erent routing con gurations are possible but this is
all we’ll need.

Deploy the service by running ‘kubectl apply -f nginx_service.yaml’.

Ingress

An ingress is how tra c gets from the outside world into the Kubernetes
cluster.

First we need to enable an ingress controller. Cloud services have their


own controllers but in development we’ll use a simple nginx ingress
controller.

Install it by running ‘minikube addon enable ingress’.

5 of 22
ffi
ff

ffi
fi
Now we can create the ingress resource.

—— insert ingress.yaml —

The rules match the request so di erent requests can be routed to


di erent services. We’re matching all requests pre xed with "/" and routing
them to our service named ‘nginx’.

Deploy the ingress by running ‘kubectl apply -f ingress.yaml’.

Now we have to wait until our ingress is ready with an endpoint ip address.
It can take a couple of minutes. Run ‘kubectl get ingress’ and when an
address is shown, navigate to that ip to view the output from the container.

It can take over a minute for the address to be lled. If it doesn’t come up,
something else is wrong. Join the discord group and let’s gure it out!

You can delete deployment we created here. We’ll be creating a new one
that can handle php. The service and ingress can be reused.

Running Laravel
We’ve used Nginx to serve a static asset, now let’s use it to serve a php-
fpm container.

Starting from the ground up, rst we’ll create the php-fpm container then
we’ll con gure Nginx to serve static assets and direct php requests to the
php-fpm container.

Building Laravel

First create a new Laravel application and in the root of that directory,
create a le called Docker le.

6 of 22
ff
fi
fi

fi
fi
ff
fi
fi
fi
—— Docker le ——

Make sure your docker environment is set to Minikube as before then run
‘docker build . --tag=laravel-php’ from the directory with the new Docker le.

Deploying Laravel

Nginx also needs access to the static assets from our Laravel application.
We’ll create a shared volume that’s accessible to Nginx and php. On
deployment, our Laravel php container will copy the static assets to the
shared volume.

First we create the persistent volume claim.

—— basic/laravel/storage.yaml ——

Deploy by running ‘kubectl apply -f storage.yaml’.

The volume exists in the Minikube virtual machine. You can access it by
running ‘minikube ssh’ then cd to ‘/tmp/hostpath-provisioner/default’.

Next include the shared volume into the deployment.

—— php_deployment.yaml ——

Deploy by running ‘kubectl apply -f php_deployment.yaml’.

We use a lifecycle command to copy the laravel application to the shared


volume. Nginx will serve from the shared volume.

This strategy isn’t perfect because each time a pod is created, it copies
the contents to the shared directory. This can cause unexpected
downtime. Shared volumes are also problematic when using multiple
nodes. We’ll solve that when we get into the production environment.

7 of 22
fi

fi
Accessing Laravel

If you tried to access through the ingress’s endpoint, you will receive a 503
error. We still can’t access our application because php-fpm doesn’t know
how to handle HTTP requests. For that we need an Nginx reverse proxy.

In our basic Nginx setup earlier, we used docker to build an image of


Nginx with the con guration le added. This time we’ll add the con g le
in using Kubernetes. That allows us to more easily manage the
con guration.

—— nginx_con gmap.yaml ——

Pay attention to ‘fastcgi_pass php:9000;’. ‘php’ references a named network


location which we will create with a service. Data is passed to it using port
9000.

Deploy by running ‘kubectl apply -f nginx_con gmap.yaml’ and let’s keep


going.

—— php_service.yaml ——

We create a service named ‘php’ which is referenced in the Nginx con g


above and open port 9000.

Deploy by running ‘kubectl apply -f php_service.yaml’.

The last thing we need to do is create the Nginx deployment with the
con guration le and the shared volume.

—— nginx_deployment.yaml ——

Deploy by running ‘kubectl apply -f nginx_deployment.yaml’.

Browse to the address given by the ingress and you should see the
Laravel start page. That’s it for a very basic setup. Next we’ll dig into a fully
edged production setup covering Redis, MySQL, Horizon, and Laravel’s
scheduler. We’ll run CI/CD using Github Actions and a zero downtime
deployment script.

8 of 22
fl
fi
fi
fi
fi
fi
fi
fi
fi
fi
fi

You might also like