Service Exchange: Evolution of Service Management in disaggregated PaaS world.
Lately, we’ve all been observing a clear trend of PaaS disaggregating into atomic components and individual open source projects forming around each one. Cloud luminaries like James Urquart and Randy Bias spoke about this phenomenon, also labeling it as Services-as-a-Platform. Gartner refers to the same, labeling it as “pivot from PaaS to CaaS.” And now that we have a Gartner approved label for this, stand by for big vendors to announce their CaaS strategies.
The disaggregating PaaS phenomenon is driven bottoms up by the development community. Developers that disagree with the opinionated and monolithic PaaS implementation of a particular vendor choose to use alternative components and architectures. Because of it, this disaggregation of PaaS carries the promise of getting broad adoption by the development community; something that monolithic PaaS was never able to achieve. On the other hand, it also creates many challenges.
The most acute of those challenges is something I call the challenge of “overlapping functionality.” As different components of PaaS separate out, some functionality that was historically an opinionated attribute within a monolithic PaaS, ends up in the middle, between two or more atomic components. Instead of a single, opinionated approach, you end up with several overlapping implementations, each carrying a different opinion.
A vivid example of this trend is an emergence of “service mesh” concept in service networking space. In the monolithic PaaS world, service-to-service networking was implemented “in the realm of invisible and implied infrastructure” and was an integrated part of whatever PaaS stack you chose to use. As we moved into the realm of CaaS and atomic components, service-to-service networking fell into the bucket of “overlapping functionality”. As polyglot organizations started building more and more diverse services in multiple languages that all had to work together, observability and troubleshooting became impossible. This created the need to make service communication first class citizen of the stack, and now we are seeing a new industry forming around service mesh with projects like Istio and LinkerD.
Another example is that UI and opinionated API of a monolithic PaaS is giving way to CI/CD-centric tools for managing service lifecycle. As a result, Spinnaker or Fabric8 are emerging as point solutions for continuous delivery of services, whereas efforts like Open Broker API are pushing standardization around service management and cataloguing.
As disaggregation of monolithic PaaS into CaaS components is happening, one area that still needs attention is service management. To better understand the problem, we have to answer some questions. How do we create consumable services from a bunch of containers? Where should rules affecting the behaviors of services reside? How should they be expressed by both the owners of the service and the owners of the environment, where services would be executing. How can these two worldviews coexist without contradiction?
Further, a lack of focus on formalizing a service consumption model, beyond a set of primitives expressed in the Open Broker API, makes management and update of services difficult and unpredictable due to inherent lack of understanding of dependencies and impact of operations affecting corresponding services. Current models impose too much burden of operational knowledge of inner workings of services onto their consumers.
Implementationally and philosophically, these functions appear to be closely related. They form a control model that one can not easily pry into independent, atomic components. For example, If one has a dependency on a particular service, whether and where this service should be allocated or whether one has to be redirected to an existing instance, with specific access rights, failover properties, and resources assigned/managed accordingly — is it a service consumption or a service lifecycle problem?
Just like we saw the need to evolve service-to-service communication beyond language specific libraries and into the first class citizen manifested in service meshes, we are now facing the need to do the same for service management. I call this functionality a Service Exchange.
Service Exchange is a direct evolution of the Service Broker concept. Rather than focusing on how to imperatively instantiate and binding specific services, the focus of the Service Exchange is tri-fold:
- A concise consumption model where the consumer of the service is shielded from understanding of its inner workings and what instance of the service is being used.
- A self-contained definition of the service that does not only point to the packaged code and some orchestration directives for instantiation, but also adds declarative means of codifying lifecycle, resource and consumption control in a way that is easily controlled by the service owner.
- Provide a way of specifying ops and governance rules that affect where, how services are instantiated, their affinity to the resources and dependencies, as well as regulation of environment-specific and cross-environment behaviors. For example: high priority services require all their dependencies to be instantiated within guaranteed distance/affinity or that highly sensitive components running in private environments should use encryption to talk to the service running externally.
Service exchange allows multi-team organizations assemble, share and consume application services without any need for synchronous linear operational dependencies, with each team providing and operating the piece that they own and have deep expertise in. This way, the big picture is sourced from multiple pieces provided by individual teams. As part of this process, all necessary information for automation and control of service lifecycle, its dependencies and behaviors is provided and codified. This method enables the service owner to define application services and operate them securely under tight governance and operational constraints over multiple environments.
At the heart of this approach is the definition of the service and its immediate “consumption” dependencies, expressed in a way that is devoid of any instance specific information. Service is a secure self-contained entity that defines the workload, its composition and behaviors. It encapsulates and abstracts all of the inner workings of the service (for example, allocation and scaling of shared or dedicated instances, authentication and authorization rules, access control), so the consumers of the service, such as other services or external entities, are not aware of the structural and behavioral detail, and such facilities can be in full control of the providing service’s owner. In this model, the consuming service only needs to understand the contract that is exposed by the providing service. There’s no need to worry about specific instances and their implementation detail.
Separation of concerns is one of the main guiding principles of Service Exchange. All behaviors of the system, including application services, are subjected to operational and governance rules that allow abstract reasoning about services under control based on their generalized properties (expressed as parametrized labels), rather than understanding of the instances that oftentimes can be transient in nature. To avoid unnecessary environmental detail “leaking” into the application intent, making it non-portable, these rules are specified externally, by the respective roles. They can be treated in a localizable fashion, as local “jurisdictions”, “domains” or “environments”. This way, rules can vary across multiple parts of the datacenter or the clouds, all without any alteration to service intent definition. These rules are designed to augment service intent definition and formalize the effect on how resources are orchestrated (scheduled/placed), service communications, scaling limitations, encryption etc.
Service Exchange takes all those definitions, dependencies, policies and decides whether to allocate a new dedicated or shared service context or assign a consumer to an existing one, in the environment/location dictated by the policy. It deploys the corresponding microservices to the assigned environments/clouds and keeps everything up and running, as definitions, policies, dependencies as well as application states change. As a result, all underlying microservice architecture components are configured and observed, and higher level service centric policies are translated into the format that lower levels can understand and enforce. The enforcement is carried out via the standard components like API gateways, Service Meshes, Container Orchestration Systems etc.
Service Exchange approach drastically reduces the complexity of managing interactions across complex application landscapes, and emphasizes boundaries of ownership and responsibilities in a large multi-team organizations. The result is the enterprise free of hard silos, yet with clearly identified roles that can collaborate without any blocking cross-organizational dependencies.