James Strachan and the CloudBees team have released the open source "Jenkins X" platform as a continuous integration and continuous delivery (CI/CD) solution for modern cloud applications that will be deployed onto Kubernetes. Strachan is sponsoring JEP 400, a formal proposal to act as a "stake on the ground" that captures the mission and the general directions for Jenkins X. The proposal requests that Jenkins X become a sub-project in the Jenkins Foundation.
Jenkins X uses a distribution of Jenkins as the core CI/CD engine, and promotes a particular Git branching and repository model. Additional tools and services provided in the distribution are built to fit this model. In a recent Jenkins blog post, Strachan, a senior architect at CloudBees, suggests that the Jenkins X development model represents the "best practice of developing Kubernetes applications". This is based in part on his experience and that of his team's from developing Fabric8, which is a project with a similar mission that attempts to realise the concrete implementation of tooling and supporting processes from the State of DevOps report.
If developers follow the suggested best practices, then Jenkins X assembles all the pieces required e.g., Jenkins, Kubernetes, Git, CI/CD etc., such that they can be "instantly productive". Strachan suggests this is akin to what Maven brought over the Ant build tool, and will encourage developers to use a standard lifecycle-model provided by Maven (DRY) to achieve greater productivity.
The associated Jenkins Enhancement Proposal (JEP), JEP 400, provides several examples of the recommended best practice for the CI/CD of cloud native applications deployed onto Kubernetes:
- The master branch shall be always clean and release ready. No long-running feature branches are allowed in order to "stay lean".
- Pull requests (PRs) are used to work on new changes, which then are issues against the master branch. CI tests are triggered on changes to a PR, and the PR can only be merged if all the CI checks pass and any required code reviews are satisfied etc.
- A release is produced from the master branch to create versioned immutable artifacts (JARs, binaries, Docker images, Helm charts etc). A release might be triggered manually, or automatically from a new PR merge, or even at set frequency.
- Which version of what services run in which environment is managed declaratively in a separate environment Git repo. You make deployment happen by pushing changes into the environment git repository which then triggers the Environments pipeline. This approach is often referred to as "GitOps" (with inspiration taken from Alexis Richardson of Weaveworks), and is similar to how people develop Chef recipes or Ansible playbooks with Git.
Among web application developers practicing CD, the notion of "environment" is a well-established practice, for example, "dev", "staging" and "production-1". Strachan states that this allows the "orderly flow of changes from a developer, through testing and staging to production", but argues that the traditional Jenkins model does not have the environment concept as the first class citizen. Jenkins X bridges this gap by introducing the concept of an 'environment' on top of more generic Kubernetes concepts, such as namespaces and labels. The development practice can then be modelled in terms of promoting applications from one environment to another in a cascading manner.
In order to make common tasks easy, Jenkins X defines a command line tool, jx, which encapsulates high-level operations. The Jenkins X CLI is used not only by developers from their local development machines, but also within the execution of Jenkins Pipeline, a mechanism to declaratively specify and implement CI/CD build pipelines.
The Jenkins X CLI is the primary control plane of Jenkins X. The tool enables:
- Installation of Jenkins X on any Kubernetes cluster
- Creation of new Kubernetes clusters from scratch on the public cloud
- Setting up environments for each Team
- Importing existing projects, or creating new Spring Boot applications. In addition, the tool:
- Automatically sets up the CI / CD pipeline and webhooks
- Creates new releases and promotes them through the environments, triggered by a branch being merged to master
- Supports "preview environments" built upon the issue of a PR
The Jenkins blog suggests that "Helm charts are the standard packaging mechanism for installing and upgrading applications on Kubernetes" (although it should be noted that the recently released Google Kubernetes development tool "Skaffold" did not build upon Helm). Accordingly, Jenkins X provides a Helm chart that allows the installation of Jenkins X on any Kubernetes cluster. Throughout the individual project build and deploy process, Jenkins X reuses tooling from Azure's Draft. This allows language and framework specific "build packs" to be maintained that contain the default Dockerfile, Jenkinsfile and Helm Chart files required to build, test, release and deploy different kinds of application.
Developers and teams don't have to spend time figuring out how to package software as docker images, create the Kubernetes YAML to run their application on kubernetes, create Preview environments or even learn how to implement CI/CD pipelines with declarative pipeline-as-code Jenkinsfiles. It's all automated for you out of the box! So you can focus instead on delivering value!
Jenkins X is not a general purpose Jenkins that can be modified to do anything. Instead, it is tailored to focus on Kubernetes and cloud native use cases, hence in the JEP 400 proposal Jenkins X is referred to as a "Kubernetes-native Jenkins."
Over time, we see an opportunity to improve Jenkins' core itself based on our learning in Jenkins X, so that Jenkins itself can be used in more cloud native configurations. This should benefit not only Jenkins X but other uses of Jenkins. These changes will result in separate JEP proposals.
Additional information on Jenkins X can be found on the project's website, and the "Getting Started" guide provides details on installation of the platform, both locally and within an existing Kubernetes cluster.