HNHacker News
TopNewBestAskShowJobs

dhinus

10 karma · joined December 18, 2015

Software Engineer

[ my public key: https://keybase.io/dhinus; my proof: https://keybase.io/dhinus/sigs/ez4_bX61Fxy-dqe335SMPyoiL0T8WHBir96czuVuh28 ]

submissionscomments
dhinus··on Ask HN: How do you keep track of releases/deployments of dozens micro-services?
For ease of deployment and to solve the problem of "what version of service_b is compatible with version x of service_a"?

IMHO this makes sense if the microservices are developed by the same team. If we're talking about services developed and managed by different teams... maybe it's not a good idea.

dhinus··on Ask HN: How do you keep track of releases/deployments of dozens micro-services?
Because we want to make sure that in the Docker registry we have _all_ services tagged with the latest commit.

For example you might have a Git history like this:

* 89abcde Fix bug in service_b

* 1234567 Initial commit including service_a and service_b

When 89abcde is pushed, the CI rebuilds both service_a and service_b so we can simply "deploy 89abcde" and you always have only one hash for all services, that is also nicely the same hash of the corresponding Git commit.

The trick to avoid rebuilding perfectly working services is to use Docker layer caching so that when you build service_a (that hasn't changed) Docker skips all steps and simply adds the new tag to the _existing_ Docker image. The second build for service_a should take about 1 second.

In our Docker registry we end up with:

service_a:1234567

service_a:89abcde

service_b:1234567

service_b:89abcde

But the two service_a Docker images are _the same image_, with two different tags.

dhinus··on Ask HN: How do you keep track of releases/deployments of dozens micro-services?
Depends on many factors... It can vary from 5 to 30 minutes, from the moment someone presses "merge" on a pull request and the moment that change is live on a test environment. The average is probably around 10-15 minutes.

The builds for all services happen in parallel, so the longest one determines the total time. Big Scala services take much longer than small React frontends. We cache both Maven and NPM modules from previous builds.

Ideally, if the pull request only modified a React component and didn't touch any Scala file, no Scala build is triggered because Docker finds a cached layer and skips the "sbt compile" step. To be honest, we are still working to make sure this always happens, we still trigger unnecessary sbt compiles because the Docker cache is not used correctly.

dhinus··on Ask HN: How do you keep track of releases/deployments of dozens micro-services?
Our apps are made by 5-15 (micro)services. I'm not sure if this approach would scale to hundreds of services managed by different teams.

We store the source code for all services in subfolders of the same monorepo (one repo <-> one app). Whenever a change in any service is merged to master, the CI rebuilds _all_ the services and pushes new Docker images to our Docker registry. Thanks to Docker layers, if the source code for a service hasn't changed, the build for that service is super-quick, it just adds a new Docker tag to the _existing_ Docker image.

Then we use the Git commit hash to deploy _all_ services to the desired environment. Again, thanks to Docker layers, containers that haven't changed from the previous tag are recreated instantly because they are cached.

From the CI you can check the latest commit hash that was deployed to any environment, and you can use that commit hash to reproduce that environment locally.

Things that I like:

- the Git commit hash is the single thing you need to know to describe a deployment, and it maps nicely to the state of the codebase at that Git commit.

Things that do not always work:

- if you don't write the Dockerfile in the right way, you end up rebuilding services that haven't changed --> build time increases

- containers for services that haven't changed get stopped and recreated --> short unnecessary downtime, unless you do blue-green