Manually creating and managing a handful of containers in a production environment is entirely doable. But at some point, organizations and teams cross a threshold. While that exact point will differ by organization, once crossed, the idea of manually patching, testing, and deploying a fleet of containers will become too much.

When the next inevitable security vulnerability is revealed, leaving both your business and customers exposed, how will your organization respond? How long will it take to mitigate? Will your development teams need to stop valuable feature development in order to patch, test, and deploy your applications?

Just as continuous integration (CI) and continuous delivery (CD) are becoming ubiquitous in the enterprise, automating the testing and deployment of applications, respectively, so too is automating the process of patching and building new, custom container images. Tanzu Build Service inserts seamlessly into your CI and CD pipelines to perform this task.

In this post, you will deploy Tanzu Build Service locally on Kubernetes, then use it to build a new, custom application.  Once that pipeline is set up, you will notice that Tanzu Build Service will continuously monitor your code, as well as the underlying base OS and build dependencies, for changes. And anytime one of these areas changes, it will automatically create a new container image and push it to your image repository.

Note: The environment you will set up is meant for demonstration purposes only. You will set up Tanzu Build Service to monitor the code repository directly. That would not be the case in a production environment, as it could conflict with a CI workflow. We are taking this approach in the interest of simplicity, and to get Tanzu Build Service up and running quickly. There are several ways that Tanzu Build Service monitors for outputs of a CI pipeline, but they are outside of the scope of this post.

Let’s get started.

Prerequisites

Before you get started, you’ll need to do the following:

  • Install Docker Desktop (for Windows or Mac) – You will use it to create your local Kubernetes cluster, as well as to run your containers built by Tanzu Build Service.

  • Create a Docker Hub account – This is where Tanzu Build Service will push your built images for you to pull down and run. It is also where you will push your Tanzu Build Service to build images during the install process. 

  • Install the pivnet CLI – This CLI offers an easy way to download applications and bundles from the VMware Tanzu Marketplace, straight from the command line, without worrying about passing credentials in curl headers. If you prefer, you can modify commands found in this post to use curl, wget, or similar.

  • Install the kubectl CLI – You will use this CLI to manage your Kubernetes environment. Tanzu Build Service also uses your Kubernetes config file to connect and authenticate with your local cluster. 

  • Install Carvel tooling (formally k14s) – You will use this set of tools (namely, kbld and ytt) during various points in the install process. 

Prep a workspace

Being organized is key to any successful project. So before you dig in, create a new project directory and cd into it:

$ mkdir tbs-getting-started && cd $_

Then define some environment variables to make the rest of the commands in this post easier to copy and paste:

$ export DH_USERNAME=<your-docker-hub-username>
$ export GH_USERNAME=<your-github-username>
$ export LOCAL_USER=$(id -un)

Download the Tanzu Build Service bundle

Tanzu Build Service is hosted on the VMware Tanzu Network (formerly the Pivotal Network, or PivNet). You will need access to this network as a customer to download Tanzu Build Service and the associated client tooling. The following command will download Tanzu Build Service into your directory.

Download commands for other releases can be found on the VMware Tanzu Network. If you do not have the pivnet client installed, this bundle can be downloaded directly from there.

$ pivnet download-product-files --product-slug='build-service' --release-version='1.0.1' --product-file-id=766634

Now unbundle the tar file:

$ tar xvf build-service-1.0.1.tar

Create the Kubernetes cluster

This is where you will install Tanzu Build Service. To create a local Kubernetes cluster using Docker Desktop, follow this guide from Docker. The process is straightforward:

Docker Desktop > Preferences > Kubernetes > Check “Enable Kubernetes” > Apply & Restart

Kubernetes running on Docker Desktop provides an easy way to get started with Kubernetes, as well as a way to reset your cluster to “defaults” should something go awry. Creating this cluster will also create a Kubernetes config file in ~/.kube/config which kubectl and Tanzu Build Service will use to interact with your new cluster.

Switch your kubectl context to your local cluster:

$ kubectl config use-context docker-desktop

And verify the cluster is working properly:

$ kubectl cluster-info
Kubernetes master is running at https://kubernetes.docker.internal:6443
KubeDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Create the Tanzu Build Service credentials file

The credentials file tells Tanzu Build Service where your Kubernetes config file is in order to connect to it. It also defines a path to your CA for Tanzu Build Service should you be using a private repository. Since this guide uses Docker Hub for the install, we don’t need to define the CA path in this step. Modify the kube_config path attribute as needed, but this is the default path on a Mac:

$ echo "name: build-service-credentials
credentials:
- name: kube_config
  source:
    path: "/Users/$LOCAL_USER/.kube/config"
  destination:
    path: "/root/.kube/config"" > credentials.yml

If you want to use Tanzu Build Service with other registries, see the Tanzu Build Service install guide for further instructions. 

Push the Tanzu Build Service bundle to Docker Hub

The bundle you downloaded earlier contains many images for the buildpack runtime packages Tanzu Build Service will use to build your images. It also contains the install image for Tanzu Build Service. For Tanzu Build Service to have access to these images, they need to be pushed to your image registry.

First, log in to your Docker Hub account. This command will ask for your password if you are not already authenticated:

$ docker login -u $DH_USERNAME

You will also need to log in to the Pivotal registry to access the install images. Use your credentials for the VMware Tanzu Network:

$ docker login registry.pivotal.io

Then use kbld to push the bundle to the repo. This command will take some time to complete, depending on your internet connection. But it should not take more than 5 minutes:

$ kbld relocate -f images.lock --lock-output images-relocated.lock --repository $DH_USERNAME/tanzu-build-service

The --lock-output attribute is an output file you will use in the next step to tell Tanzu Build Service where each image is located. 

Install Tanzu Build Service 

Now it’s time to install Tanzu Build Service to your local Kubernetes cluster.

Modify the docker_password credential below for your environment. You can also change the install name from tanzu-build-service to something that makes more sense for your use case:

$ ytt -f values.yaml
    -f manifests
    -v docker_repository=$DH_USERNAME
    -v docker_username="$DH_USERNAME"
    -v docker_password="*****"
    | kbld -f images-relocated.lock -f-
    | kapp deploy -a tanzu-build-service -f- -y

Note: While this guide is for setting everything up yourself, it is worth noting the responsibilities of different roles within an organization. If this were a production use case, for example, an operations team would be setting up and managing the Tanzu Build Service cluster environment. It would manage the cluster credentials and buildpack images and take all the steps you just took.

Everything that follows would typically be done by a developer. They would simply install and connect the Tanzu Build Service client application, kp (or more appropriately, script the install as part of setting up a developer environment), and set up the automated build flow.

Install kp

The local CLI tool, kp, is used for interacting with your Tanzu Build Service installation. It can be downloaded from the VMware Tanzu Network for your platform here. The following commands are specific to macOS. Modify them as needed for other platforms.

To download the binary for macOS, use the following pivnet command. Go to the Tanzu Build Service bundle in the VMware Tanzu Network to find versions for other platforms:

$ pivnet download-product-files --product-slug='build-service' --release-version='1.0.1' --product-file-id=760687

Once downloaded, rename the binary:

$ mv kp-darwin-0.1.0 kp

Make the binary executable:

$ sudo chmod +x kp

And move it into your local $PATH:

$ mv kp /usr/local/bin

Now the Tanzu Build Service server and the kp client are installed. But there are not yet any builders or stacks with which to build the application. You will set those up next.

Installing dependencies

You now need to install a package of default cluster stacks and cluster builders. Stacks are a pair of base OS container images: one for the build process, and one to run the application. Builders are a collection of Cloud Native Buildpacks used to compile and build your application.

The first thing you need to do is download the bundle from the Tanzu Network. Here again is the command using the pivnet CLI tool:

$ pivnet download-product-files --product-slug='tbs-dependencies' --release-version='7' --product-file-id=765765

Note: At the time of this writing, version 8 is the most up-to-date dependency bundle. You are purposefully downloading version 7 here because in a later step you will upgrade this dependency bundle to see Tanzu Build Service automatically recreate your container image based on a patch to the underlying base OS.  

Next, use kp import to bulk import these dependencies into Tanzu Build Service. 

This will download all stack and build images, and make them available in your builds: 

$ kp import -f descriptor-7.yaml

Note: kp import is a handy tool for bootstrapping your Tanzu Build Service installation. But for updating specific dependencies, you will likely want to be more selective about which packages you update. Later in this post, you will upgrade just the base OS images to get an idea of this flow. But know that you could also just use kp import again to upgrade everything. The choice is yours. See the installation documentation for further details.

Verify your installation by listing the clusterstacks available to Tanzu Build Service:

$ kp clusterstack list
NAME       READY    ID
base       True     io.buildpacks.stacks.bionic
default    True     io.buildpacks.stacks.bionic
full       True     io.buildpacks.stacks.bionic
tiny       True     io.paketo.stacks.tiny

Access the example application

Before Tanzu Build Service can build a container image for us, we need an application for it to build. In this project, the application we are using is called spring-petclinic, which would be used to manage a veterinary hospital. It is relatively easy to understand and make changes to as you experiment.

You can use the spring-projects repository version to do a onetime build and test of Tanzu Build Service. But that won’t allow you to see the automated build functionality when a new commit is pushed to the repo. To test the automated build functionality on Tanzu Build Service, you will need to fork this repository into your own. You can also use a different image entirely. In that case, just be sure to modify the rest of the commands in this guide to suit your needs. All of the commands that follow assume you have forked this repository into your own account.

Forking is done through the GitHub GUI (a guide for how to do that can be found here):

$ git clone https://github.com/$GH_USERNAME/spring-petclinic.git

Configure secrets

Tanzu Build Service will need to talk to your version control system and your image registry. In this guide, you are configuring Tanzu Build Service with GitHub and Docker Hub. To do this, you need to pass these credentials to Tanzu Build Service using the kp secret command.

First, create a secret for your Docker Hub account. Be sure to modify the following command by adding your Docker Hub username. It will prompt you for your Docker Hub password:

$ kp secret create my-dockerhub-creds --dockerhub $DH_USERNAME

Note: At this point, you would normally need to create another secret for GitHub. But since the code we are running is open source and in a public repository, we can skip this step. But note that the command (and its arguments) are very similar to the one above. 

Configure an image

So now our Tanzu Build Service project knows about the systems it needs to talk to. The last step is to tell it about the code we want to monitor and build.

With this next command, we are telling Tanzu Build Service where to retrieve the source code. Tanzu Build Service will be configured to watch the master branch by default, but you can configure it to watch your own development branch for whatever feature or bug you happen to be working on. Finally, the tag is where the image will be pushed in your registry. Modify this file to address your own image:

$ kp image create spring-petclinic --tag index.docker.io/$DH_USERNAME/spring-petclinic --git https://github.com/$GH_USERNAME/spring-petclinic.git --git-revision main

Once the image configuration has been applied, Tanzu Build Service will scan the repo and start building your image. You can see this happening by running the kp command below to list all of the builds associated with an image tag:

$ watch kp build list spring-petclinic
BUILD    STATUS     IMAGE
STARTED              FINISHED                REASON
1        SUCCESS    index.docker.io/$DH_USERNAME/spring-petclinic@sha256:<...>    2020-07-07 10:24:18    2020-07-07 10:25:42    CONFIG

Once completed, Tanzu Build Service will put a copy of the image into your Docker Hub registry, as well as onto your local Kubernetes cluster within the default namespace (this is configurable). From there, you can run the image locally and see any changes you push to your registry.

This command runs the container and forwards the local port 8080 to the container port 8080:

$ docker run --rm -p 8080:8080 index.docker.io/$DH_USERNAME/spring-petclinic:latest

Now open a browser window with the URL http://localhost:8080.

Next, try making a change to the source code and pushing it to the branch your Tanzu Build Service project is configured to watch. For a nice, visible change, consider changing the home page “Welcome” message:

$ vim spring-petclinic/src/main/resources/messages/messages.properties

Now modify the welcome variable, then commit and push that change back to the main branch:

$ cd spring-petclinic && git add . && git commit -m "Updated welcome message"
$ git push && cd ..

Tanzu Build Service will pick up the change automatically, build a new container, and push it to your registry! Here you can watch the build start and see when it has successfully completed:

$ watch kp build list spring-petclinic

For a proof point, try pulling and running the container again to see your changes.

Next, let’s take a look at updating the underlying base OS.

Applying a base OS update

One of the most common and powerful use cases of Tanzu Build Service is applying OS patches to your containers automatically. Here you will use this feature to patch one image. But imagine if you had hundreds or even thousands of container images to patch once the next heartbleed-level vulnerability was found. Tanzu Build Service will patch and rebuild all of the containers it manages based on this single update.

Instead of installing all of the available dependencies as you did above in the installation process, here you are just going to update a single dependency. You will update the “full” clusterstack.

These images are hosted on the Pivotal registry. To find their tag names and full URLs, go to the Tanzu Network > Tanzu Build Service Dependencies > Select the version > Image References > Full build image/Full run image. Click the information button and copy out the command. For simplicity, this command is provided for you here:

$ kp clusterstack update full --build-image registry.pivotal.io/tbs-dependencies/build-full@sha256:423b15b46ee55ddb32851f0460468e1abecbf0d7b894ca9a9ab03543e008e9ab --run-image registry.pivotal.io/tbs-dependencies/run-full@sha256:d2019a8b64c252e6d164f84afa89d699cc6d6a2ff9b7ad6553278fc710626a15

Now Tanzu Build Service is using an updated base OS image for your image configuration. And since there was a change to the previous image, Tanzu Build Service will start a new build automatically.

$ watch kp build list spring-petclinic

All of this applies to your build dependencies, too. For example, if you need to patch your Java runtime, the process is very similar. Tanzu Build Service will pick up those changes and rebuild and redeploy all of your containers. This is a very powerful feature of Tanzu Build Service, one that helps keep your customers—and your business—safe from vulnerabilities.

If you would like to dive deeper into VMware Tanzu Build Service, check out the documentation section. And make sure to let us know how the beta* is going!

*This article may contain hyperlinks to non-VMware websites that are created and maintained by third parties who are solely responsible for the content on such websites.