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 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.
We will deploy a simple Laravel application onto a Kubernetes cluster.
This installation guide comes with a couple of prerequisites. Fortunately, each of these comes with links to get set up individually.
- 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.
- 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.
- 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
- The manifest.yml file is a convenient way of specifying the default configuration for use during the 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.18.104.22.168.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.
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.
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).
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.
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
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.
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 that 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 press enter.
Wait until the deployment has been completed successfully. The following message will be displayed on the terminal.
- Next, run the tasks for completing the installation.
cf run-task laravel-demo
- 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.