Deploy PHP Application with Kubernetes on Ubuntu 18.04

Kubernetes is a container orchestration framework that is open source. You can build, upgrade, and scale containers without having to worry about downtime.

Nginx serves as a proxy for PHP-FPM while running a PHP script. Containerizing this configuration in a single container can be a pain, but Kubernetes can make it easier to handle both services in their own containers. Using Kubernetes will allow you to keep your application up to date.

As part of our DigitalOcean Management Services, we’ve seen some such Kubernetes-related queries here at Skynats. Today, we’ll look at how to use Kubernetes to deploy a PHP framework on Ubuntu 18.04.

Create PHP-FPM and Nginx Services

The PHP-FPM and Nginx services will be created in this phase. Access to PHP-FPM pods will be granted by the PHP-FPM programme, while access to Nginx pods will be granted by the Nginx service. Since the PHP-FPM pods will be proxied by Nginx pods, you’ll need to tell the service where to look for them.

You’ll start by making a directory to store your Kubernetes object definitions. Create the definitions directory on your master node by SSH to master node to store your Kubernetes object definitions.

mkdir definitions

Move to the newly created definitions directory

cd definitions

Create a php service.yaml file for your PHP-FPM service.

vim php_service.yaml

To indicate that this object is a service, set the kind to Service. Since it will have links to PHP-FPM, call the service php.You’ll use labels to logically group related objects. Labels will be used to divide objects into “tiers”, such as frontend and backend. Since the PHP pods will be running behind this service, you can name it tier: backend.

Selector labels are used by a service to decide which pods to access. To allocate the pod to the backend tier, use the tier: backend label. To specify that this pod runs PHP, you’ll also add the app: php name. After the metadata portion, add these two labels. Finally  specify the port used to access this service.

The following is an example of a completed php service.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: php
  labels:
    tier: backend
spec:
  selector:
    app: php
    tier: backend
  ports:
  - protocol: TCP
    port: 9000

Save the file and create the service for php-fpm using below command.

kubectl apply -f php_service.yaml

Verify that your service is running:

kubectl get svc

You will see your PHP-FPM service running:

Output
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    10m
php          ClusterIP   10.100.59.238   <none>        9000/TCP   5m

Now, we can create the Nginx service. Create and open a new file called nginx_service.yaml.

vim nginx_service.yaml

Since this service can be used to manage Nginx pods, you should call it nginx. You’ll also have a tier: backend mark to indicate that it belongs in the back-end tier:
Target the pods with the selector labels app: nginx and tier: backend, much like the php service. Make this service available on port 80, which is the standard HTTP port.
Using your Droplet’s public IP address, the Nginx service will be publicly open to the internet. Add your IP under spec.externalIPs.

The following is an example of a completed Nginx service.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80
  externalIPs:
  - your_public_ip

Save and close the file. Create the Nginx service:

kubectl apply -f nginx_service.yaml

You can view all running services by executing:

kubectl get svc

You will see both the PHP-FPM and Nginx services listed in the output:

Output
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    13m
nginx        ClusterIP   10.102.160.47   your_public_ip 80/TCP     50s
php          ClusterIP   10.100.59.238   <none>        9000/TCP   8m

Install the DigitalOcean storage plugin for deploying thr PHP Application

To store your DigitalOcean API token, you’ll first create a Kubernetes Secret object. Secret objects are used to share confidential information with other Kubernetes objects in the same namespace, such as SSH keys and passwords. Namespaces allow you to divide your Kubernetes objects logically.

Open a file named secret.yaml

vim secret.yaml

Your Secret object will be called digitalocean, and it will be added to the kube-system namespace. Add the access-token as stringData. This is what your secret.yaml file would look like:

apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system
stringData:
  access-token: your-api-token

Create the secret service:

kubectl apply -f secret.yaml

Now ,install the DigitalOcean block storage plug-in as your Secret is set up.

kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml

You can now build block storage to store your application code and configuration files after installing the DigitalOcean storage plug-in.

Configuring the Persistent Volume on Ubuntu System.

A Persistent Volume is accessed via a PersistentVolumeClaim, or PVC, which mounts the PV along the appropriate path.

Open file code_volume.yaml

vim code_volume.yaml

Add the below code to the file

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: do-block-storage

Save the file and Create the code PVC using kubectl

kubectl apply -f code_volume.yaml

To view available Persistent Volumes:

kubectl get pv

Create PHP-FPM Application deployment

To create your Deployment, open a new file called php_deployment.yaml

vim php_deployment.yaml

The Deployment will manage your PHP-FPM pods, so name the Deployment object php. Add the below code to the file opened.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: php
      tier: backend
  template:
    metadata:
      labels:
        app: php
        tier: backend
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code
      containers:
      - name: php
        image: php:7-fpm
        volumeMounts:
        - name: code
          mountPath: /code
      initContainers:
      - name: install
        image: busybox
        volumeMounts:
        - name: code
          mountPath: /code
        command:
        - wget
        - "-O"
        - "/code/index.php"
        - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php

Save the file and create the PHP-FPM Deployment

kubectl apply -f php_deployment.yaml

You can view your Deployment by running:

kubectl get deployments

You can view the pods in this Deployment

kubectl get pods

Nginx Deployment on Ubuntu server to run PHP Application

To configure Nginx in this step, you’ll use a ConfigMap. Your configuration is stored in a key-value format in a ConfigMap, which you can reference in other Kubernetes object definitions.

Create a nginx_configMap.yaml file for your ConfigMap

vim nginx_configMap.yaml

Add the data for the ConfigMap. The final nginx_configMap.yaml will be as below:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  labels:
    tier: backend
data:
  config : |
    server {
      index index.php index.html;
      error_log  /var/log/nginx/error.log;
      access_log /var/log/nginx/access.log;
      root /code;

      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }

      location ~ \.php$ {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass php:9000;
          fastcgi_index index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }

Save the file and create ConfigMap

kubectl apply -f nginx_configMap.yaml

After creating ConfigMap, we can build the Nginx Deployment.

Open nginx_deployment.yaml file:

vim nginx_deployment.yaml

Paste the entire code in the file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      tier: backend
  template:
    metadata:
      labels:
        app: nginx
        tier: backend
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code
      - name: config
        configMap:
          name: nginx-config
          items:
          - key: config
            path: site.conf
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - name: code
          mountPath: /code
        - name: config
          mountPath: /etc/nginx/conf.d

Save the file and create Nginx Deployment

kubectl apply -f nginx_deployment.yaml

You can see Nginx and PHP-FPM Deployments using:

kubectl get deployments

Run the command to list the pods managed by the Deployments

kubectl get pods

Finally, you can see the list of services running by:

kubectl get services -o wide
Output
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE       SELECTOR
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    39m       <none>
nginx        ClusterIP   10.102.160.47   your_public_ip 80/TCP     27m       app=nginx,tier=backend
php          ClusterIP   10.100.59.238   <none>        9000/TCP   34m       app=php,tier=backend

You will get your public IP from above output. Visit your server by typing http://your_public_ip into your browser. You’ll see the php info() performance and know that your Kubernetes services are up and running.

If you need any assistance, our Support Engineers are available anytime.

FREE SERVER AUDITING

Get Auditing Report of Your Server for FREE!!