For this use case we have dozens of Tenants sharing many (100-1000) common Services. The Tenants (top level service requestors and root span originators) are very large (high volume) products/applications with the tenancy determined via application code. The Tenant will require their own collector/DB and perhaps may even require multiple collector/DB based on the location of the serving application instance. The tenancy (for all downstream services) is attached to each service request and therefore must be implemented via distributed context.
The Services themselves must not need to be aware of the baggage tag names or to explicitly extract the tenancy information from the context. All spans, including those generated by instrumented 3rd party libraries and frameworks, must automatically include the tenant information as span tags. Each Service will share its Jaeger Agent(s) between all of that service's Tenants. The Jaeger Agent will use the tenancy information in the spans to send those spans to the correct Tenant collector/DB. The Agents config file will contain the data to associate tenant information with a collectors host ip and port information.
In our POC we used specially named baggage tags that would automatically "self promote" to become span tags. These tags will travel with context across to all services and ,after self promoting, to each service's jaeger agent as a tag in every span. For example, any baggage tag that
has a key starting with a double underscore, as in “__tenant-id”, will be automatically promoted to be a span tag in each
(sub) Service. In order to self-promote, the client libraries must be modified to create the span tag from the baggage tag when the opentracing-span is being converted to a thrift-span. We modified and tested the go, java, node.js and python client libraries. Security and an API to hide the implementation could easily be added.
The Jaeger Agent was modified to hold a map of uber tchannel objects using a tenant name as the key. The Jaeger Agent will "route" the spans to different collector/DB's based on the value of a specified span tag. The configuration was modified to support this functionality. Example:
"--collector.host-port=def...@192.168.99.100:30418,ten...@192.168.99.101:30021,ten...@192.168.99.101:30063"
"--collector.route-tag=__tenant-id"
Instructs the jaeger agent, when you see a span tag named “__tenant-id” that has a value of “tenant1”, then use “192.168.99.101:30021” as the host:port address to the collector/DB.
We also created test clients in Java, Go, Python and Node.js. Hotrod was also modified to be multi-tenant. All with great success.At the end we concluded that perhaps the tenant tag or what the agent called the collector.route-tag should be a fixed name. It would get very confusing to have each tenant specify its own different tenant tag to common services.
From AT&T's perspective, we would need this base functionality to begin to use Jaeger. How can we best move this forward.
Thanks,
Bruce Peterson
SRE AT&T
I hope this discussion on multi-tenancy is still alive. At AT&T our main use case is a little different. For our primary use case, span authentication is not needed. For our larger tenants, we will not share the data base. This should make a multi-tenant solution much easier. Let me outline our primary use case and then describe what we have done for a POC. I will call this case Shared Services for Large Tenants.
For this use case we have dozens of Tenants sharing many (100-1000) common Services. The Tenants (top level service requestors and root span originators) are very large (high volume) products/applications with the tenancy determined via application code. The Tenant will require their own collector/DB and perhaps may even require multiple collector/DB based on the location of the serving application instance. The tenancy (for all downstream services) is attached to each service request and therefore must be implemented via distributed context.
The Services themselves must not need to be aware of the baggage tag names or to explicitly extract the tenancy information from the context. All spans, including those generated by instrumented 3rd party libraries and frameworks, must automatically include the tenant information as span tags. Each Service will share its Jaeger Agent(s) between all of that service's Tenants. The Jaeger Agent will use the tenancy information in the spans to send those spans to the correct Tenant collector/DB. The Agents config file will contain the data to associate tenant information with a collectors host ip and port information.
In our POC we used specially named baggage tags that would automatically "self promote" to become span tags. These tags will travel with context across to all services and ,after self promoting, to each service's jaeger agent as a tag in every span. For example, any baggage tag that has a key starting with a double underscore, as in “__tenant-id”, will be automatically promoted to be a span tag in each (sub) Service. In order to self-promote, the client libraries must be modified to create the span tag from the baggage tag when the opentracing-span is being converted to a thrift-span. We modified and tested the go, java, node.js and python client libraries. Security and an API to hide the implementation could easily be added.
The Jaeger Agent was modified to hold a map of uber tchannel objects using a tenant name as the key. The Jaeger Agent will "route" the spans to different collector/DB's based on the value of a specified span tag. The configuration was modified to support this functionality. Example:
"--collector.host-port=default@192.168.99.100:30418,tenant1@192.168.99.101:30021,tenant2@192.168.99.101:30063"
"--collector.route-tag=__tenant-id"