BLOG
17 September 2020

Let's Try Cloud Foundry for Deploying Your Application

tech

If you are interested in using Cloud Foundry as your cloud platform of choice, but never had any experience with it, then you should first try it on a small scale.

That’s when cfdev project comes in handy – it allows you to create a fully working Cloud Foundry platform installation on a single physical device, including your work laptop.

You just need to be aware that it must be a slightly more powerful device – documentation recommends at least 8 GB of available RAM, 60GB of usable hard disk space, and 2 powerful CPU cores for it to run.

Installing the basics

First, you need to install the Cloud Foundry command-line interface. The instructions can be found in the official platform documentation, but on Debian/Ubuntu/RHEL/CentOS it is as easy as installing the software from the provided package. The other dependency is BOSH, which will be used to manage underlying Virtual Machines infrastructure. Just download the appropriate binary from the github releases page.

After you installed CF and BOSH CLIs you need to add the cfdev plugin to your Cloud Foundry installation:

cf install-plugin -r CF-Community cfdev

Then there’s only one command standing between you and the fully working Cloud Foundry platform. Please enter the below in your terminal:

cf dev start

You will see a welcome screen with basic CF platform information like the used domain (it’s local only, you won’t be able to access the dev CF platform outside your device), login details, and available services. CFDev comes with one available service of MySQL database, so let’s deploy it. It will not create a service instance but install a service broker, which will make the service available in the marketplace later.

cf dev deploy-service mysql

The results of running the above mentioned commands.

Configuring organizations, spaces and users

Cloud Foundry platform is built around organizations. An organization is an abstraction for a single cloud tenant, for example, a single, separated application. Organizations can be divided into spaces.

The most common usage scenario for spaces is dividing your resources between production, staging, and dev environment. Every user can have different roles for each organization and each space, from the Manager role giving full access, to having no access to specific organization/space. That structure allows Cloud Foundry to host multiple completely separated tenants on one underlying infrastructure.

Let’s create an organization first, then a space in it. Later we will create a new user and assign him a Manager role for both the organization and space. Actually, John will also need a SpaceDeveloper and SpaceManager role to deploy services and view logs.

To do that we need to log in as admin first. Use cf login and input login and password to obtain access to the platform. The default credentials are admin and admin. Then execute the below commands. The expected results are presented in the screenshot below.

1 2 3 4 5 cf create-org softwarehut cf create-space -o softwarehut staging cf create-user johndoe johnspass cf set-org-role johndoe softwarehut OrgManager cf set-space-role johndoe softwarehut staging SpaceManager cf set-space-role johndoe softwarehut staging SpaceDeveloper cf set-space-role johndoe softwarehut staging SpaceAuditor

This way our friend John should have full access to Softwarehut organization and the staging space. Let’s try to login using the newly created user credentials.

Enter cf login again and provide the user details, which we have just created. Because the user is a manager for a single organization and space, they should be automatically targeted during the login.

Deploying MySQL DB instance

Most of the apps will require storage of some kind, MySQL is often used when a relational database is needed. Let’s provision an instance (actually, a couple) of it so we can store the data from the applications we will deploy later. Use a cf marketplace command to see a list of available services and plans. The plans aren’t really limited to the dev platform, so they will use all the resources they can get from the host device, no matter which plan you will choose. This is of course different for a production-ready platform.

Let’s provision two instances of mysql 20mb plan by using the commands listed down below. The instances will be named “mysql1” and “mysql2” – what a surprise!

1 2 cf create-service p-mysql 20mb mysql1 cf create-service p-mysql 20mb mysql2 cf services

The output should be similar to the one below:

Deploying your first application: Stratos Web UI

As you have probably already noticed, there is no graphical interface for cloud foundry provided by default, the only management interface is the CLI. What if we want to have more friendly user interface?

Fortunately, Cloud Foundry also maintains a Stratos project which is a web application that can be deployed directly on CF platform and provides a web management UI, where we can perform nearly every possible action using the CLI.

First, clone the application code from the provided repository link. You should then have a look at the manifest.yml file, which is a deployment descriptor for Cloud Foundry. It contains settings for the deployed application like the name (which will also be a subdomain used for routing), available memory, disk space, etc.

While we are here, let’s add a service binding, so the app will use one of the databases which we have provisioned previously. We will do that using the services section and providing the id of the service, which is “mysql1”.

1 2 3 4 applications: - name: console memory: 1512M disk_quota: 1024M host: console timeout: 180 buildpack: https://github.com/cloudfoundry-incubator/stratos-buildpack#v3 health-check-type: port services: - mysql1

Save the manifest file. Now you are ready to see the magic of Cloud Foundry happen live. When you execute cf push command the application will be build, deployed to the platform and the MySQL service will be bound to it, so the app will use the database as it’s primary data source.

Let’s do that now. It may take a few minutes if you have not built the application previously. As you seen in the manifest file, the app uses custom buildpack so it can build the app from scratch while doing cf push without the need to enter any previous commands. The buildback builds both the JS frontend and Go backend for the app in one go.

When it is finished you should see a summary similar to the below, with a state column saying running. Paste the URL shown in the console to see the app in action. You should login to the app using your Cloud Foundry user credentials. You can see a security warning, because Stratos uses self-signed SSL certificates by default, but as long as you’re only running this on your local machine for testing this should be fine.

Let’s see what’s happening inside the database

Don’t you think it would be great to check if the Stratos app is actually using the database which we have provisioned previously? To do that, let’s deploy one more simple application, which allows us to browse the MySQL databases and check their parameters using a web interface – PivotalMySQLWeb.

First, download the application and build it using mvn package command. This time we will be using the default java buildpack which requires the artifact to be build before executing cf push command. Next, open the manifest.yml file and bind the database service there, exactly like we did for the Stratos app before.

Next, execute cf push command. The application will be deployed under psqlweb subdomain, open it in the browser when it gets deployed (you can find full URL in the deployment summary). The application is based on Spring and uses Spring Security, with the password set in main/resources/application-cloud.yml file. The default credentials are admin as login and cfmysqlweb as password.

When you log in to the app and enter the tables section, you will see the tables created by the Stratos application. Feel free to browse and check what kind of data it saves. You can use PivotalMySQLWeb tool to allow browsing any MySQL database service instance deployed on your Cloud Foundry platform.

Deploy Spring Boot app and bind the database

Spring Boot is a widely popular framework used to build microservice applications. As our last exercise, let’s build an example Spring Boot application, deploy it to the CF platform, and bind the second database we’ve provisioned earlier to it. The app we will be using is one of the Spring Guides example applications.

Please clone the repository and enter the “complete” directory in it. There’s only one modification that we need to do before we try to connect this app to the database. It was created to work with in-memory database, but if we want it to connect to actual relational DB, we need to create a file in src/main/resources/application.properties and add a single line in there: spring.jpa.hibernate.ddl-auto=create. This will allow the app to create a database schema on startup.

Next, build the app using mvn clean package command. After that, create a manifest.yml file for the Cloud Foundry. Put the below content in it:

1 2 --- applications: - name: spring-demo memory: 1G instances: 1 path: ./target/accessing-data-rest-0.0.1-SNAPSHOT.jar

Cloud Foundry will automatically use Java buildpack for jar artifacts. You have probably also noticed that we didn’t bind the service in the manifest. Instead, this time we will do that at runtime using CLI commands. For now, please execute the cf push command to deploy the Spring Boot app to Cloud Foundry. Oops! You are now probably seeing the same as me – an error during the deployment! What has happened? CF is trying to help us – look at the error information:

So, let’s actually use the cf logs command as suggested. It’s a very useful command, which allows us to check recent logs for any app deployed on CF platform – just replace spring-demo with the app name of your choice. But, what has happened with our demo app? When you execute the command, you will notice the error similar to this:

2020-06-09T08:52:48.38+0200 [APP/PROC/WEB/0] ERR Cannot calculate JVM memory configuration: There is insufficient memory remaining for heap. Memory available for allocation 512M is less than allocated memory 613085K (-XX:ReservedCodeCacheSize=240M, -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=101085K, -Xss1M * 250 threads)

As you can see, the available memory is an issue. “But my PC has got enough!” you might say. It might have it, indeed. However, it’s not the physical memory on your workstation, but the memory provided to the staging container, which is actually containerizing our demo app. Fortunately, the fix is as simple as adding just one parameter to the cf push command. Let’s use cf push -m 1G.

This time everything should go smoothly. Java buildpack often requires more than the default 512MB of memory to successfully go through the staging and deployment process. When the app deploys, run cf bind-service spring-demo mysql2 to bind the MySQL database service to the app. This alters the environment variables for our spring-demo app, so for the app to pick up the changes we need to restart it. This can be done using cf restage spring-demo command. Do that now. Also, let’s change the binding for our psqlweb app so we can see the mysql2 database.

Please execute:

1 2 cf unbind-service psqlweb mysql1 cf unbind-service psqlweb mysql2 cf restage psqlweb

When both apps are up and running, it’s time to do some testing! Let’s POST some data in the Spring app. Do a POST request to http://spring-demo.dev.cfdev.sh/people providing the below JSON as a request body.

{ "firstName": "John", "lastName": "Doe" }

This will add a Person object to our database with first and last name as we provided. Open https://psqlweb.dev.cfdev.sh/, and you should see two tables: person and hibernate_sequence. In person table you will find the data we have just pushed towards the app. You can also go ahead and do a GET request to http://spring-demo.dev.cfdev.sh/people/1, which should return a HAL/JSON object with our John Doe data.

Wrapping up

That was easy, wasn’t it? Cloud Foundry makes tasks like provisioning the database and connecting it to our microservice easy. Using service brokers you can provide your developers with the ability to provision almost every kind of service you can think of, including databases, message brokers, caching solutions, etc.

This article is already long enough, but I hope that you learned enough about Cloud Foundry to continue the journey yourself. The next areas that I would suggest for you to explore are microservices monitoring and scalability. These are also essential features for a modern cloud deployment platform and, of course, Cloud Foundry provides them and makes them as easy to use as they can be!

I believe that after going through the above exercise you will have practical knowledge on what advantages Cloud Foundry may bring to your team and its projects. It is an interesting option for your next cloud-native application deployment solution, but always remember to carefully consider pros and cons before choosing one over the other. If you still cannot decide between Cloud Foundry and Kubernetes, you should check our other article on the subject, which may be helpful.

Explore our custom software development services



Author
Bartosz Siemieńczuk
Software Developer