Multiple versions of roles

In what follows we expand the material provided in the configuration section of the component documentation, and the role definition section of the service app documentation.

Motivation

Kumori Platform manges the lifecycle of a deployed service. This includes changes in a deployment ranging from mere configuration parameter changes, to actual software updates changing the way a role is implemented.

Introducing upgrades to the implementation of roles is often best carried out through cautious progressive substitution of an implementation for another. Some strategies that may be followed are

  1. Derive a percentage of the load to the new implementation, in order to observe its behavior, and potentially test it for potential problems not found during standard testing cycles.

  2. Move concrete requests to new implementations of a microservice. Which requests should be sent to what versions is dependent on the client of the microservice. In order to make the decision, some sort of context information must be made available to that client.

In fact, case (1) above can be seen as a specialization of case (2), which is more general.

Kumori Platform covers both classes of usage by means of a tagging mechanisms expressed through the concept of version set's

Version sets

A version set (vset) represents a microservice, potentially implemented using multiple variations of code. As a microservice, a vset defines a channel interface, as any artifact does in Kumori Platform.

The definition of the vset field is as follows

vset: [string]: {
srv:   #MicroService    // The collection of version sets
roles: [rn=#roles]: {
   meta: {...}
   for sn in srv.#servers_a {
      map: "\(sn)": role[rn].artifact.description.srv.#servers  | *sn
   }
   for dn in srv.#duplexes_a {
      map: "\(dn)": role[rn].artifact.description.srv.#duplexes | *dn
   }
}
}

Including a role in a vset implies configuring a field within the roles field of the vset with the name of the role to be added.

The value of that added field will itself be a structure with a meta field, containing the metadata that will be exposed to clients of the vset, and a map field, relating the server/duplex channels of the vset with the server/duplex channels of the role, so that the names of the vset channels may differ from those of the roles in the vset. By default the map is the identity.

When we presented how the topology of a service application was expressed in our model, we introduced the usage of the connect field. In that section, the connect field was introduced as linking roles in a given service, being consistent with our equating role to microservice within a service application.

However, in our model a microservice is actually represented by a version set, which may aggregate multiple roles. Thus, connect actually acts by linking microservices represented by `vset`s through connectors. Or, more precisely, connect links default vsets (vsets associated by default with roles) to vsets via connectors.

Roles and Vsets

Every vset is composed by one or more roles in a service application. In order to make a role belong to a vset, the vset field of the service must include the name of the role within the field vsets of its definition.

Given any role in a service, Kumori Platform defines automatically a default vset with its name, containing only that role. It is not legal to explicitly define a vset with the name of an existing role.

The namespace for vsets includes that of roles within a service application.

For any vset, its channel interface must be specified explicitly. For each role belonging to the vset a map is defined mapping server/duplex channels in the vset to those of the role.

If no map is specified, for a role, the role is assumed to have the same server7duplex channels as the vset.

Roles in multiple vsets

Kumori Platform's allows a role to belong to multiple vsets, although the usual case will see a particular role belonging to just its own vset, or, when actually participating of an upgrade strategy, belonging to its own vset, plus another vset representing the microservice that is being upgraded.

Implementing automatic request routing to a vset

As seen previously, when launching an instance of a component, file /kumori/config.json contains metadata that helps the code in the component decide and discover what the actual implementation of a target vset it should use.

There are occasions when we want the process to be transparent to the actual code of such component, in order to implement policies that randomly reroute part of the traffic to the various roles behind a vset.

Kumori Platform suggests the usage of complement containers (sidecars) to take care of these scenarios proxying the requests of such a component. To support such scenario, Kumori Platform will also resolve the name of each client channel (without the tag), returning the address of a local interface (127.0.0.x, the x depending on the channel).

Then a daemon can be started binding to such local address, waiting for the requests from the main container. This daemon can actaully be started within a sidecar, making the process transparent to the code in the main container.

As sidecars get mapped the same configuration files as the main containers, the sidecar can then apply any routing policy it deems convenient (e.g., weighted random). If a request context can be made available as part of the call (as it may be the case when using http) then the routing logic can be coded within the sidecar, making it more maintainable as it will not require involving functional code in the main container of the component.