In a previous blog post, we saw how Codefresh compared to Jenkins. In that post, the major takeaway is the fact that Codefresh is a solution for both builds and deployments (CI/CD) while Jenkins does not support any deployments on its own (only CI).
Jenkins X has recently been announced and it is has been introduced as a native CI/CD solution for Kubernetes. It adds deployment capabilities to plain Jenkins and also makes entities such as environments and deployments a first-class citizen.
In theory, Jenkins X is a step in the right direction especially for organizations that are moving into containers and Kubernetes clusters. It therefore makes sense to see how this new project stands up against Codefresh, the CI/CD solution that was developed with Docker/Helm/Kubernetes support right from its inception.
In practice, Jenkins X has some very strong opinions on the software lifecycle which might not always agree with the processes of your organization.
Jenkins X is still using Jenkins 2.x behind the scenes inheriting all its problems
This is probably the most important point to understand regarding Jenkins X. Jenkins X is NOT a new version of Jenkins, or even a rewrite. It is only a collection of existing services that still include Jenkins at its core. If you deploy Jenkins X on a cluster you can easily look at all the individual components:
Fun fact: Chartmuseum is actually a Codefresh project!
This means that Jenkins X is essentially a superset of plain Jenkins. Of course it adds new deployment abilities to the mix but it also inherits all existing problems. Most points we have mentioned in the original comparison are still true:
- Plugins and shared libraries are still present
- Upgrading and configuring the Jenkins server is still an issue
- Pipelines are still written in Groovy instead of declarative YAML
You can even visit the URL of Jenkins in a Jenkins X installation and see the familiar UI.
What is more troubling is that all Jenkins configuration options are still valid. So if you want to change the default Docker registry, for example, you still need to manage it via the Jenkins UI.
Another downside of the inclusion of all these off-the-shelf tools is the high system requirements. Gone are the days where you could just download the Jenkins war on your laptop and try it out. I tried to install Jenkins X on my laptop and failed simply because of lack of resources.
The recommended installation mode is to use a cloud provider with 5 nodes of 20-30GBs or RAM. I tried to get away with just 3 nodes and was not even able to compile/deploy the official quickstart application.
Jenkins X deploys only on Kubernetes clusters, Codefresh can deploy anywhere
Kubernetes popularity is currently exploding and JenkinsX contains native support for Kubernetes deployments. The problem, however, is that JenkinsX can ONLY deploy on Kubernetes clusters and nothing else.
All new JenkinsX concepts such as environments, previews, and promotions are always targeting a namespace in a Kubernetes cluster. You can still use Jenkins X for compiling and packaging any kind of application, but the continuous delivery part is strictly constrained to Kubernetes clusters.
Codefresh, on the other hand, can deploy everywhere. Even though there is native support for Helm and Kubernetes dashboards, you can use Codefresh to deploy to Virtual machines, Docker Swarm, Bare Metal clusters, FTP sites, and any other deployment target you can imagine.
This means that Codefresh has a clear advantage for organizations that are migrating to Kubernetes while still having legacy applications around, as Codefresh can be used in a gradual way.
Jenkins X requires Helm, in Codefresh Helm is optional
Helm is the package manager for Kubernetes that allows you to group multiple microservices together, manage templates for Kubernetes manifests and also perform easy rollbacks to previous releases.
Codefresh has native support for Helm by offering a private Helm repository and a dedicated Helm dashboard.
We love Helm and we believe it is the future of Kubernetes deployments. However, you don’t have to adopt Helm in order to use Codefresh.
In Codefresh the usage of Helm is strictly optional. As mentioned in the previous section you can use Codefresh to deploy anywhere including plain Kubernetes clusters without Helm installed. We have several customers that are using Kubernetes without Helm and some of the facilities we offer such as blue/green and canary deployments are designed with that in mind.
Jenkins X, on the other hand, REQUIRES the adoption of Helm. All deployments happen via Helm as the only option.
Helm is also used to represent complete environments (the Helm umbrella pattern). The GIT repositories that back each environment are based on Helm charts.
We love the fact that Jenkins X has adopted Helm, but making it the only deployment option is a very aggressive stance for organizations that want to deploy legacy applications as well.
Representing an environment with a Helm umbrella chart is a good practice but in Codefresh this is just one of the many ways that you can do deployments.
Jenkins X enforces trunk based development, Codefresh allows any git workflow
From the previous sections, it should become clear that Jenkins X is a very opinionated solution that has a strong preference on how deployments are handled.
The problem is that these strong opinions also extend to how development happens during the integration phase. Jenkins X is designed around trunk based development. The mainline branch is what is always deployed and merging a pull request also implies a new release.
Trunk-based development is not bad on its own, but again there several organizations that have selected other strategies which are better suited for their needs. The ever-popular gitflow paradigm might be losing popularity in the last years, but in some cases, it really is a better solution. Jenkins X does not support it at all.
There are several organizations where even the concept of a single “production” branch might not exist at all. In some cases, there are several production branches (i.e. where releases are happening from) and adopting them in Jenkins X would be a difficult if not impossible task.
Codefresh does not enforce a specific git methodology. You can use any git workflow you want.
A similar situation occurs with versioning. Jenkins X is designed around semantic versioning of Git tags. Codefresh does not enforce any specific versioning pattern.
In summary, with Codefresh you are free to choose your own workflow. With Jenkins X there is only a single way of doing things.
Jenkins X has no Graphical interface, Codefresh offers built-in GUI dashboards
Jenkins X does not have a UI on its own. The only UI present is the one from Jenkins which, as we have already explained, knows only about jobs and builds. In the case of a headless install, not even that UI is available.
This means that all the new Jenkins X constructs such as deployments, applications, and environments are only available in the command line.
The command line is great for developers and engineers who want to manage Jenkins X, but very inflexible when it comes to getting a general overview of everything that is happening. If Jenkins X is installed in a big organization, several non-developers (e.g. project manager, QA lead) will need an easy way to see what their team is doing.
Unfortunately, at its present state, only the JX executable offers a view of the Jenkins X flows via the command line.
Codefresh has a full UI for both CI and CD parts of the software lifecycle that includes everything in a single place. There are graphical dashboards for:
- Git Repos
- Docker images
- Helm repository
- Helm releases
- Kubernetes services
It is very easy to get the full story of a feature from commit until it reaches production as well as understand what is deployed where.
The UI offered from Codefresh is targeted at all stakeholders that take part in the software delivery process.
Jenkins X uses Groovy/JX pipelines, Codefresh uses declarative YAML
We already mentioned that Jenkins X is using plain Jenkins under the hood. This means that pipelines in Jenkins X are also created with Groovy and shared libraries. Codefresh, on the other hand, uses declarative YAML.
The big problem here is that the jx executable (which is normally used to manage Jenkins X installation) can also be injected into Jenkins pipelines by extending their pipeline steps. This means that pipelines are now even more complicated as one must also learn how the jx executable works and how it affects the pipelines it takes part in.
Here is an official example from the quick start of Jenkins X (this is just a segment of the full pipeline)
// ensure we’re not on a detached head
sh “git checkout master”
sh “git config –global credential.helper store”
sh “jx step git credentials”
// so we can retrieve the version in later steps
sh “echo $(jx-release-version) > VERSION”
sh “mvn versions:set -DnewVersion=$(cat VERSION)”
sh “jx step tag –version $(cat VERSION)”
sh “mvn clean deploy”
sh “export VERSION=`cat VERSION` && skaffold build -f skaffold.yaml”
sh “jx step post build –image $DOCKER_REGISTRY/$ORG/$APP_NAME:$(cat VERSION)”
You can see in the example above that jx now takes place in the Jenkins X pipelines requiring developers to learn yet another tool.
The problem here is that for Jenkins X to do its magic your pipelines must behave as they are expected to. Therefore modifying Jenkins X pipelines becomes extra difficult as you must honor the assumptions already present in the pipeline (that match the opinionated design of Jenkins X).
This problem does not exist in Codefresh. You can have a single pipeline that does everything with conditionals or multiple independent pipelines, or linked-pipelines or parallel pipelines, or any other pattern that you wish for your project.
Jenkins X does not cache dependencies by default, Codefresh has automatic caching
JenkinsX is scaling by creating additional builders on the Kubernetes cluster where it is installed. When you start a new pipeline, a new builder is created dynamically on the cluster that contains a Jenkins slave which is automatically connected to the Jenkins master. Jenkins X also supports a serverless installation where there is no need for a Jenkins master at all (which normally consumes resources even when no builds are running).
While this approach is great for scalability it is also ineffective when it comes to build caching. Each build node starts in a fresh state without any knowledge of previous builds. This means that all module dependencies needed by your programming language are downloaded again and again all the time.
A particularly bad example of this is the quick start demo offered by Jenkins. It is a Java application that downloads its Maven dependencies:
- Whenever a branch is built
- When a pull request is created
- When a pull request is merged back to master
Basically any Jenkins X build will download all dependencies each time it runs.
The builders in all 3 cases are completely isolated. For big projects (think also node modules, pip packages, ruby gems etc) where the dependencies actually dominate the compile time, this problem can quickly get out of hand with very slow Jenkins X builds.
Codefresh solves this problem by attaching a Docker volume in all steps on the pipeline. This volume is cached between subsequent builds so that dependencies are only downloaded once.
In summary, Codefresh has much better caching than JenkinsX resulting in very fast builds and quick feedback times from commit to result.
In this article, we have seen some of the shortcomings of Jenkins X. Most of them center around the opinionated workflow & design decisions behind JenkinsX.
The biggest drawback, of course, is that JenkinsX also inherits all problems of Jenkins and in some cases (e.g. pipeline syntax) it makes things more complicated.
Finally, at its present state, Jenkins X has only a command line interface, making the visualization of its environment and application a very difficult process.
In the following table, we summarize the characteristics of JenkinsX vs Codefresh:
|Git repository dashboard||No||Yes|
|Versioning||Git tags /semantic||Any|
|Pipeline Management||CLI||Graphical and CLI|
|Built-in dynamic test environments||Yes||Yes|
|Native build caching||No||Yes|
|Pipelines as code||Groovy||Yaml|
|Native Monorepo support||No||Yes|
|Extension mechanism||Groovy shared libraries||Docker images|
|Internal Docker registry||Yes||Yes|
|Docker Registry dashboard||No||Yes|
|Custom Docker image metadata||No||Yes|
|Native Kubernetes deployment||Yes||Yes|
|Kubernetes Release Dashboard||No||Yes|
|Deployment mode||Helm only||Helm or plain K8s|
|Integrated Helm repository||Yes||Yes|
|Helm app dashboard||Yes||Yes|
|Helm release dashboard||No||Yes|
|Helm releases history and management (UI)||No||Yes|
|Helm Rollback to any previous version (UI)||No||Yes|
|Deploy to Bare Metal/VM||No||Yes|
|Deployment management||CLI||GUI and CLI|
New to Codefresh? Create Your Free Account Today!