The principle “build once, deploy anywhere” is a fundamental part of Continuous Delivery and Deployment. If your underlying architecture is not built to support this behavior, you’re creating quite a few headaches for yourself and your Continuous Integration/Continuous Delivery/Deployment (CI/CD) pipeline. By following a few guidelines, you can ensure that the Artifact (the built code) you create is the same throughout each environment. In this article, we walk through a CI/CD pipeline deploying to AWS Elastic Container Service for Kubernetes (EKS) that simplifies the deployment process and guarantees the “build once, deploy anywhere” principle is followed.
The first step is to guarantee that your code is architected for environmental differences to be provided at run time, rather than hard-coded with the source. For .Net Core, this means taking advantage of the revamped configuration that enables appSettings and environmental variables to control how you launch your application. Here are some guidelines for configuration:
- Provide global, environment specific information as Environment variables. This means that most settings providing connectivity information can be moved to Environment variables, supported through the Properties\launchSettings.json in .Net core. A special environment variable can be set here for development: ASPNETCORE_ENVIRONMENT. This variable controls which appSettings.json file is loaded during run time and provides programmatic access so that different logic can be applied based on environment.
- Move configuration into appSettings. The appSettings files can contain configuration that is specific to the role the code will be performing. The appSettings is like web.config for previous versions of ASP.Net and can be used for overall application configuration.
- Create a DockerFile and Kubernetes deployment YAML file that can be transformed with parameters during the release pipeline.
When building, configure a single build that will compile the source and generate any environment specific artifacts that may be necessary into the pipeline. For Azure DevOps Build & Release, this means creating a build with a Continuous Integration trigger. The output should be a single build Artifact. This guarantees the “build once” part of the principle and sets up the rest of the pipeline.
Since you’re focusing on a Kubernetes pipeline, a central piece is going to be the Container image. Containers provide a consistent run-time for the application to be hosted in, guaranteeing consistent behavior across every environment we deploy to. For the Release pipeline in Azure DevOps, you can utilize some built-in tasks from Docker and AWS to build and push your Docker image.
In this case, you are pushing your image to an internal container repository using AWS Elastic Container Registry (ECR). This ensures our assets are protected from external access without having to manage and create your own Docker repositories.
Now that your Container image is created from the build artifact, you need a mechanism to host the container and create environment specific information. As mentioned, the hosting environment for this pipeline is EKS. Using Kubernetes (K8s), an open-source, cloud-provider agnostic system, you can automate deployment, scaling, and management of containerized applications. EKS gives you a managed K8s cluster in AWS across multiple Availability Zones to ensure high availability. Using K8s through EKS, you can add environment specific steps in your pipeline to configure and deploy your container image to each environment.
In each environmental step, you are transforming your deployment YAML file with environmental settings, pointing to your container and the special ASPNETCORE_ENVIRONMENT variable.
Lastly, you need to deploy this YAML to your EKS cluster. The integration of EKS with Azure DevOps is a bit lacking currently. However, you can easily drop down to the lower level AWS Shell Script task and take advantage of the excellent AWS Command Line Interface (awscli) and the Kubernetes Command Line Tool (kubectl). Your custom deploy script can run with AWS IAM credentials and perform command line operations in a consistent manner to connect to EKS and deploy our container image.
Now that your containerized application is configured for per environment deployments, you can ensure the “build once, deploy anywhere” principle is adhered to. to discuss how Azure DevOps, Docker, and Kubernetes can help improve your deployment process and ensure a consistent delivery pipeline.