Microservices for Java Developers: Continuous Integration and Continuous Delivery
1. Introduction
If we look back at the number of challenges associated with the microservice architecture, ensuring that every single microservice is able to speak the right language with each of its peer is probably one of the most difficult ones. We have talked a lot about testing lately but there is always opportunity for bugs to sneak in. Maybe it is last minute changes in the contracts? Or maybe it is that security requirements have been hardened? And what about unintentionally pushing the improper configuration?
In order to address these concerns, along with many others, we are going to have a conversation about the practices of continuous integration and continuous delivery. So what are these practices, how they are helpful and what are the differences between them?
Table Of Contents
The continuous integration paradigm advocates for pushing your changes to the mainstream source repository as often as possible paired with running the complete build and executing the suite of the automated tests and checks. The goal here is to keep the builds rolling and tests passing all the time, avoiding the scenario when everyone tries to merge the changes at the last moment, dragging the project into the integration hell.
The continuous delivery practice lifts the continuous integration to the next level by bringing in the release process automation and ensuring that the projects are ready to be released at any time. Surprisingly, not many organizations understand the importance of continuous delivery, but this practice is an absolutely necessary prerequisite in order to follow the principles of the microservice architecture.
Fairly speaking, continuous delivery is not the end of it. The continuous deployment process closes the loop by introducing the support of the automated release deployments, right into the live system. The presence of the continuous deployment is an indicator of mature development organization.
2. Jenkins
For many, the term continuous integration immediately rings Jenkins to mind. Indeed, it is probably one of the most widely deployed continuous integration (and continuous delivery) platforms, particularly in the JVM ecosystem.
Jenkins is a self-contained, open source automation server which can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software. – https://jenkins.io/doc/
Jenkins has an interesting story which essentially spawns two radically different camps: the ones who hate it and the ones who love it. Luckily, the release of Jenkins version 2.0 a few years ago was a true game changer which sprawled out the tsunami of innovations.
To illustrate the power of Jenkins, let us take a look at how JCG Car Rentals platform is using pipelines to continuously build and test its microservice projects.
The true gems of Jenkins are its extensibility and enormous amount of the community plugins available. As you may remember, all JCG Car Rentals projects integrate with SpotBugs for static code analysis and OWASP dependency-check for catching the vulnerable dependencies. Unsurprisingly, Jenkins has plugins for both, which are easily injectable into the build pipeline, like the one Customer Service has.
pipeline { agent any options { disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr:'5')) } triggers { pollSCM('H/15 * * * *') } tools { jdk "jdk-8u202" } stages { stage('Cleanup before build') { steps { cleanWs() } } stage('Checkout from SCM') { steps { checkout scm } } stage('Build') { steps { withMaven(maven: 'mvn-3.6.0') { sh "mvn clean package" } } } stage('Spotbugs Check') { steps { withMaven(maven: 'mvn-3.6.0') { sh "mvn spotbugs:spotbugs" } script { def spotbugs = scanForIssues tool: [$class: 'SpotBugs'], pattern: '**/target/spotbugsXml.xml' publishIssues issues:[spotbugs] } } } stage('OWASP Dependency Check') { steps { dependencyCheckAnalyzer datadir: '', hintsFile: '', includeCsvReports: false, includeHtmlReports: true, includeJsonReports: false, includeVulnReports: false, isAutoupdateDisabled: false, outdir: '', scanpath: '', skipOnScmChange: false, skipOnUpstreamChange: false, suppressionFile: '', zipExtensions: '' dependencyCheckPublisher canComputeNew: false, defaultEncoding: '', healthy: '', pattern: '', unHealthy: '' } } } post { always { archiveArtifacts artifacts: 'target/*.jar', fingerprint: true archiveArtifacts artifacts: '**/dependency-check-report.xml', onlyIfSuccessful: true archiveArtifacts artifacts: '**/spotbugsXml.xml', onlyIfSuccessful: true } } }
Once the pipeline job is triggered on Jenkins, the SpotBugs and OWASP dependency-check reports are published as part of the build results.
It is critically important to stay disciplined and to follow the principles of the continuous integration. The builds should be kept healthy and passing all the time.
There are a lot of things to say about Jenkins, particularly with respect to its integration with Docker but let us better glance over other options.
3. SonarQube
We have talked about SonarQube along previous parts of the tutorial. To be fair, it does not fit into continuous integration or continuous delivery bucket but rather forms a complementary one, a continuous code quality inspection.
SonarQube is an open source platform to perform automatic reviews with static analysis of code to detect bugs, code smells and security vulnerabilities on 25+ programming languages including Java, C#, JavaScript, TypeScript, C/C++, COBOL and more. … – https://www.sonarqube.org/about/
The results of the SonarQube code qualify inspections are of immense value. To get a glimpse of them, let us take a look at the Customer Service code quality dashboard.
As you may see, there is some intersection with the reports generated by SpotBugs and OWASP dependency-check, however SonarQube checks are much broader in scope. But how hard it is to make SonarQube a part of your continuous integration pipelines? As easy as it could possibly get since SonarQube has outstanding integrations with Apache Maven, Gradle and even Jenkins.
With over 25 programming languages supported, SonarQube would certainly help you to raise the bar of code quality and maintainability across a whole microservices fleet (even if there may be no out of the box integration with the continuous integration platform of your choice).
4. Bazel
Bazel came out of Google as a flavor of the tool used to build company’s server software internally. It is not designated to serve as continuous integration backbone but the build tool behind it.
Bazel is an open-source build and test tool similar to Make, Maven, and Gradle. It uses a human-readable, high-level build language. Bazel supports projects in multiple languages and builds outputs for multiple platforms. Bazel supports large codebases across multiple repositories, and large numbers of users. – https://docs.bazel.build/versions/master/bazel-overview.html
What is interesting about Bazel is its focus on faster builds (advanced local and distributed caching, optimized dependency analysis and parallel execution), scalability (handles codebases of any size, across many repositories or a huge monorepo) and support of the multiple languages (Java included). In the world of polyglot microservices, having the same build tooling experience may be quite advantageous.
5. Buildbot
In essence, Buildbot is a job scheduling system which supports distributed, parallel execution of jobs across multiple platforms, flexible integration with different source control systems and extensive job status reporting.
Buildbot is an open-source framework for automating software build, test, and release processes. – https://buildbot.net/
Buildbot fits well to serve the needs of the mixed language applications (like polyglot microservices). It is written in Python and extensively relies on Python scripts for configuration tasks.
6. Concourse CI
Concourse takes a generalized approach to the automation which makes it a good fit for backing continuous integration and continuous delivery, in particular.
Concourse is an open-source continuous thing-doer. – https://concourse-ci.org/
Everything in Concourse runs in a container, it is very easy to get started with and its core design principles are encouraging to use the declarative pipelines (which, frankly speaking, are quite different from Jenkins or GoCD ones). For example, the basic pipeline for the Customer Service may look like that:
resources: - name: customer-service type: git source: uri: branch: master jobs: - name: build plan: - get: customer-service trigger: true - task: compile config: platform: linux image_resource: type: docker-image source: repository: maven inputs: - name: customer-service outputs: - name: build caches: - path: customer-service/.m2 run: path: sh args: - -c - mvn -f customer-service/pom.xml package -Dmaven.repo.local=customer-service/.m2
Also, Concourse comes with command line tooling and pretty basic web UI which is nonetheless helpful in visualizing your pipelines, like at the picture below.
7. Gitlab
Gitlab is a full-fledged open source end-to-end software development platform with built-in version control, issue tracking, code review, continuous integration and continuous delivery.
GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security. – https://about.gitlab.com/
If you are looking for all-in-one solution, which could be either self-hosted or managed in the cloud, Gitlab is certainly an option to consider. Let us take a look at the Customer Service project development in case of Gitlab being chosen.
The continuous integration and continuous delivery pipelines are pretty extensible and by default include at least 3 stages: build, test and code quality.
It is worth noting that Gitlab is being used by quite a large number of companies and its popularity and adoption are steadily growing.
8. GoCD
The next subject we are going to talk about, GoCD, came out of ThoughtWorks, the organization widely known for employing the world-class experts in mostly every area of software development.
GoCD is an open source build and release tool from ThoughtWorks. GoCD supports modern infrastructure and helps enterprise businesses get software delivered faster, safer, and more reliably. – https://www.gocd.org/
Unsurprisingly, pipelines are central piece in GoCD as well. They serve as the representation of a workflow or a part of a workflow. The web UI GoCD comes with is quite intuitive, simple and easy to use. The Customer Service pipeline in the image below is a good demonstration of that.
The pipeline itself may include an arbitrary amount of stages, for example the Customer Service’s one has two stages configured, Build and Test. The dedicated view shows off the execution of the each stage in great details.
The GoCD pipelines are very generic and not biased towards any programming language or development platform, as such addressing the needs of the polyglot microservice projects.
9. CircleCI
If the self-hosted (or to say it differently, on-premise) solutions are not aligned with your plans, there are quite a few SaaS offerings around. The CircleCI is one of the popular choices.
CircleCI’s continuous integration and delivery platform makes it easy for teams of all sizes to rapidly build and release quality software at scale. Build for Linux, macOS, and Android, in the cloud or behind your firewall. – https://circleci.com/
Besides being a great product, one of the reasons the CircleCI is included in our list is the presence of the free tier to let you get started quickly.
10. TravisCI
TravisCI falls into the same bucket of the SaaS offerings as CircleCI but with the one important difference – it is always free for open source projects.
Travis CI is a hosted continuous integration and deployment system. – https://github.com/travis-ci/travis-ci
TravisCI is probably the most popular continuous integration service used to build and test software projects hosted on GitHub. On the not so bright side, the future of TravisCI is unclear since it was acquired in January 2019 by private equity firm and reportedly the original development team was let go.
11. CodeShip
CodeShip is yet another SaaS for doing continuous integration and continuous delivery, acquired by CloudBees recently, which also has a free plan available.
Codeship is a fast and secure hosted Continuous Integration service that scales with your needs. It supports GitHub, Bitbucket, and Gitlab projects. – https://cms.codeship.com/
One of the distinguishing advantages of the CodeShip is that it takes literally no (or little) time to set it up and get going.
12. Spinnaker
Most of the options we discussed so far are trying to cover the continuous integration and continuous delivery under the same umbrella. On the other hand, the Spinnaker, originally created at Netflix, is focusing purely on continuous delivery side of things.
Spinnaker is an open source, multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence. – https://www.spinnaker.io/
It is truly unique solution which combines a flexible continuous delivery pipeline management with integrations to the leading cloud providers.
13. Cloud
Hosting your own continuous integration and continuous delivery infrastructure might be far beyond one’s purse. The SaaS offerings we have talked about could significantly speed up the on-boarding and lower the upfront costs, at least when you just starting. However, if you are in the cloud (which is more than likely these days), it makes a lot of sense to benefit from the offerings the cloud provider has for you. Let us take a look at what leaders in the cloud computing came up with.
The first one in our list is for sure AWS, which has two offerings related to continuous integration and continuous delivery, AWS CodeBuild and AWS CodePipeline respectively.
AWS CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces software packages that are ready to deploy. With CodeBuild, you don’t need to provision, manage, and scale your own build servers. … – https://aws.amazon.com/codebuild/
AWS CodePipeline is a fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates. CodePipeline automates the build, test, and deploy phases of your release process every time there is a code change, based on the release model you define. … – https://aws.amazon.com/codepipeline/
Moving on to the Google Cloud, we are going to stumble upon Cloud Build offering, the backbone of the Google Cloud continuous integration efforts.
Cloud Build lets you build software quickly across all languages. Get complete control over defining custom workflows for building, testing, and deploying across multiple environments … – https://cloud.google.com/cloud-build/
The Microsoft Azure took another route and started with the managed Jenkins offering. But shortly after GitHub acquisition, the Azure DevOps has emerged, the completely new offering which spawns across continuous integration, continuous delivery and continuous deployment.
Azure DevOps Services provides development collaboration tools including high-performance pipelines, free private Git repositories, configurable Kanban boards, and extensive automated and continuous testing capabilities. …. – https://docs.microsoft.com/en-ca/azure/devops/index?view=azure-devops
14. Cloud Native
Before wrapping up, it would be great to look on how existing continuous integration and continuous delivery solutions adapt to the constantly changing infrastructural and operational landscape. There is a lot of innovation happening in this area, let us just look through a few interesting developments.
To begin with, Jenkins has recently announced the new subproject, Jenkins X, to specifically target the Kubernetes-based deployments. I think this trend is going to continue and other players are going to catch up since the popularity of Kubernetes is skyrocketing.
The spread of the serverless execution model put the continuous integration and continuous delivery into the new perspective. In this regards, it worth to note LambCI, a continuous integration system built on AWS Lambda. It is very likely that we are going to see more options emerging on this front.
15. Conclusions
The importance of the continuous integration poses no questions these days. From the other side, the continuous delivery and continuous deployment are falling behind but they are undoubtedly the integral part of the microservice principles.
Along this section of the tutorial, we have glanced over quite a number of options but obviously there are many others in the wild. The emphasis is not on the particular solution though but the practices themselves. Since you embarked yourself on the microservices journey, it is also your responsibility to make it a smooth one.
16. What’s next
In the next section of the tutorial we are going to dig more into operational concerns associated with the microservice architecture and talk about configuration management, service discovery and load balancing.