Monday, January 14, 2019

Devs will just dev! The Cloud Foundry promise

“Every company is a technology company” said Peter Sondergaard and evidence of this is all around us. But it was not so easy becoming a technology company, the entry barriers were high. Besides developing their business propositions, companies had to develop, maintain and operate the platform on top of which their businesses (i.e. applications) run. Until Cloud options and "X as a Service” models became available. It started mainly with Infrastructure as a Service (IaaS) offerings but like everything, it keeps evolving.

Rise of DevOps culture, automated pipelines, container technologies, microservices, all contributed to an improved situation. And all these are still evolving and getting increasingly popular. But still, businesses have to deal with things outside the development of their specific business propositions. There is still operational load to carry. And the load seems to be moved now to the hands of developers. Cloud Foundry helps eliminating this operational load, and the need of building platforms and utility components that have no relation to your business propositions. Cloud Foundry makes possible to develop only what contributes to your bottom line and it takes care of the rest. It allows developers, to just develop! 

Cloud Foundry (CF) is an open source platform for hosting cloud native applications. When running on CF you only have to manage your applications and data while CF takes care of the rest. At the same time it allows you to choose your underlying infrastructure, be it AWS, Openstack or you own. CF does not limit you on the kind of applications you can run on it. It supports many languages such as Java, Go, NodeJS, Ruby and others but most importantly, since it is open source, it allows the community to develop and provide what might be missing. The Cloud Foundry platform itself has many implementations and certified providers include Pivotal, IBM, Atos and SAP. As a user, you gain from the abstraction. You interact with all these platforms in the same way. If you know how to run your applications in one of them, you can do it in all of them. The above can be summarized as Cloud Foundry being a language agnostic, multi-vendor, multi-cloud environment for running cloud native applications.

Let’s see what you get from Cloud Foundry, before showing how it delivers:

  • Always on: it ensures that your system has the resources you specify 24/7
  • Easy elasticity: scale up, down in and out. Fast and possibly without downtime
  • Language Agnostic: run your apps in the language and frameworks that suit you
  • Out of the box functionality: common needs in any application are provided and can be used so you do not have to built it yourself
  • Distributed tracing: distributed applications can be difficult to analyze logs and tracing but CF helps with that too
  • Guards against cascading failure: the failure of one component will not bring others of your system down
  • No vendor lock-in: multi-vendor, multi-cloud, you can switch where you run your applications any time. No changes in your actual application code necessary
  • Enhanced security: ways that makes your application more secure will be discussed later
  • You only need to care about your code! No need to manage the platform, just describe what you want and CF takes care of it for you

You can easily see how Cloud Foundry delivers the above by examining the platform itself. Each component has a specific purpose. 

Every Cloud Foundry provider has their own UI for interacting with an instance, but all CF implementations share the same API. Cloud Foundry Command Line Interface (CLI), is a terminal that allows you to communicate with the CF instance in which you want to run your apps (target). Underneath, the CLI makes a series of REST calls to your target. Through the CLI you can connect to the platform, and instruct Cloud Foundry to deploy your application, scale it, bind it to services and more. 

To show how easy it is to deploy and manage an application via the CLI and Cloud Foundry, let’s say that we want to deploy a Java app called myapp, to run on 2 instances, with 1G memory per node. This is simply done by:

cf push myapp -b java_buildpack -i 2 -m 1G -p ./myapp.jar --random-route

That’s it! Our application will run with the specifications instructed, will be accessible on a random auto-generated endpoint and CF will make sure that it stays at this desired situation at all times.

The Cloud Controller, is your interface with Cloud Foundry. It provides the API that listens to the requests made by the CLI and kick-starts the processes for deploying, running, scaling, monitoring and managing your applications. The Cloud Controller is in charge of keeping track of your desired state of your applications, meaning, what was specified for each app when it was “pushed”. It keeps track of such metadata on the Cloud Controller Database. It also stores the uploaded application (the jar in the above example) on the Blob Store.

The Router, is the first component (after the load balancer) that receives incoming requests to a given CF instance and directs the request either to the Cloud Controller or to the application listening on the endpoint specified in the request. Applications go on and off, their number of instances change, as well as the URIs (called routes) on which they are “listening”. The Router takes care to direct each call to the appropriate receiver while all these events are taking place. It achieves that using a routing table which maps the routes to applications. The routes are emitted via the nats message bus. An application can be bound to zero or more routes. A route can be mapped to zero or more applications. This gives us great flexibility, for example to easily make a new release with no downtime. Additionally, when handling requests, the router adds headers for enabling distributed tracing. It allows us to follow a logical request within the platform and all the internal services called in order to handle it.

Diego takes care of the lifecycle and health of your applications using a set of subcomponents with a specific purpose (see picture below). Its Garden component creates containers for the apps as instructed and keeps track on their actual state. Diego contains one or more virtual machines called Cells and the containers for the applications run in them. Knowing the actual state of your application and in cooperation with Cloud Controller (who knows the desired) it ensures that the health of the applications are as expected. Bulletin Board System (BBS) monitors the real time state of your applications and periodically compares it with the desired state (received via nsync). If for some reason one of the instances of your application crashes, Diego Brain discards it and fires up another container with your application automatically. The containers are a made of the operating system, information about the system environment and the application droplet (will be explained in next section). When about to create new instance of an application, Cell Rep performs auction on which cell to host the container. Diego opts for deploying instances of the same applications across different cells to increase resiliency. If enabled also across multiple availability zones. Always on, no need for late night calls to Ops.

Cloud Foundry components. source 
Chances are that your applications need runtime dependencies to execute such as JRE. When staging your applications, external dependencies are added into them, so your application can work. These runtime dependencies are called Buildpacks. There are buildpacks for different kind of languages and different buildpacks for each language. When pushing the application it is possible to define the buildpack you want to use, else Cloud Foundry will try to identify the appropriate buildpack. The application along with the buildpack generate a droplet which is a binary executable that runs inside a container in a Diego cell. The droplet is also stored in the Blob Store.

Applications generate logs and so are the components of Cloud Foundry (e.g., Cloud Controller, Diego, Router). A lot of metrics are generated through the applications lifecycle which are crucial for operations. Loggregator, as the name suggests, is in charge of aggregating all the logs and metrics from your applications (as long as you direct them to standard out and standard error). The logs are made available in real time via CLI (temporarily) but they can also be streamed onto external tools that persist, index and search them such as Splunk. It is important to note that logs can be lost in the Loggregator and this is by design. Logs can be dropped if in danger of the Loggregator becoming bottleneck.

Most applications have common needs, such as persisting data. Such needs can be covered in CF with the use of services. Services can be databases, message buses or specific applications you built in order to do something needed in your system only. Services should be considered as resources which can be bound to applications. Cloud Foundry maintains a list of readily available services which can be found in its marketplace. These services are called managed services. When you want to make a service available in the marketplace, you need to implement the Service Broker API. All services are accessible through this standardized interface. When an application requests to be bound to a service, the service broker is responsible for creating the service instance and passing the credentials to the application as environment variables. 

A special kind of services are the so called route services. These are services that are bound to routes and not applications. Their main usage is for cross cutting concerns, for example checking certain headers and perform some validations before the call reaches applications. We could create an application that does that, create a route service out of it, and place it to the routes of applications we select. Then when a request is received by the router, if the route is bound to a route service, first goes through the route service and then back to the router and eventually to the app. 

One can guess that there are a lot of things going on in terms of security. A detailed description is out of the scope, but we should briefly mention the highlights. Cloud Foundry is a platform, used by many tenants so there is a need for authentication and authorization of users. This way, there can be a segregation between orgs (a logical separation of tenants in a CF instance) and spaces (a logical division of parts of orgs). Users can only perform actions permitted by their assigned role. Cloud Foundry’ s User Account and Authentication (UAA) takes care of that. It is an OAuth2 provider for the platform but UAA can be used as a service itself by your applications. Besides that, there are other reasons that enhance your security when running in CF. Your applications are behind the Load Balancer and the Router, and that decreases the network surface exposed for potential attacks. Also, the easiness of “throwing away” and replacing the containers in which your apps run, makes applying security patches simple and fast. Containers are isolated from each other and all traffic to your application is encrypted. Standardized buildpacks can put you at ease about what your application is running on. 

It should be clear that Cloud Foundry is a strong enabler for developers. It takes care of operational load and makes sure that our systems just work. It allows developers to focus on what matters most: the applications or better, the business proposition to customers.

2 comments: