Implementing a CI/CD workflow for application development is becoming increasingly popular. At the same time, however, scaling and optimizing CI/CD poses a challenge.
Today we are going to discuss what this challenge is and explore exactly how we can scale and optimize CI/CD. So, follow along!
Nowadays, application development is usually done in teams consisting of several developers. Each person or team has its role in the project by advancing on their dedicated part.
We then find ourselves at the end of the project with several pieces of code to compile. Depending on everyone’s working methods, much time can be wasted managing this integration.
CI/CD, Continuous Integration, and Continuous Delivery/Deployment is a solution to this problem and ensures updates are released without unnecessary delays and conflicts. Let’s understand this process.
CI or Continuous Integration groups together processes aimed at continuously publishing code changes and additions to a shared branch of the project. It allows the code to be tested and improvements and changes to be made in real-time. The goal is to test each element through the creation of tests.
This permanent measure makes it possible not to check everything in one block at the end and to avoid working on too many elements simultaneously. Performing unit tests is, therefore, very useful to ensure this. Thus, it is easier to detect errors by ensuring that the code compiles well and does not create regressions.
Continuous delivery or CD brings together continuous integration and testing that can be bundled into containers and put into production. That is, it gathers these codes and tests performed and puts them into production via automation.
Even if it requires human action, it becomes automated by putting everything that has been done “on the air” in an integrated and complete way. Concretely, with the continuous distribution, our application is developed so that it can be put into production, no matter when.
While the concepts of continuous delivery and continuous deployment are similar, there are differences. If their objective is the same, that is to say, the deployment of the application in production, the means to achieve it differ. What separates continuous delivery from continuous deployment is the release.
Indeed, continuous deployment makes it possible to directly deploy each modification that crosses the different stages of our pipeline. While in continuous delivery, a human validation step is necessary for the deployment to take place.
When the number of microservices increases, it becomes almost inevitable to scale your CI/CD. The increased number of microservices results in different pipelines connected to a single git repository which increases the load of the CI server and lowers the performance.
To scale CI/CD, it is necessary to create a standardized and automated development pipeline for all teams and, from there, ensure the quality of individual developer deliveries and team deliveries. It also makes the management of the pipeline easy.
Scaling can be accomplished by defining a CI process for executing unit tests and validating the quality of the delivered code.
Followed by a CD process for building the images and deploying them in the environments continuously and finally defining a process for building the images and deploying them in the production environment.
Steps to Scale CI/CD
The first step is to align the pipeline with the architects, involving team leaders. It follows the mapping of the Git branches to the environments (develop -> development and master -> [homologation and production]). It then comes the firing of the CI Job at each Pull Request and the CD Job at each change in the mapped branches.
A Job stream can be created for both CI and CD to be followed.
The CI Job Flow develops in 7 steps:
Check out the Pull Request source and destination branch ;
Checks if the merge does not have conflicts that need manual resolution;
Run unit tests;
Build the package to verify the integrity and that the code is compilable;
Trigger code quality validation;
Increment and commit the project version to the source branch;
Notify Pull Request Git repository of success or failure via Webhook or Rest API call (Git Repository).
The CD job flow follows the following path:
The notified branch is checked out.
The artifact is built using the specific build tool of the project being worked on.
After the artifact comes, the library projects are sent to the Nexus for storage of the artifact, and the flow is finished.
The following actions are carried out:
Step 1: A Docker image is created for the generated artifact, applying the artifact version to the Docker image.
Step 2: The image is uploaded to the Docker registry.
Step 3: Deployment through image rollout via Kubernetes.
For application Projects that are in an approval/production environment, follow steps 1 and 2 above and then the following:
Deploy through image rollout via Kubernetes in the approval environment;
The job takes a break to wait for the rollout to be approved for production;
If approved, the image that is being approved is promoted for production;
Otherwise, it rolls back the image in approval.
CI/CD improves the application development cycle and solves the problem caused by integrating new code and increasing the frequency of delivery.
Following are how you can further optimize the use of CI/CD:
Prioritize fixing a corrupted build
When a build breaks down, fixing it should be the team’s priority. If the build cannot be fixed in minutes, the team must decide whether to remove the code or disable the feature flag.
The idea behind fixing a broken build is that the build will always produce working code that can be released.
Small frequent deployments
Generally, the application’s stability is at risk whenever a deployment happens. So we tend to distance deployments from one another. This approach’s problem is that we accumulate too many changes. One of these changes could go wrong, forcing us to roll back the others that were working.
Apply the strangler pattern and break complicated changes into small and simple ones. If you deploy more frequently and work in small batches, the risk of deploying is lower.
Automate QA tests for risk mitigation
We have all probably been involved in the “worked on my local machine” scenario because local development environments often differ. There can be many different things between your local environment and where you go into production. You can optimize CI/CD by automating Quality Assurance (QA) tasks such as browser testing, mitigating the risk of a bug reaching the live application.
Trust automated tests
To validate when a developer integrates new code, CI relies on an automated and reliable test suite. If you need to compile code, the first test is that it compiles. Then you can add as many tests as you deem critical.
How many tests should be included? To determine this, remember that CI’s goal is to provide feedback as quickly as possible. If a developer has to wait an hour to get feedback, it won’t work. You will always miss things, but when you spot a bug in production, create a test case and include it in the CI loop.
Always consider the security
Consider the security of a CI/CD tool as it integrates into existing configurations or environments. CI/CD requires that all security testing tools be called programmatically and their results aggregated in one place. Look for tools that have APIs for automated encryption audits.
Benefits of Scaling and Optimizing CI/CD
Apart from increasing the efficiency of development teams, scaling and optimizing CI/CD have other benefits too, some of which are:
Development hours are typically billable, but what about time spent manually deploying code or files? Automating large parts of your flow will save time for billable work, something everyone can appreciate. Automated testing also allows you to fail sooner rather than finding errors in QA or production or worse, the customer finds them. More bugs fixed in the same amount of time is a clear win.
Delivery with fewer bugs and less risk
You catch bugs much earlier in the development process by releasing minor changes more frequently. When you implement automated tests at all stages of development, you don’t risk moving the failing code to the next stage, and it’s easier to roll back minor changes when needed.
Respond to market conditions faster
Market conditions change constantly. Suppose you discover that a new product is losing revenue or that more customers access your site from smartphones than laptops. In that case, it’s much easier to make a quick change if you have optimized continuous delivery.
If you have optimized CI/CD, which means you have a robust test suite, your confidence in not submitting a bug increases greatly. If you are transparent with your process and educate the rest of your team and customers, their trust in you as a development team also increases.
CI/CD makes your integrations and deliveries faster. However, it is important to scale and optimize it to avoid the process becoming counterproductive due to increasing complexity.