Introducing Knctl: A simpler way to work with Knative, Part 2

Social

In Part 1 of this two-part blog series, we introduced Knctl, a command-line interface (CLI) for interacting with Knative, and we showed you how to deploy pre-built Docker images with Knative. In this part, we explore newer features of Knctl, specifically, deploying applications from source, splitting traffic across revisions, and connecting Knative services to databases.

Deploy from source code

Knative deploys applications based on container images. In part one, we showed how you can use Knctl to deploy an image with a simple command. But what if you are still actively working on the application source code, and therefore do not have an image for it yet?

Knative Build is a project that allows you to turn source code into a container image. There are two options using it to build from source: 1) with a Dockerfile, and 2) with a Buildpack build template.

Before you can deploy, you must set up secrets for Knative Build to connect to an image registry for pushing and pulling images. The following example uses DockerHub and assumes that your user name and password are saved in DOCKER_HUB_USERNAME and DOCKER_HUB_PASSWORD environment variables:

After your service account and secrets are created, you clone the sample Go app, which includes a Dockerfile. Note that the example shows the generic case for DockerHub with a private account requiring both a pull and a push secrets. If you used a public account, you might not need to set up a pull secret (because all images are public).

With the Knctl deploy command you can view the output during execution. When building from source, you see the Docker build process and see the image that is uploaded to the registry. After the build process is complete and successful, you should be able to access the deployed service and even re-deploy it with the resulting image. Re-deploying adds a new revision of the service if you use the same name.

Buildpacks

BuildTemplate objects in Knative Build allow you to build images in a variety of ways. The Buildpack template is based on the popular Buildpack process, first created by Heroku and now popularized by Cloud Foundry and other platforms as a service (PaaS).

First you need to add a BuildTemplate object to Kubernetes. The object provides directions on how to actually build and configure container image:

Then you can use the buildpack template with Knctl. Issue the deploy command with the --template buildpack flag. You still need to include the secrets for your registry because the resulting container image needs to be saved somewhere for subsequent access:

Note that while we used the same application that includes a Dockerfile, you could remove this file when using the --template buildpack option. With this build template, the container image is created automatically. The buildpack process attempts to discover what your application type is and create the image accordingly. You can then verify that your service was deployed as we did above with the knctl curl command.

A word of caution: While deploying with buildpacks appears to be easier because you don’t need to create your own Dockerfile, it might be more difficult to track dependencies. Tracking dependencies is especially difficult when your application deviates from the common practices of frameworks used to create your application. We therefore recommend creating a Dockerfile for your applications and functions to guarantee repeatability of the image building process.

Traffic splitting

With traffic splitting, you can control the amount of traffic that Knative delivers to a specific revision of your service, which can be useful for a variety of reasons. One common example is to roll out service updates (and roll them back) in an incremental fashion to reduce risk of breaking users. The so-called blue-green deployment is easy to do with knctl rollout command.

The first thing to do when splitting traffic is to create a service with multiple revisions:

The latest revision is tagged as latest and the previous is tagged as previous. You can then use these tags to split traffic between these revisions. You can also chose to specify your own tags when deploying, for example, v1, v2, and so on. You can add these tags after deployment with the $ knctl revision tag ...command.

Because the example split the traffic evenly across the two revisions, the easiest way to verify that traffic is indeed spread across is to curl the service multiple times. You should see that about 50% of the traffic is routed to the latest and other 50% to the previous revision.

Connecting to a database

Most cloud applications, services, and functions do not exist in a vacuum. That is, for any meaningful cloud service, you need to connect the service to some other external service. The most common example is to connect to a cloud database in order to store your data and allow it to be searched and queried securely and efficiently. Although you can hard code service dependency connections and credential information directly into source code, it is not typically a good idea.

A common solution is to use environment variables, or Kubernetes secrets, or external configuration files to hold sensitive information. We found a sample Go application that uses a MySQL database in order to store and retrieve blog posts. We made a change to the application to use DATABASE_URI environment variable for its database URI connection string.

Before we deployed this application, we created a MySQL service instance from IBM Cloud service catalog. After creating an instance of that service, we created credentials for the MySQL service instance and downloaded the JSON document that includes the connection information. The following screen capture shows the IBM Cloud user interface. The rest is self-explanatory after you create the service instance.

(For our adventurous readers, you can try to install the Kubernetes Service Catalog project and instead provision a MySQL service instance through the svcat command-line interface.)

After downloading the credential JSON, you need a YAML file with a Secret object similar to the one in our example:

To verify that the application can successfully use database, you should open it in your browser. If you can’t set up DNS for your Knative installation, you can try using kwt to configure the DNS on your local machine temporarily:

What’s next?

The important next steps for the Knctl project are not only socializing with Knative enthusiasts and new users but also connecting with the Knative community to increase adoption and perhaps make it the defacto default CLI.

We demonstrated these Knctl features recently at a “show and tell” meeting with the community. We will work with the community to achieve the next steps in defining the CLI for Knative, hopefully using Knctl as the base.

Conclusion

Now you have seen some examples of how to run Knative service from a local directory, split traffic across several revisions of a Knative service, and connect your service to a MySQL database. Using these features through a few commands helps demonstrate the realization of our goals for Knctl: simplifying Knative use for developers.

As we keep Knctl in sync with upcoming releases of Knative, we continue to welcome your your feedback via our Github project and look forward to your pull requests.