2

We are planning to move into Microservices. Currently on the design talks stage. Thinking of how to versioning the releases?

Let's say we will start with 10 microservices. We want to develop them and deploy separately. Possibly every microservice in different point in time.

Then, when tested, each of them will become release candidate. The product owner will be able to pick few of them, charge the customer and click the button to apply these microservices to the customer.

The question is now, how the product owner will know how to name the version which he is trying to sell for the client?

Detailed scenario: Assuming we have a ten microservices: M1, M2, ..., M10. Product owner sold for two customer packages in following configuration: Customer 1: M1 & M5 Customer 2: M1 & M3

Then he won't say 'Hey customer, here you have 3.4 version of the app'. He will be only able to define version of the application by applied packages. So in this case 'Hey customer, here you have the app. It contains service M1 (in version 1), and service M5 (in version 1)'.

I would like to know how to represent this kind of releases as one number, not a list of separate number for every microservice sold?

7
  • 1
    Welcome to the "everything is harder" part of going with microservices. To be honest, how you version really depends on your use case. For example, the easy case is a well known site like Facebook or Netflix only has one fully deployed version. However, in multi-tenancy situations where one client has a base set of services + some custom ones, and another client has the base set + other custom ones, that can be difficult to manage. You could choose to version each service in isolation, which can work. It just makes it hard to understand what services are compatible with others. – Berin Loritsch Sep 3 '19 at 20:54
  • I'm confused by this question. I think you might be using 'version' in a non-standard way: to identify a set of components. Typically 'version' in this context refers to the version of the software i.e. changes made to the way it works. – JimmyJames Sep 3 '19 at 20:55
  • @BerinLoritsch Thanks for greetings from this harder side :) There is an option to go with one deployed version like mentioned Facebook (don't know whether Business will permit). Then all latest versions of the microservices related to the product could be deployed to all the customers. Then chargeable functionalities can be switched on by flags. Do you think this will work well? – codeedward Sep 3 '19 at 21:51
  • @JimmyJames Yeah, you can say Release Id instead of Release Version. So release id 2019.1 which contains M1(v1), M2(v5), M3(v1) etc. – codeedward Sep 3 '19 at 21:54
  • I think the term 'bundle' is appropriate here. You are asking about how to name/version 'bundles'. – JimmyJames Sep 4 '19 at 14:05
2

This is a common problem in configuration management of complex systems, and isn't necessarily unique to software. Even before microservices, I've seen this in complex electro-mechanical-software systems where various components have versions or revisions and different customers may have different physical products with different revisions of hardware components.

Typically, this is handled by having multiple version identifiers - one at the system level and one at the component level. You can decompose components as much as you want or need, as well. Any revision to a lower level propagates up the chain. Normally, in the context of hardware, you'd always get the most recent revision of everything, but that's often because the changes were made to handle obsolesce of parts or improve ease of manufacturing and/or maintenance and it's not feasible to build a new product with the old configuration anymore. With software, it's easier to mix-and-match different versions and build them.

The important thing to keep track of is an association between the customer and the revision of all of the microservices that they have. What you call that system combination doesn't necessarily matter. In the hardware world, this responsibility is on the vendor - whoever makes the system is responsible for being able to associate a serial number with the engineering design documentation of every constituent part. If a customer has multiple deployments, then you have to consider that as well.

In this scenario, you don't necessarily need to version your microservices and the system in the same way. I'd tend to favor Semantic Versioning for the services - it's well defined for APIs and you can define a sane format for user interfaces / user facing applications as well. You can use letters, numbers, GUIDs, hashes, or some other unique identifier for the system combination. This may even allow you to keep track of customers with the same configuration deployed.

As far as displaying versions, you should probably consider having a way to get the version of each service somehow. This could be through the user interface, something recorded in the logs, or accessible through a common endpoint that all configurations share.

All of this said, it's probably going to be painful if you need to manage configurations in this way. No matter what system you use, if you have different customers with different configurations in different environments, you need to be able to track the impact of a given change to all customers and understand that a non-breaking change to one customer may be a breaking change to someone else. It's a non trivial problem.

You can always read more. Here are just a few Wikipedia articles on relevant topics to get started:

2
  • I am trying to think of alternatives to reduce the pain involved with managing configurations of the microservices. What would you say about releasing all the latest versions of the microservices to every customer every time. Then there wouldn't be any need for managing different versions. Then let business option to 'switch on' chargeable products by some Admin GUI panel? Still some customers would have different switches on/off, but at least all would be on the same version of the code. – codeedward Sep 5 '19 at 17:14
  • @codeedward I believe that would be far less complex than deploying different versions to different people. There's still complexity in configuration options, but you can probably automate testing. I believe it's also more consistent with microservices - you can update and deploy a new microservice version when it's ready (and schedule deployments when it's appropriate for your customers to receive them). You can even consider a configuration endpoint to pull down and generate reports on current configurations, if you wanted to. – Thomas Owens Sep 5 '19 at 17:22
0

If they're separate products, they should probably just get their own versions. In your examples, you could say "Hey customer 1, you have M1 v3.4 and M5 v3.4" and "Hey customer 2, you have M1 v3.4 and M3 v3.3 -- you should probably update M3 to latest".

For simplicity, you might want to keep them all roughly the same, but that would be more of a cosmetic decision. The main thing is the version should identify the source code it came from, and should be unique. Some services just use a combination of the auto-incrementing build number and/or git commit hash, so they can just say something like "M1 #fe45ce2 build 12043".

Why version?

Knowing why version numbers are important helps to figure out what they need to be. Commonly:

  • Be able to communicate what's running (between customer/dev/PM/support/etc)
  • Be able to tell if there's an update or not (and how far behind you are)
  • Know if a newly discovered bug is really new or already known/fixed
  • Figure out what revision of code (and/or build) a piece of running software is from

Dependencies

Here's one of the things with microservices vs monoliths: each microservice is effectively its own, independent product. If they are talking to each other, you now have to think about version cross-compatibility (forwards and backwards) between all the independent services.

Does M1 v3.4 work with M3 v3.3? Does M3 v3.5 work with M1 v3.1?

You don't have to be forwards- or backwards-compatible (and certainly not for all versions) but then you introduce other operational challenges, like if someone updates M1 then they have to update M3 and until they do, one or both services will be broken -- and you probably want to think about how you present "broken" to end users (eg: do they see an HTTP 500 error page with a stack trace or an "under maintenance" page?).

Single version number

If you have a single repository and a single build that contains all your services, it's pretty easy to version that in a consistent way (whatever you choose). You still have to figure out how you handle dependencies and cross-compatibility, so long as it's possible to install/upgrade independently.

If you have independent repositories, but a single build, you can use a build number. If you have a single repository but independent builds, you can use a source code revision.

If everything is independent, there's really no way to enforce consistency -- it would have to be manual and pretty easy to mess it up (which means it will eventually be messed up).

If you really want a consistent version, have everything in one repository/build, and want customers to be only on one version so you don't have to worry about cross-compatibility, then microservices might not be the right architecture choice for your situation, so you'll need to reconsider what you're trying to achieve and what trade-offs you want to compromise on.

1
  • Exactly, having one build will mean that I will have to build all the microservices together. But from what I read one of the benefits of having microservices is that you can build them and deploy independently. Meaning it's fast and less risky. Answering your question all the microservices are components of the Product. So product has 10 microservices. They are not separate products. Therefore there is a need to install few of them to update Product at the same time. – codeedward Sep 3 '19 at 22:00
0

The answer depends on how you test your changes, the CI/CD design.

We have been following the strategy of treating the docker image tags of all microservices at an event as a single release. This release can be installed into a cluster by some tool, though effectively only the changed docker images get updated.

The event referred above is tied to the CI/CD flow.

A merge to master (pre-merge) could trigger a CI/CD event that could trigger a Docker image build and version upgrade of a particular MS, and a test release created out of the updated MS and rest of the unaffected MS. This test release could be applied and tested in staging.

Similarly, the event could be a post-merge event, in which case the release could be candidate for deployment to production after tests. We can call this pattern mono-releases. This is what we have been following for about two years and I can tell that this gives a lot more clarity and sanity for all, especially program management who can think in conventional releases.

I am explicitly not mentioning here about versioning the interface or API exposed by each MS. For MS to work properly you need to ensure that interfaces are backward compatible, and you should rely on strongly typed and versioned interfaces like GRPC instead of interfaces and types by conventions which can be easily broken. REST was never meant as an interface contract for a complex service.

There is a problem with this versioning of a set of MS. What if you have thousands of microservices. In this case, the rate of change will be so high that it will be difficult for a CI/CD system to keep up with the mono-release pattern.

Basically, by the time you tag and send it to CD machine for a test, there will be a hundred other MS changed in master, and you need to batch a snapshot from the master, where the minimum batch time will be equal to your CI.CD time.Basically you have to do this serially then as you are snapshotting a release in time and testing it and promoting it.

What about each MS going through its own CI/CD cycle, that is each or a common CD environment is updated by the latest published docker image version of MS in production registry and your MS from dev registry tests against this and if it passes then it is published to say production registry. This will be like a micro-release pattern. Instead of each MS you could group similar MS together too..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.