In the first part of our article, we described how we use Drone to manage our CI, from code to the final artifact.
It’s now time to move to CD. In this article, we describe how we deploy our code and how we monitor it.
At BOOM we have production and non-production environments. The way we deliver our artifacts, and the outcome of the CI phase, is slightly different for the two. In non-production environments, the deployment (the CD) happens immediately after building the artifact, whereas in production this is done with a separate flow in a different moment. We have in fact a building phase in which we create the production artifact, and a deployment phase in which we perform the artifact installation in production. The building phase is the outcome of the CI performed on the master branch, whereas the deployment phase is a different Drone pipeline that “just” performs the installation. This kind of pipeline makes use of a powerful feature of Drone, promote, and it is a specific event that encompasses another parameter, the target, and it identifies the environment in which the deployment will take place. A very basic example is the following one (details are omitted for sake of simplicity):
But how does the deployment really happen?
Our applications run on different infrastructures, all of them hosted on AWS. In summary we have:
microservices deployed on kubernetes (EKS);
reaction applications deployed on S3 (proxied by kubernetes).
Let’s start with kubernetes.
After the CD flow described in part 1, ECR hosts the image of the microservice, but it is not enough to perform a deployment on kubernetes, we need manifest files to build up the full deployment, environment variables and so on. In order to keep each deployment consistent we decided to use Helm, a standard (together with Kustomize) when it comes to generating reusable templates needed to install microservices on kubernetes. In simple terms, when writing a Helm Chart appropriately, it can be reused to deploy all microservices that need similar kubernetes resources. The specific configuration of created resources is controlled by the values.yaml file provided at deployment time. Interestingly enough, we also use Drone to compile and deploy the charts on our Nexus instance.
Let’s go back to the Drone pipeline in charge of deploying a specific microservice. All we need to do is add a specific stage:
where we provide the helm repository location and the name of the chart to use, together with the values.yaml file that will specialize the chart with the needed configurations. This stage is quite powerful, as it enables the debugging of the deployment flow should any potential issues occur during the deployment. Furthermore, this stage must wait for the full deployment of the release before ending, so that we make sure that everything is up and running correctly on kubernetes.
We embrace the GitOps approach, so we store all values.yaml for any microservice and any environment on a git repository. To make them available to Drone, we simply have to clone this repository before running the deployer stage with something like that:
But where do we instruct the image name and tag needed for the deployment? Again, we can insert an extra stage before the deployer one, to inject variables:
In this example, we use out-of-the-box variables provided by Drone in order to create those values, nothing else should be changed, if we want to work on a different microservice too. Just to clarify, the .env file produced here is read from the deployer stage and used under the hood.
What about react applications?
Deployment of react applications is a bit simpler. All we need to do is move the compiled code to the target S3 bucket.
In order to achieve this we need to add a stage such as the following one:
But hang on, at the beginning we mentioned that we used the “promote” feature of Drone to perform deployment in production, so how can we separate the building from the deployment in this scenario? Quite simply, by compiling the code and deploying an npm package to Nexus during the CI for production:
To deploy the compiled code from there, all we need to do is download the npm package from Nexus, unzip it, and move the code to the target S3 bucket.
To sum up, along with Part 1 of this article this is a clear picture of how we use Drone to manage our CI/CD. What never fails to amaze us is the flexibility of Drone, and the fact that it is capable of handling almost any task requested. Drone can really create any sequence of stages you have in mind and trigger them only when specific events are triggered. And if after all that you still cannot find a plugin to fit your needs...just write your own (more about that later)!