Our Continuous Integration (CI) approach, the topic of this chapter, is one of “zero-infrastructure overhead”. To accomplish this goal, we utilize GitHub Actions to build and push a microservice’s associated container images to Docker Hub for public consumption. The GitHub Actions workflows are defined in the owning repository’s
Our GitOps approach focuses on a single-repository, environment-per-subdirectory model which can be forked and cloned to replicate deployments to other clusters and environments. The reference implementation utilizes Kustomize as its templating technology to utilize the
app-deploy.yaml files, provided by each individual microservice, as a base and then layer in environment-specific configuration and credentials as needed.
Our Continuous Delivery (CD) approach focuses on a GitOps-based delivery model, using a GitHub repository as a single source of truth for the deployment, management, and operations of our running application components. In this model, we have the flexibility to use multiple open-source technologies to apply the single source of truth from a given GitHub repository onto a desired cluster environment.
The continuous integration workflow for our project is detailed figure below:
On the left side, the developer uses their environment with Appsody CLI to build and test the code. Once tests have run successfully, they commit and push the code to the main branch, which triggers the GitHub Actions workflow. For the walkthrough of our CI process, we will be using the Order Command microservice as our reference point.
The first task in each GitHub Actions workflow, validate-docker-secrets, ensures that all the necessary Secrets are defined on the repository under which the build action is running. Similar to Kubernetes Secrets, GitHub Repository Secrets allow you to store encrypted, sensitive information in a programmatically accessible way.
Here is an example of such secret definitions:
The majority of the microservices that comprise the Reefer Container Shipment solution reference implementation are built using the Appsody open-source project. While each microservice is free to choose its own specific technology for implementation via Appsody Stacks, each component can be easily built in any given environment by issuing the
appsody build commands.
The second task in each component microservice’s workflow, build-docker-image:
- runs on a base Ubuntu container image
- creates a new semantically-versioned tag (in the form of
0.1.2) for the repository
- installs the latest Appsody CLI tools, performs the
appsody buildcommand with the appropriate parameters
- tags the newly created version-specific image with
- pushes the image with both tags to the public Docker Hub repository defined by the aforementioned repository secrets
- and stores the
app-deploy.yamlgenerated by the
appsody buildfor use in the next task of updating the GitOps repository.
This task updates the
app-deploy.yaml file in every environment subdirectory in the GitOps repository for that specific microservice, by replacing each copy with the newly revised
app-deploy.yaml generated in the previous task.
This simple approach of overwriting works for two reasons:
app-deploy.yamlthat is checked into the original microservice repository is patched by the
appsody buildcommand, such as updating the image tag.
- No changes are made directly to the
app-deploy.yamlfile within the GitOps repo. Instead, modifications required for each environment are stored as patches, applied using
kustomizeat deployment time.
The update is performed via a standard
git commit process, as this allows for a visible audit trail of environment management and operations updates - one of the key advantages of the GitOps approach!
For details on how the GitOps repository is structured and how to create your own environment definitions, reference the peer GitOps Environments chapter of this manual.
For details on how the Continuous Delivery implementation leverages the GitOps artifacts, reference the peer Continuous Delivery (CD) chapter of this manual.