Back to top
3 minute read

Running our website on kubernetes using our PHP container

How we run our website here at ngineered

At ngineered we believe in running our own systems in the same way as we run our customers. So we run our own website on a kubernetes cluster using our own hugely popular PHP container nginx-php-fpm.

If you are unfamiliar with Kubernetes you can find more information about it on the project's website, but to sum it up, kubernetes is a system that allows us to schedule and manage containers across a series of compute nodes.

So why did we build our own container? We were looking for a way of streamlining the deployment process and so we built a container that allows us to specify some environment variables that the container uses to allow it to pull, and potentially push, to a git repository. You can read about this in previous blog entry here. We've recently finished a further update that allows the use of personal access tokens, rather than a ssh key to authenticate to github. You can read about that here, but to summarise this makes setting up access to your repository much easier.

We can't go into detail in this article about how to build a kubernetes cluster, but we wanted to show how we use our PHP container to run our website. There are a list of resources you might find useful at the end of the article.

Kubernetes is configured using a series of files or commands. You can write the configuration files in either JSON or YAML, we use YAML as that is what the kubernetes' best practice guide recommends. We run our site under a Replication Controller configuration at the moment, but we will move this to the newer Deployment type soon.

Here is our website replication controller yaml file with bits redacted as you would expect:

apiVersion: v1
kind: ReplicationController
metadata:
  namespace: ngineered
  name: ngd-www-app
  labels:
    ngd-www-component: app
spec:
  replicas: 1
  selector:
    ngd-www-component: app
  template:
    metadata:
      labels:
        ngd-www-component: app
    spec:
      containers:
      - name: ngd-www-app
        image: richarvey/nginx-php-fpm:latest
        imagePullPolicy: Always
        env:
          - name: GIT_PERSONAL_TOKEN
            value: 'eW91ZGlkbnR0aGlua2l3b3VsZGRpZHlvdQo='
          - name: GIT_USERNAME
            value: 'our_username'
          - name: GIT_REPO
            value: 'our_repo'
          - name: GIT_EMAIL
            value: 'our_email'
          - name: GIT_NAME
            value: 'container update'
          - name: WEBROOT
            value: 'our_webroot'
          - name: PHP_MEM_LIMIT
            value: '256'
          - name: PHP_POST_MAX_SIZE
            value: '256'
          - name: PHP_UPLOAD_MAX_FILESIZE
            value: '256'
        ports:
        - containerPort: 80

Kubectl the kubernetes configuration tool

Again we can't go into detail about how to setup kubectl to talk to your cluster, but assuming you have a working kubectl and this file is called ngd-website.yaml you can start it by running:

kubectl --namespace ngineered create -f ./ngd-website.yaml

This will create a replication controller and a pod in the ngineered namespace. A pod is the basic object within kubernetes and defines an entity that runs a container image. A pod can have more that one container running within it, but this one just has our PHP image specified by this line:

image: richarvey/nginx-php-fpm:latest

You can specify a tag after the colon and we have specified that the latest image should be pulled and run. The most important part for our container is the section after env:, this part of the file defines name/value pairs that map into environment variables on the container and are used to specify the variables needed to pull our code from our git repository. You can see that these variables map onto those given in the article mentioned before.

Once we have run the kubectl create command above we can check on the status of the pod by running the following:

kubectl --namespace ngineered get pods

You would obviously use a different namespace value.

Which gives similar output to this:

NAME                  READY     STATUS    RESTARTS   AGE
ngd-www-app-gskxo     1/1       Running   0          20d

The Status column is important, you hope to see Running, but you can see ContainerCreating when the image is being pulled, if you see the dreaded Error or CrashLoopBackoff then you need to investigate further. We will write another article on troubleshooting kubernetes at a later date.

Pulling the code

Once your pod is running you can now use the pull script supplied with our PHP container to pull the code, you do this using kubectl once more:

kubectl --namespace ngineered exec ngd-www-app-gskxo /usr/bin/pull

Again you would use your own namespace and the pod name we use here is from the Name column in the get pods command above.

Troubleshooting

If you find you have problems you can shell into the pod and investigate using a command similar to this:

kubectl --namespace ngineered exec ngd-www-app-gskxo -i -t -- bash -il

This should give you a bash prompt within the container.

Contact us

Please feel free to contact us using the details below if you want to discuss what services ngineered can provide to your company.

Useful links

Using CoreOS to setup a kubernetes cluster

If you prefer to watch a video rather than read an article Kelsey Hightower's videos are always very informative:

Kubernetes on bare metal

Tim Hockin is one of the main developers working on Kubernetes, here is a video from him:

Container clusters with Kubernetes



Ian MacDougall

Ian is responsible for Ngineered’s customer builds. An expert in the requirements of the enterprise, he is known for his rock-solid builds, and his sensitivity to legacy systems.

Discussion