The Open Service Broker API and Why it Matters
The Cloud Foundry Foundation publicly launched the Open Service Broker API project (OSB) last week, and though I was dubious at first, my colleague Robert Moss has made me a convert. The past five years has brought incredible change to application architecture; with cloud native design patterns, twelve-factor, continuous delivery, containers, and cloud services, do we really need a new project talking about “open” and “services”? Now that I’ve converted, of course the answer is “yes”, but we need to bypass the hyperbole and make it crystal clear why OSB is an idea that all developers and architects need to understand.
By now everyone in the industry who hasn’t been living under a rock is familiar with the idea of microservices: applications are built up from small, modular pieces that each expose an interface. (And for those of you who have been under a rock: it’s like code libraries, except the microservices are distributed and long-running, or if using Function-as-a-Service, they’re not long-running, they’re just distributed.) In any case, microservices are distributed, which means in constructing an application, you need to know how to wire them up.
The Open Service Broker API is the latest product of a lot of smart people (Including my colleague, Robert) who have been thinking about how to solve this service wiring problem, which we’ll summarize as follows:
How do system components get connected to the service components they require?
It’s not a new problem, but microservice architectures increase the pressure on solutions, and the OSB idea represents the biggest breakthrough in solving the wiring problem since DNS. Simply put, the OSB API lets:
- Consumers request a service, with identification and parameters
- Brokers respond with connection information, based on that request’s context, and possibly doing things first in order to fulfil that request optimally
In practice, OSB has a little bit more complexity — a factor of four, as the API applies the pattern above at the time of service birth and service death, and when binding or unbinding a service to an application. But the essence of the innovation is implied in those few bold words, and the colossal capabilities they belie.
A Brief History of Service Wiring
To appreciate the significance of “identification”, “parameters”, and “possibly doing things first”, it’s worth looking at other solutions people have employed for service wiring.
Stage 1: DNS
In the beginning was DNS. Everything before — the command line, bulletin board systems, TCP/IP, UUCP — was fundamentally anti-social. With the Domain Name System, ugly 32-bit number can be given a pretty name, and machines can resolve that pretty name back to the right number reliably and efficiently. My application wants to get some finance data from Yahoo!, I can simply tell it to go to “finance.yahoo.com”.
The complex process of finding the address so my application traffic can route to it is taken care of by the humble DNS. It can load-balance by giving out any of many addresses, and it’s done in a way that survives Yahoo!’s changing IP addresses (as they move to Verizon’s cloud). It can even know where I am and give an address near me. It’s brilliant, and it works with an efficiency and scale that makes the Internet of Things climb back into its crib.
Stage 0: Static Endpoints
I called DNS humble just a few sentences back: whilst often a noble thing, humility is DNS’s biggest flaw. For a vast number of developers, the notion that DNS could do service wiring on any scale smaller than planetary simply never occurred. DNS’s second biggest impediment is that for most developers to whom the idea of DNS for local service wiring did occur, the DNS server configuration was too cumbersome, programmatically and/or politically. Logically it’s not hard to apply DNS in a local context, with subdomains and domain search paths, and in some lucky environments we’ve seen this happen. But in the main, DNS has been relegated to the public internet, for web-sites and email addresses and little more.
This takes us backwards in our history, from Stage 1 to Stage 0, where we observe developers hard-coding IP addresses in their code. Enlightened shops would replace this by configuration and dependency injection (normally after a severe server outage and IP address shake-up). It’s a false enlightenment, however, as you were still configuring and injecting static IP addresses, and probably sharing them via fax machines too.
Stage 2: Service Discovery Systems
These dark ages went on for decades, careful fax paper records of IP addresses and ports and credentials (which may have given way to spreadsheets), but it inevitably sprawled to become a big messy zoo. Registry and directory services came and went until one day, a chubby ZooKeeper heralded a cleaner way, still in widespread use: “I will record your addresses, and you can search me and query me so your applications can use names,” it said, solving that static IP mess. “Write to me if you want, and I will coordinate and distribute that knowledge so others can find it,” it said, solving the cumbersome-to-configure-DNS problem and taking much of the pain out of split-brain. Enterprise service architectures were sold, but a vicious rumour — “he’s written in Java!” — led many in the wiring desert to consider him scarcely better than cuneiform on wet clay tablets. Non-Java cousins etc and Eureka and consul soon followed, bringing the youth into the fold, and bringing a few improvements of their own. “Dig me,” some of these new arrivals even said: “I speak DNS.” And with that these new systems won over even the greybeards.
This type of service wiring solution, the service discovery pattern, needs application components to be wired with only a single service discovery endpoint: components can then find out about the services they require dynamically. If they expose services, they can write their details for other components to find and consume them, and if there’s contention or races, the service discovery can offer election or conflict resolution. Components can block until their dependencies are online, making it simpler to start a collection of microservices, or look up metadata and configuration for the services being provided. While much of this is possible with DNS, service discovery adds a more modern-looking API, and an API for adding and changing services. In some service discovery systems, health checks can be setup to run against services, so failures can be identified automatically, and configuration information updated accordingly.
The Modern Era: Microservices and Smart Wiring
This is where we are today. But as a solution it’s not quite satisfactory. We’re post-language now; whether it’s Java or Go or Python, it’s not the service discovery implementation I care about, it’s the API. If we get the APIs right, our tools will interoperate and everything will be as marvellous as when DNS was shiny and new.
This is the vision of the Open Service Broker API.
To achieve this, however, we have to agree on the scope of the problem. And when looking at the problem through an API lens, it becomes clear that the problem is not a lookup-style discovery, but a wiring challenge: the API needs to return the right wiring details for a consumer. That may vary based on any number of factors, and the problem is more akin to brokerage than discovery.
This is the approach Cloud Foundry has taken in its Service Broker API; over the past couple of years it has proven incredibly versatile and powerful, so it’s a natural choice to start with. Enough people were interested that the Open Service Broker API project was launched to decouple this from Cloud Foundry and make it a general service wiring solution.
(Disclaimer: although I am interested, I wasn’t interested enough to be involved. Or, rather, my time has been dominated by service deployment and management not discovery and brokerage. But Robert Moss, an active member of the CF Service Broker API working group (now OSB API PMC), and the author of the CF Foundation Brooklyn Service Broker and our company’s Cloudsoft Service Broker built around BSB, has been involved. It’s in talking with him I’ve been struck by the significance of what’s going on there, hence this blog.)
Stage 3: Service Brokerage
The need for a common API is important, and necessary, but obvious once it’s pointed out. The importance of the “broker” role is more subtle, but essential if we’re to converge to an API capable of handling the complexities of the real world. (As a side note, describing it as “open” seems trite at first blush, with OSS and community being table stakes in this world, but on a second look that word is also making an important point: the API is open for any system to consume, not just Cloud Foundry. Think “open bar” not “open marriage”, to mix up the “free as in {beer,speech,love}” metaphors.)
In service discovery, and DNS, there’s not much scope to be smart about the caller’s request. Some things can be inferred by the caller’s IP address or make use of pre-defined metadata, but essentially they are all just doing lookups. A broker, on the other hand, will take a bit more time, get to know you, and even consider the right service to connect you to. A broker might even construct for you a bespoke product (but avoid the mortgage-backed securities).
In short, compared with name-address lookup and service discovery, the service broker supports three key things:
- Identification: the broker can know who the caller is, confirm authentication and entitlements, and use that information to choose which services to wire up, and how to do it, depending whether the caller is in dev or prod, investment or retail, India or Canada. In other words, the context of the request and the nature of the requestor (customer) has real bearing on the results returned, and (hopefully) the quality or appropriateness of that result.
- Parameters: the caller can provide constraints and hints, QoS and maximum cost, even callback information — anything of use to the service broker in determining what result to return in response to the request; callback information can even be used by the service or broker to communicate back in the event service changes, migrations, credential rotation, outages, or other dynamic event
- Possibly doing things first: in this age of agile infrastructure and security, a service request might merit some sort of provisioning. This might be new compute (containers, VMs, etc), new routes (tunnels, firewall rules, bandwidth reservation), a new account or sub-account or simply private dedicated credentials. Without a broker to consider the context and prepare the service to meet the request, you can’t create any of these on-demand. Without the capacity of “possibly doing things first”, you’ve essentially got a great big legacy lookup yoke strangling any cloud ambitions.
In Conclusion: What OSB means for Cloudsoft
We’ve seen this active ”concierge” capabilities of service brokers with Cloud Foundry, where new routes can be created for services, and in the Cloudsoft Service Broker (CSB), where databases can be newly created on demand for a group of applications, caller-supplied schemas installed, and each new consumer given its own unique credential for the sake of security and traceability.
For us, opening the Service Broker API means that our Cloudsoft Service Broker can provide that secure database access function for Kubernetes or for “heritage” applications. The same applies to its capabilities to create consumable services from simple, declarative Apache Brooklyn blueprints. And the tracking and control that CSB provides — where operators can see at a glance who is consuming which services, and admins can enforce access controls, network isolation, even disconnect specific usages — now becomes available as a drop-in solution wherever applications or platforms consume the OSB API.