PaaS platforms like Cloud Foundry, container orchestrators like Kubernetes, Serverless platforms like OpenWhisk and Service-mesh like Istio are all great technologies to deploy and manage your microservices on. Common wisdom says there is no such thing as too many choices, but abundance of choices can lead to analysis paralysis. In this code we look at deployment experience the different platforms provide, and what do we gain and loose by choosing one against another.
We start with a sample Node.js monolithic application, Flightassist, factor it into two microservices, and then use it for demonstrating and comparing various deployment technologies. A set of trade-offs and comparisions can be made between these deployment models, and this application provides a basis for those discussions.
The scenarios are accomplished by using:
- Cloud Foundry
- Kubernetes Clusters
- Istio
- OpenWhisk
- Cloudant NoSQL Database
- Insights for Weather
- TripIt Developer API
- FlightStats Developer API
Register and obtain the keys for FlightStats Developer API and TripIt Developer API to query flight status.
When signing up for a FlightStats developer key, note that there is a review process that may take 24 hours or more to get your application credentials activated for a 30-day trial with the API.
Click the button to deploy your app and fill in all the variables from Delivery Pipeline. For Further instructions, please follow the Toolchain instructions.
You should see a link under the Cloud Foundry Deploy stage and that's where your application is hosting.
Toolchain Scenarios Two: Microservices on Kubernetes Clusters, with or without Serverless capabilities
If you want to deploy with microservices, please leave the OpenWhisk Auth variable blank on Delivery Pipeline. Otherwise, fill in the OpenWhisk Auth variable to enable serverless for your Flightassist.
Then, click View logs and history under Kubernetes Deploy stage in your pipeline to access your application via the URL link at the end of your logs.
- Provision application services - Cloudant Database and Insights for Weather Service
- Deploy monolithic application
- Factor monolithic application into microservices and test
After you deployed Flightassist using any platform, you can go to How to Use Flightassist and start testing your application.
First, clone and get in our repository git clone https://github.com/IBM/Microservices-deployment-with-PaaS-Containers-and-Serverless-Platforms.git && cd Microservices-deployment-with-PaaS-Containers-and-Serverless-Platforms to obtain the necessary files and scripts for building this example.
Since we need to create services using the command line, we need to install Bluemix CLI before proceeding to the following steps.
We will use Bluemix's The Cloudant NoSQL database service and Insights for Weather service for our database and weather data. Therefore, run the following commands to create cloudant and Insights for Weather service.
For this example, we recommend you name your services to mycloudant and myweatherinsights.
bx service create cloudantNoSQLDB Lite mycloudant bx service create weatherinsights Free-v2 myweatherinsightsBefore moving on, the demo application is missing code to create the databases used to cache API responses in your newly created Cloudant instance. You can run the following commands with your cloudant URL to create the databases.
bx service key-create mycloudant {service key} #You can put any name for your {service key} bx service key-show mycloudant {service key} #This will output your cloudant credential, "url" is Your cloudant URL curl -k -X PUT {your-cloudantURL}/trips curl -k -X PUT {your-cloudantURL}/weather curl -k -X PUT {your-cloudantURL}/connectionsIn this scenario, we will deploy Flightassist as a monolithic application and host it on Cloud Foundry.
First, install Cloud Foundry CLI.
Then, type the following commands to push your application with your own unique application name.
cf push {your_unique_app_name} -f main_application/manifest.ymlNow, go to https://console.ng.bluemix.net/dashboard/apps and select your application. Click the Runtime settings for your application and add these four environment variables to set up external credentials to the TripIt and FlightStats services:
FLIGHTSTATS_APP_ID: application ID assigned by FlightStatsFLIGHTSTATS_APP_KEY: application key assigned by FlightStatsTRIPIT_API_KEY: API key assigned by TripItTRIPIT_API_SECRET: API secret assigned by TripItBASE_URL: You URL for accessing your application. e.g. {app_name}.mybluemix.net
Your application should restart automatically but can be done manually as well in the UI. With the service bindings and added environment variables, the application should be operational at the hostname route you selected for your CF application.
Congratulation, now you can learn about How to Use Flightassist and start testing your application.
To factor the application into microservices, we add a python microservice to the picture. Instead of directly accessing the apis from Node app, the python program will serve as a proxy to query. This step tests the two microservices and associated dockerfiles which are created.
First, install Docker CLI.
Next, edit the docker-compose.yaml file and add your credentials for FLIGHTSTATS_APP_ID, FLIGHTSTATS_APP_KEY, TRIPIT_API_KEY,TRIPIT_API_SECRET,CLOUDANT_URL, and WEATHER_URL. You can run the following command to view your service credentials.
bx service keys {service_name} #This will output all your service keys bx service key-show {service_name} {service key} #This will output your service credential, "url" is Your service URLThen, run the following commands to build your docker images and run Docker Compose.
docker build -f main_application/Dockerfile.local -t flightassist main_application docker build -f flightassist-weather/Dockerfile.alpine -t weather-service flightassist-weather docker-compose upNow, your FlightAssist application should be running on http://localhost:3000/
Make sure you have both developer accounts mentioned in prerequisites. Also make sure you have cloudant and weatherinsights services created as listed in step 1.
In this scenario, we take the Flightassist which is factored in microservices. Since Cloud Foundry apps (warden containers) are not allowed to talk privately, they need to communicate via public route.
We first push the python microservice.
cf push <name1> -f path-to/flightassist-weather/manifest.yml make sure you pick a unique name for the app.
This will bring up the first app we need. The output should look like:
requested state: started instances: 1/1 usage: 256M x 1 instances urls: <name1>.mybluemix.net last uploaded: Thu Jun 8 21:36:15 UTC 2017 stack: unknown buildpack: python_buildpack And we need the urls for next step.
Now we will push the second app, but without starting it.
cf push <name2> -f path-to/main_application/manifest.yml --no-start make sure you pick a unique name for the app, too.
Now we inject the environment variables as in monolithic deployment:
FLIGHTSTATS_APP_ID: application ID assigned by FlightStatsFLIGHTSTATS_APP_KEY: application key assigned by FlightStatsTRIPIT_API_KEY: API key assigned by TripItTRIPIT_API_SECRET: API secret assigned by TripItBASE_URL: You URL for accessing your application. In the format https://{app_name}.mybluemix.net**/**
Plus, a couple more since we have two apps:
USE_WEATHER_SERVICE: trueMICROSERVICE_URL: name1.mybluemix.net
Now we start the 2nd app: cf start <name2>
You can now test the apps by going to http://name2.mybluemix.net
In this scenario, we use the Flightassist microservices in which are in two containers. We will run Flightassist as our main application with weather-service as our microservice to query the weather data. Then, we will host those containers using Kubernetes.
First, follow the Kubernetes Cluster Tutorial to create your own cluster on Bluemix.
Then, install the container registry plugin for Bluemix CLI.
bx plugin install container-registry -r BluemixNext, build your own docker images and push them to your own bluemix container registry.
Replace
<namespace>with your own namespace, you can view your namespace by runningbx cr namespacesIf you have an unauthorized error, run
bx cr loginto authorized your container-registry.
docker build -f main_application/Dockerfile.local -t registry.ng.bluemix.net/<namespace>/flightassist main_application docker build -f flightassist-weather/Dockerfile.alpine -t registry.ng.bluemix.net/<namespace>/weather-service flightassist-weather docker push registry.ng.bluemix.net/<namespace>/flightassist docker push registry.ng.bluemix.net/<namespace>/weather-serviceThen, you need to run the following commands to bind your Cloudant and Weather Insights services to your clusters.
bx cs cluster-service-bind {your-cluster-name} default mycloudant bx cs cluster-service-bind {your-cluster-name} default myweatherinsightsNext, create secret to give FlightStats and TripIt API credentials for Flightassist. Modify the secret.yaml file with flightstats-app-id, flightstats-app-key, tripit-api-key, and tripit-api-secret.
Then, edit the flightassist.yaml and replace the <namespace> with your own namespace. You can obtain your namespace by running bx cr namespace. Also replace <your-app-end-point-url> with your node ip and nodeport (e.g. 169.47.237.139:30080). You can obtain your IP by running kubectl get nodes and your nodeport is 30080.
Lastly, run the following commands to deploy the secret and deployment.
kubectl create -f secret.yaml kubectl create -f flightassist.yamlCongratulation, now your Flightassist application should be running on http://<your_node_ip>:30080. You can go to How to Use Flightassist and start testing your application.
Istio is an open platform that provides a uniform way to connect, manage, and secure microservices. Istio is the result of a joint collaboration between IBM, Google and Lyft as a means to support traffic flow management, access policy enforcement and the telemetry data aggregation between microservices, all without requiring changes to the code
- Download the latest Istio release for your OS: Istio releases
- Extract and go to the root directory.
- Copy the
istioctlbin to your local bin
$ cp bin/istioctl /usr/local/bin ## example for macOS- Run the following command to check if your cluster has RBAC
$ kubectl api-versions | grep rbac-
Grant permissions based on the version of your RBAC
* If you have an alpha version, run:$ kubectl apply -f install/kubernetes/istio-rbac-alpha.yaml
* If you have a **beta** version, run: ```bash $ kubectl apply -f install/kubernetes/istio-rbac-beta.yaml ``` * If **your cluster has no RBAC** enabled, proceed to installing the **Control Plane**. Install the Istio Control Plane in your cluster
kubectl apply -f install/kubernetes/istio.yaml cd ..You should now have the Istio Control Plane running in Pods of your Cluster.
$ kubectl get pods NAME READY STATUS RESTARTS istio-egress-3850639395-30d1v 1/1 Running 0 istio-ingress-4068702052-2st6r 1/1 Running 0 istio-manager-251184572-x9dd4 2/2 Running 0 istio-mixer-2499357295-kn4vq 1/1 Running 0 Important: You must complete scenario two for Kubernetes Clusters in order to proceed the following steps.
First, you want to delete all the services and deployments from the previous scenario.
kubectl delete -f flightassist.yamlNow, grab your isito-ingress IP:Port.
echo $(kubectl get po -l istio=ingress -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc istio-ingress -o jsonpath={.spec.ports[0].nodePort})Then, edit the flightassist.yaml file and replace your BASE_URL with http://<isito-ingress IP:Port>
You also can remove
type:NodePorton flightassist-service because we will access our application via isito-ingress.
Next, deploy ingress to connect the microservices and inject Istio envoys on Flightassist and Weather Microservice.
kubectl create -f ingress.yaml kubectl create -f <(istioctl kube-inject -f flightassist.yaml --includeIPRanges=172.30.0.0/16,172.20.0.0/16)Congratulation, now your Flightassist application should be running on http://<isito-ingress IP:Port>.
In this scenario, we will deploy Flightassist with a function to show how you could replace your microservices with OpenWhisk actions.
Important: You must complete scenario two for Kubernetes Clusters in order to proceed the following steps.
First, you want to delete all the services and deployments from the previous scenario.
kubectl delete -f flightassist.yamlThen, install OpenWhisk CLI and Mark down its credentials.
Next, edit flightassist_serverless.yaml and replace the <namespace> with your own namespace, <your-app-end-point-url> with your node ip and nodeport, and <your-openwhisk-auth> with your OpenWhisk authentication. You can run wsk property get --auth | awk '{print $3}' to view your OpenWhisk authentication.
Now, let's deploy the new flightassist app with serverless capability
kubectl create -f flightassist_serverless.yamlCongratulation, now your Flightassist application should be running on http://<your_node_ip>:30080. Also, you can learn about How to Use Flightassist and start testing your application.
First, you want to add a trip on TripIt. Then, add a new flight plan for your trip. In your plan, please fill in your confirmation number or airline with flight number.
Once you added a new plan and you have your Flightassist running, open your Flightassist and click Authenticate with TripIt to login to Flightassist.
Now you can see the most recent flight status and weather for all your flights within 24 hours.
It's hard to compare the different technologies toe to toe since they are targeted for different use cases. However,we can get a sense of their pros and cons from the above example.
Cloud Foundry: Developer Centric; Developers don't have to build or maintain containers; Support various programming languages and libraries; Large bases of services; Kind of hacky to deploy multi apps; Needs to know CF functions well to manage.
Kubernetes: Orchestration tool that manages complicated container delolyments well; Large services available ;Developer has to build and maintain containers in the repositories.
Istio: Addtion to Kubernetes; Provide load balancing and other features; Needs to know the "envoy" concept.
OpenWhisk: Serverless, event triggering; low cost; function based, doesn't work for large apps; Stateless.
| File | Description |
|---|---|
| flightassist.js | Main application, start the express web server and calling the major AJAX functions |
| All JavaScript files (main_application/*.js) | The implementation of the flightstats, tripIt, and weather information, shared by all deployment options |
| package.json | List the packages required by the application |
| manifest.yml | Description of the application to be deployed |
| File | Description |
|---|---|
| flightassist.js | Main application, start the express web server and calling the major AJAX functions |
| All JavaScript files (main_application/*.js) | The implementation of the flightstats and tripIt information, shared by all deployment options |
| app.py | Weather Microservice, query and sent weather information to the main application |
| package.json | List the packages required by the application |
| Dockerfile.local and Dockerfile.alpine | Description of the Docker image |
| docker-compose.yaml | Specification file for the deployment of the service in Docker |
| File | Description |
|---|---|
| flightassist.js | Main application, start the express web server and calling the major AJAX functions |
| All JavaScript files (main_application/*.js) | The implementation of the flightstats and tripIt information, shared by all deployment options |
| app.py | Weather Microservice, query and sent weather information to the main application |
| package.json | List the packages required by the application |
| Dockerfile.local and Dockerfile.alpine | Description of the Docker image |
| flightassist.yaml and secret.yaml | Specification file for the deployment of the service and secret in Kubernetes |
| File | Description |
|---|---|
| flightassist.js | Main application, start the express web server and calling the major AJAX functions |
| weather.js | Trigger actions in OpenWhisk to get the weather information |
| All JavaScript files (main_application/*.js) | The implementation of the flightstats and tripIt information, shared by all deployment options |
| package.json | List the packages required by the application |
| Dockerfile.local | Description of the Docker image |
| flightassist_serverless.yaml and secret.yaml | Specification file for the deployment of the service and secret in Kubernetes |
This project is based on this flightassist example.
Phil Estes and Lin Sun are the main contributors for the flightassist example.



