Deploy A Laravel Application On Kubernetes Using Cloud Foundry

Ram Iyengar
Cloud Foundry Foundation
5 min readSep 23, 2021

Note — This guide is meant to document a few tips, tricks, caveats, and workarounds employed in getting a functional Laravel application deployed to Kubernetes using Cloud Foundry. It assumes that the reader is new to Cloud Foundry, Laravel, or both. Care has been taken to explain the “whys” of each step to cater to this audience. If it feels very basic, please skip these sections.

This tutorial uses the Google Kubernetes Engine (GKE). However, the steps followed in this guide can be applied to Kubernetes clusters running on any cloud provider, as long as Cloud Foundry (cf-for-k8s) has been installed on it. Also, the series of install steps outlined here can function for any “composer” based PHP application such as Drupal, Symfony, etc.

Summary

We will deploy a simple Laravel application onto a Kubernetes cluster.

Prerequisites

This installation guide comes with a couple of prerequisites. Fortunately, each of these come with links to get setup individually.

1. A functional cf-for-k8s installation — which means a Kubernetes cluster running 3–5 nodes and Cloud Foundry deployed to it. Follow these steps to install it.

2. A MySQL database. In this example we will be using a database running using cf services on the same cluster. To enable this, you need a service broker that offers the MySQL service. Check out this video to learn how. You could use any cloud-hosted db that you have access to.

Installation

1. Clone the Laravel repo from Learnk8s. We will be using this one to get started. The tutorial should work for all Laravel apps though.

$ git clone https://github.com/learnk8s/laravel-kubernetes-demo.git

2. The manifest.yml file is a convenient way of specifying default configuration for use during installation of the Laravel application. The following is the manifest file that will be used:

---
applications:
- name: laravel-demo
buildpack: paketo-buildpacks/php
env:
APP_KEY: base64:DMPu9CzEci0nNj5zX91Kx+T5PVkAdbcxqmND7qx0aWw=
APP_URL: laravel-demo-8.apps.34.69.176.230.nip.io
APP_ENV: local
APP_DEBUG: true
CF_STAGING_TIMEOUT: 15
CF_STARTUP_TIMEOUT: 15
DB_CONNECTION: mysql
DB_HOST: mysql-0d1fd1a12b308b16bbcb.servicebroker.svc.foo.local
DB_PORT: 3306
DB_DATABASE: laravel-db
DB_USERNAME: root
DB_PASSWORD: ●●●●●●●●●●
processes:
- type: task
name: migrate
command: |
php artisan migrate - force
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan optimize

Essentially, there are three parts to this manifest file.

Part I.

The first couple of lines provide directives that are minimal and required for any manifest file. Specifying the name of the application within a manifest is mandatory. In the second line, in order to optimize the build process and increase the accuracy at the “DETECT” phase of the buildpack lifecycle, we specify the buildpack to be used.

The APP_KEY parameter is generated locally by running the following command:

php artisan key:generate - show

For the APP_URL parameter, you will concatenate the application name with the domain that you used when installing cf-for-k8s on your cluster.

The next few parameters are boilerplate, and not many details are required in this context. Suffice it to say that they are all sane defaults for operating applications running on the Cloud Foundry instance.

Part II.

The second significant part of the manifest file is the set of parameters pertaining to the database configuration. By default, Laravel requires a backend database to work with its various components. To make this a true 12-factor app, it needs to be integrated with a database that can be connected through a cloud provider. In this case, we’re using a local database made available via the Cloud Foundry Service broker. In this case, we provide details about the database URI, a name, the port number, root username, and password. Manipulating passwords in plaintext is certainly not a secure practice and the best workarounds are to use secrets or read them from environment variables (details provided separately).

Part III.

The final piece of the manifest file as illustrated here is a set of “tasks”. Cloud Foundry provides a list of tasks that can be executed on the shell at the application root. These tasks are used for scaffolding, install steps, or any other one-time needs. Some example use cases for tasks include migration jobs (db, file storage), data processing, or triggering emails. In this specific case, they are used to execute artisan commands which are a Laravel-specific construct used to prepare the Laravel app for deployment.

3.

The next file we will need to include is a buildpack.yml file. Cloud Foundry makes use of Buildpacks in order to generate the containers it needs for deploying onto the container runtime within Kubernetes. The configuration needed to create these containers is found in the Buildpacks.yml file. Typically it contains information such as php version, composer version, document root, etc. The specific contents for this installation are:

php:
# directory where web app code is stored
# default: htdocs
webserver: httpd # Web server to use, e.g php-server, httpd, nginx
webdirectory: public
version: 7.4.* #PHP Version to use, Default is 8.0 or as defined in composer.json

4.

PHP makes use of several special libraries or plugins that contribute to specific functions within the application. In the case of this specific Laravel app, PHP requires a database interface, OpenSSL, and a couple of others. This list is stored in an extensions.ini file, located within the .php.ini.d directory. The contents of the file are as follows:

extension=openssl.so
extension=pdo.so
extension=pdo_mysql.so
extension=mbstring.so
extension=bz2.so
extension=zlib.so

Create a directory called .php.ini.d and a file named extensions.ini inside it. Paste the above contents into this file and save it.

5.

Due to an open issue in the Paketo PHP Buildpacks, a workaround is required for organizing the vendor workspace which contains all the dependencies for the app, and the home directory of the app itself. To make this work, create a basic .profile script which will create the symbolic links needed to create a redirection. Save the contents below in the base directory of the Laravel application.

#!/bin/bash
ln -s /workspace/app /layers/paketo-buildpacks_php-composer/php-composer-packages/app
ln -s /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor /workspace/vendor

6.

This is the deployment step. Type cf push and push enter.

7.

Wait until the deployment has completed successfully. The following message will be displayed on the terminal.

8. Next, run the tasks for completing the installation.

cf run-task laravel-demo

9. Access the URL of the app from a browser to confirm that the app is running.

This completes the installation of a Laravel application on Kubernetes, using Cloud Foundry.

Thanks to Glenn Rossman for his editorial review. Special thanks to Dishant Pandya for helping with various portions of the installation and much needed clarifications.

--

--

Ram Iyengar
Cloud Foundry Foundation

culture vulture. (d)evangelist. help tech find people, and vice versa.