Multi-Service Workspaces

There are scenarios where you test specific versions of services together. Some examples include:

  • Test a change in a backend service (branch version) from the frontend API or Web UI (baseline version)
  • Test a feature end-to-end that includes changes in multiple services (branch versions)

In such cases, services need to call the correct version of the services they depend on. This can be achieved in one of the following ways:

  1. Statically change the service reference to point to the correct version of the service(s) it depends on
  2. Dynamically route the requests to the correct version of service(s)

Changing Service References

Since you cannot change the baseline versions of Services, you need to fork a Service into a Workspace that you wish to change. You can create Workspaces with multiple forked Services using the Signadot Dashboard. Service references can be updated if they are implemented as environment variables.

Dynamic Routing

If Services have the capability to propagate request headers from incoming to outgoing requests, Signadot can dynamically route requests to specific versions of Services in Workspaces. These headers are automatically set on requests that go through Signadot Preview URLs. Multi-Service Workspaces are implemented using lightweight sidecars or by integrating with a service mesh. Among service meshes, currently Istio is supported.

Header propagation is commonly implemented using distributed tracing libraries. Signadot Workspaces supports the following header formats in HTTP 1/2 and gRPC and the corresponding tracing libraries.

OpenTelemetry Tracing

There are two mechanisms of propagation that are supported from the OpenTelemetry specification: baggage and tracestate. In both of these cases, a key named sd-workspace is used to persist information pertaining to Workspaces.

If you're making use of OpenTelemetry instrumentation in your services, baggage and tracestate headers are propagated automatically.

Jaeger Tracing

A header named uberctx-sd-workspace is expected to be propagated by your services. If you're making use of Jaeger instrumentation in your services, headers in this format are propagated automatically.

Datadog Tracing

A header named ot-baggage-sd-workspace is expected to be propagated by your services. If you're using Datadog's Go language instrumentation libraries, headers in this format are propagated automatically. Support in other languages depends on the library being used and the mode in which it's used.

Custom Instrumentation

If you are not using the above libraries, we recommend that you make use of the baggage header as described in the W3C Baggage Specification. Services would need to propagate this header from each incoming request to any outgoing requests the original handler makes.

The headers that will be set on the entry-point service when using a Signadot preview URL will be in the following format and the application must propagate this header as-is (or with modifications according to the W3C spec) to other services in the system.

baggage: sd-workspace=<workspace-id>

Setting up Dynamic Routing

You would need to opt-in each service to Signadot workspace routing. Routing ensures that requests made to Preview URLs reach the customized versions of Services in Workspaces.

Setting up routing using Signadot sidecar

If your app is not running in Istio, you can enable workspace routing by opting each service into Signadot sidecar injection. This can be done by adding an annotation to the Pod template of each service's Deployment as shown below.

apiVersion: apps/v1
kind: Deployment
metadata:
  ...
spec:
  template:
    metadata:
      annotations:
        # Set the value to "http" or "grpc" based on
        # the protocol that this service uses.
        sidecar.signadot.com/inject: http

In order to add the inject annotation to a particular deployment, you can run the following kubectlcommand.

kubectl -n <namespace> patch deployment <deployment-name> -p '{
   "spec":{
      "template":{
         "metadata":{
            "annotations":{
               "sidecar.signadot.com/inject": "http"
            }
         }
      }
   }
}'

If Signadot is already installed in the cluster, the Pods will have a proxy sidecar container injected, which will perform workspace routing based on metadata in each request.

Setting up routing using Istio

If your app is running in an Istio mesh, the only requirement to enable workspace routing is that each Service has a matching VirtualService in the same namespace. If you don't already have a VirtualService defined, you just need to create a basic one with a default route. For example, here is a basic VirtualService for a Service called my-svc in namespace ns-1:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-svc
  namespace: ns-1
spec:
  hosts:
  - my-svc.ns-1.svc.cluster.local
  http:
  - name: default
    route:
    - destination:
        host: my-svc.ns-1.svc.cluster.local

Signadot will then add and remove routes in the VirtualService as needed to configure workspace routing.


Did this page help you?