How to use IBM Cloud's DevOps Toolchain to deploy and update an application running on virtual servers in IBM Virtual Private Cloud.
There is an excellent summary of the different approaches a developer can take to deploy applications in IBM Cloud's Virtual Private Cloud (VPC) in the tutorial "Install software on virtual server instances in VPC."
In my case, I want to automate the initial deployment of my application and keep it updated after daily commits to my code repository. The DevOps Toolchain and its Delivery Pipeline offers these automation capabilities through the integration with various code, build, deploy, and test tools.
Creating an environment in VPC is a relatively simple process when leveraging the UI; however, I am anticipating potential changes to the desired environment. I will need to scale up the number of virtual server instances to test scenarios where the app is distributed across multiple availability zones. I will have a load balancer for testing application availability/health throughout it, and I will need to modify it each time I add or remove a virtual server. Finally, I also want to easily tear down the environment when it is no longer needed.
This post will provide an overview of a template built specifically for VPC that leverages the learnings from the resources above.
Deployment architecture scenario
The full environment I plan to use requires high availability and, as such, I needed to deploy three virtual server instances (nodes in the diagram) across three availability zones. With the application running in three availability zones, I need a load balancer to perform health checks and appropriately spread the load to each of the running instances.
(1) Public GitHub is used for storing all the source code/templates, although Git running in the IBM Cloud, GitHub Enterprise, or other code sources can also be used. This project leverage a template repository (see further below for details): vpc-toolchain-liberty-sampleapp.
(2) and (3) The continuous delivery pipeline monitors the master branch in a cloned version of the repository stored in your own account. Upon noticing changes, it runs the pipeline to build and redeploy the app to the virtual server instances and runs a simple test.
(4) Identity and Access Management (IAM) is used to create/validate the API key that is used to access the IBM Cloud and VPC resources when the pipeline is running.
(5) End user(s) can access the application via a load balancer using HTTP (HTTPS if a certificate is configured).
Overview of the toolchain and the pipeline
Creating the toolchain is straightforward: Access the vpc-toolchain-liberty-sampleapp repository and follow the instructions available in the README.md. The vpc-toolchain-liberty-sampleapp repository will be cloned to a location you select in public GitHub, and the pipeline will create all the required VPC resources and deploy a sample application from the cloned repository. With you own version of the repository, you can make changes as you see fit.
Toolchain/delivery pipeline template overview
The repository contains all the configuration for the toolchain and delivery pipeline as well as the required inputs (i.e., IBM Region to deploy, API key, etc.). It is used to initially create the toolchain/delivery pipeline and is not needed afterward.
The toolchain.yml and deploy.json are used for setting up the toolchain and contain the form fields that are required for input during creation (i.e., prompting for the IBM Cloud API Key to use, SSH Keys to access virtual instances, and determining what repo to use as an initial source for the application).
The pipeline.yml includes all the stages in the pipeline and calls to various shell scripts that are required to build and deploy the application. For ease of identification, the shell scripts are named after the job name in each of the stages.
More information on understanding and modifying a toolchain template can be found in the SDK.
VPC environment Terraform template
Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. This repository contains all the infrastructure configuration instructions (e.g., availability zones, subnets, virtual server instances, load balancer configuration, etc.) to create the resources from scratch in the IBM Cloud, as depicted above.
Another excellent read to help understand how to use Terraform is the "Plan, create, and update deployment environments" tutorial. You can also learn more about the APIs available in the IBM Terraform Provider repository.
The nodes running the application are running in a private network, which means a bastion host is required to proxy SCP and SSH commands into the running instances. The bastion host configuration is included as a separate module in the template configuration tf_modules/vpc_bastion.
The main.tf contains the instructions for provisioning and configuring the VPC resources in the IBM Cloud.
The output.tf contains the values that result from the Terraform apply. These values, such as the IP addresses of the virtual servers and the name of the load balancers, are passed to the next stages in the pipeline as they are needed for deployment and testing.
The variables.tf contain all of the input required by the Terraform template. They are supplied by the previous stage in the pipeline.
The repository includes an example Java application that will be deployed to run on WebSphere Liberty Profile.
The sample application code a very straightforward and resides under the src folder. The pom.xml contains all the deployment details and dependencies.
The scripts folder contains the various shell scripts that are invoked during the run of the pipeline. As mentioned earlier, for convenience, they are named after the name of the job in each of the stages.
- The build.sh takes the input used during the creation of the toolchain and stores them into environment variables that will be used whenever the pipeline runs. It also creates an archive of the application based on the pom.xml (i.e., it runs through a build, test/archive).
- The apply_deploy_test.sh runs a Terraform plan and apply to create the VPC resources. Before and after it runs, it does a Git checkout and commits the Terraform state to a dedicated branch in the repository. This makes it possible to preserve the Terraform state and prevent complete rebuilds of the environment each time the pipeline runs. The Terraform state can also be used to tear down the environment when it is no longer needed. This script will also perform an update of the application on each node one at a time, with a 60-second delay between each, allowing enough time for the load balancer to identify via health check that a node is available again to receive traffic.
- The destroy.sh is used to read the last saved Terraform state and delete all the resources that were created by the apply_destroy_test.sh run.
When they run, every pipeline job will output the results of the shell script in logs, and you can view those logs to confirm success or failure to be able to address them.
To get started, try our sample code on GitHub. Instructions are provided to create and use the toolchain. We will start with the pipeline and associated code—creating a slightly smaller environment as depicted above—and in subsequent runs, update the infrastructure code to add additional resources and redeploy the app. We also cover how to clean up resources when you no longer need them.
Questions and feedback
This sample repository is only a starting point—you could split it to two or three different repositories. For example, hosting the infrastructure build code (Terraform) in a repository of its own and having a separate pipeline for executing infrastructure changes and a different one for deploying/updating the code.
The GitHub repository for this scenario has an Issues tab where you can comment on the content and code. If you have suggestions or issues, please submit your feedback.