Process Activator on Kubernetes

4/27/2021

We have a microservices/ish archictecture we currently on a VM. Each of our applications are deployed as DLLs with no executable. To run them, we spawn a new instance of our activator, passing the path of the application as an argument. The process activator injects behaviors on the application via DI, such as proxies and service discovery logic.

This has the benefit that the applications and the process activator can be developed, managed and deployed independently of one another. If we have an update for the activator, we only need to deploy it and restart all applications for our changes to take effect; No need to re-deploy an application, much less to rebuild it.

As we are now developing a plan to migrate our archictecture to Kubernetes, however, we've hit a roadblock because of this design. We haven't been able to find a way to replicate this. We've thought of doing it by simply deploying the two together and setting the activator as the entrypoint; However, that would mean that anytime we update the activator, all applications' images would have to be updated as well, which completely defeats the purpose of this design.

We've also thought of deploying them as two different containers and somehow making the activator read the contents of the application container and then load its DLLs, but we don't know if it's possible for a container to read the contents of another.

In the end, is there a way to make this design work in Kubernetes?

-- andre_ss6
kubernetes

1 Answer

4/28/2021

If the design requires the following:

  • Inject files into the main container to change its behaviour

Then a viable choise is to use init containers. Init containers can perform operations before the main container (or containers) starts, for example they could copy some files for the main container to use.

You could have this activator as the main container and all the various apps being a different init container which contains the DLLs of that app.

When an init container starts, it copies the DLLs of that app on an ephemeral volume (aka emptyDir) to make them available to the main container. Then the activator container starts and find the DLLs at a path and can do whatever it wants with them.

This way:

  • If you need to update the activator, you need to update the main container image (bump its tag) and then update the definitions of all the Deployments / StatefulSets to use the new image.
  • If you need to update one of the apps, you need to update its single init container image (bump its tag) and then update the definition of the Deployment / StatefulSet of that particular app.

This strategy works perfectly fine (I think) if you are ok with the idea that you'll still need to define all the apps in the cluster. If you have 3 apps, A, B and C, you'll need to define 3 Deployments (or StatefulSets if the apps are stateful for some reasons) which uses the right init containers.

If the applications are mostly equal and only few things changes.. like only the DLLs to inject to the activator, you could think of using HELM to define your resources on the cluster, as it makes you able to template the resources and personalize them with very little overhead.


Some documentation:

Init Containers: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

Example of making a copy of files between Init container and Main container: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-initialization/

HELM: https://helm.sh/docs/

-- AndD
Source: StackOverflow