-
Notifications
You must be signed in to change notification settings - Fork 21
Kubernetes vs Cloud Foundry
Kubernetes and Cloud Foundry are both technologies that allow you to deploy and run applications on the Cloud. In this blog, I am going to talk about my experiences with deploying the same code pattern, Summit Health Analytics, to both on IBM Cloud.
The Kubernetes Service uses containers to run the application. This means that I needed to containerize the code pattern. To do this, I used Docker. I had to find compatible containers for the different parts of the code pattern. This included two Node.js containers: One for the front end UI and the other for the data service and APIs. In addition I also included a MongoDB container for the data lake database. Once all of the containers were configured and running successfully on my local machine, I pushed the containers to Docker Hub.
With the containers ready to deploy to the Cloud, I then needed to provision a cluster on Kubernetes. Deploying this code pattern to the Cloud can be achieved using either the lite or standard cluster. Once the cluster was done creating, I had to apply YAML files that configured and deployed each container from Docker Hub. For the standard cluster, additional YAML files were applied for configuring the ingress of the two Node.js containers.
Once all of the containers were deployed, I was able to successfully run and interact with the code pattern on IBM Cloud.
Cloud Foundry on IBM Cloud includes an SDK for Node.js for running Node.js applications on Cloud Foundry. For this code pattern, two instances of the SDK needed to be provisioned: One for the front end UI and the other for the data service and APIs. In addition, I provisioned an instance of Compose for MongoDB.
Once all three instances were running, a manifest YAML file needed to be configured for the two Node.js parts of the code pattern. Once I configured the YAML file, I pushed it to IBM Cloud to deploy the code from my local machine to the Cloud.
Once the code was successfully deployed on the Cloud, I was able to successfully run and interact with the code pattern on IBM Cloud.
Deploying to Kubernetes used more steps and required me to have a Docker Hub account, but in the end all parts of the code pattern were running in the same cluster on IBM Cloud. This means that all parts of the code pattern can be accessed from the same base URL.
Even though there were less steps to deploy to Cloud Foundry, the different parts of the code pattern were deployed separately and therefore had to be accessed from different URLs.
Unlike deploying to Cloud Foundry, deploying to Kubernetes on IBM Cloud has a free option. Using the free option means that you can't configure the ingress and therefore have to access the code pattern through the IP Address and Ports. In addition, it uses http rather than https.
With the code pattern running on Kubernetes on the Cloud, I could then focus on making updates. After these updates were running successfully on my local machine, I could then deploy the updated code to the Cloud. This process works similarly to setting up. First, the updated containers need to be pushed to Docker Hub. Next, the YAML files that were used for deploying the containers that are associated with the updated containers need to be deleted and reapplied. What this means is that if I updated code that was in only one of the Node.js containers, I would only need to redeploy that container.
With the code pattern running on Cloud Foundry on the Cloud, I could then focus on making updates. After these updates were running successfully on my local machine, I could then deploy the updated code to the Cloud. This process works similarly to setting up. The same manifest YAML file gets pushed to IBM Cloud to redeploy the code from the local machine to the Cloud.
Similar to deploying, it is much easier to update on Cloud Foundry than Kubernetes. It only requires one command whereas Kubernetes requires the deletion and redeployment of each container that needs updating. I also noticed that at times the container/service would not delete completely on Kubernetes and would require me to delete multiple times.
A key difference between the two is portability and versioning of applications to the Cloud. Docker makes it easy to create different versions of a container. For deploying different versions of an application or even multiple instances of just one version, Kubernetes makes this process simple. For a different cluster provisioned, the same YAML files can be used. However, if a different version of a container is used, the image in the file must be changed to where it is located in Docker Hub. In fact, you don't even need the code on your local machine to deploy, you just need the necessary YAML files. On the other hand, using Cloud Foundry is more complicated. For each additional application you want to deploy, the necessary components need to be provisioned on IBM Cloud. In addition, the code must be on your local machine. For versioning, one option that could be used is to create different branches on GitHub that are associated with a version and push the code for the branch you want to deploy.
Just because an application is running successfully locally, does not mean that it will also run successfully on the Cloud. I learned this when deploying this code pattern to the Cloud. Similarly to debugging this code pattern locally through the browser and logs through the terminal console, Kubernetes on IBM Cloud debugging works similarly. Browser debugging works the same way as running locally. However the logs can be found by running kubectl logs <podname> where podname is the pod where the container is that you are interested in reading the logs for. Unfortunately, sometimes debugging requires pushing multiple updated containers to the Cloud which slows down the process.
The process of debugging on Cloud Foundry is similar to Kubernetes where you can use the browser to debug and also check the logs. The logs can also be run by running a command: ibmcloud cf logs <appname> where appname is the name of the application that you are interested in reading the logs for.
I found reading the logs easier to follow on Kubernetes. Cloud Foundry's logs wraps what is shown in console into their own logs which can be confusing to understand at first.
Initially when working on this code pattern, I was working with a small data set (< 1MB) for sending to the Node.js API responsible for populating the MongoDB database. When I decided to use a larger data set (~ 6MB), I started to run into some issues. First when running locally, I had to increase the body parser limit in the Node.js application. After I fixed that and had the data successfully populating the database locally, I tried it on Kubernetes. Unfortunately, I was getting the following error when trying to send the larger data set:
<head><title>413 Request Entity Too Large</title></head>
<body bgcolor="white">
<center><h1>413 Request Entity Too Large</h1></center>
<hr><center>nginx</center>
</body>
</html>
I found that I needed to set the ingress.bluemix.net/client-max-body-size in the ingress file associated with the container service with the APIs.
Fortunately, Cloud Foundry has auto-scaling so sending a larger data set to my API was not a concern and successfully worked.
Cloud Foundry's auto-scaling feature works great for this code pattern, because the scaling is something that does not have to be worried about since it is done automatically. With Kubernetes, a limit on the size of the data has to be set.
The way I configured this code pattern for Kubernetes has all parts of the code pattern running in the same Kubernetes cluster. This means that all parts of the code pattern can be accessed from the same base URL/IP address. If ingress files are used, you also have the ability to control what/how gets exposed to access. For example, with this code pattern, I have exposed the UI on https://some-url and the APIs on https://api.some-url
The way I configured this code pattern on Cloud Foundry has each part running separately on the Cloud. Unfortunately with the way this code pattern is structured, it cannot all run together in one application. This means that the code pattern is exposed on different URLs for each part.
As I mentioned in the deploying section, unlike deploying to Cloud Foundry, deploying to Kubernetes on IBM Cloud has a free option. Using the free option means that you can't configure the ingress and therefore have to access the code pattern through the IP Address and Ports. In addition, it uses http rather than https. Cloud Foundry automatically uses https.
Because the parts of the code pattern are scattered on Cloud Foundry on IBM Cloud, I noticed that running this code pattern was slower than running it on Kubernetes.