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:
Jenkins X is just Jenkins plus Chartmuseum, Nexus, Mongo, Monocular, etc. The main new addition is the jx executable which is responsible for installing and managing JX installations.
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
- Extending the platform requires Groovy/Java knowledge
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 Jenkins X contains native support for Kubernetes deployments. The problem, however, is that Jenkins X can ONLY deploy on Kubernetes clusters and nothing else.
All new Jenkins X 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
- Pipelines
- Builds
- 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)
steps { container('maven') { // 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
Jenkins X 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.
Jenkins X advantages
In the previous sections we have seen some shortcomings of Jenkins X when compared directly to Codefresh. However, some of these issues actually have to do with the mindset behind Jenkins X and the goals it tries to achieve.
First of all, Jenkins X tries to help you with creating a CI/CD pipeline as fast as possible by automating several tasks that are typical prerequisites. For example, you can quickly create a Kubernetes cluster on any popular cloud provider with the jx create cluster
command. Codefresh just assumes that your Kubernetes cluster is already there (and possibly created by another member of your team such as an SRE).
Creating a project from scratch in Jenkins X is also a very simple process as several buildpacks are offered for all popular programming languages. With the same jx
executable you can easily create a project skeleton for Rust, Ruby, Scala, Gradle etc. You also get an automatically generated Dockerfile for your project. Jenkins X will even commit your project to GIT for you if it is not already in source control. Codefresh again assumes, that you already have an existing source code project and the only thing missing is the CI/CD pipeline.
This makes the usage of Jenkins X very easy for beginners, as with several built-in commands they can start from nothing to a full blown CI/CD pipeline. This is especially helpful for startup teams that start on green field projects where there are no existing best practices and processes.
Jenkins X also attempts to solve more aspects of software development (and not just the CI/CD part), such as the experience for local programming. A Jenkins X installation automatically offers live sync of dev code while being developed (devpods). This helps developers to test their application code even before they merge their feature in the mainline, by seeing how their code runs on the same environment as it will be deployed. Codefresh has no such capability and assumes that you are using an external solution such as garden, skaffold, telepresence, Okteto etc. (Jenkins X is in fact using Skaffold behind the scenes).
Jenkins X makes also very easy the promotion of releases among different environments if you indeed follow trunk based development. Jenkins X automatically creates a GIT repository for each environment with an umbrella Helm chart and all promotions are happening via pull requests. You can get the same thing in Codefresh, but it is up to you to set-it-up, while with Jenkins X you get it out of the box. So for companies that need this specific functionality, they can start using pull-based promotions right away with Jenkins X.
Finally, Jenkins X has IDE integrations with Visual Studio Code and Intellij allowing developers to monitor builds from their favorite development environment. Codefresh offers no such functionality.
Conclusion
In this article, we have seen some discussion points on how Jenkins X and Codefresh work with CI/CD pipelines.
Jenkins X is a beginner friendly solution that tries to help as much as possible with the initial project setup. With just a few commands you can get a cluster created with Jenkins X, several deployment environments (backed by git repositories) and a source code skeleton for your development project. This model would work great in a startup company that works on a brand new project where no conventions exist yet.
This quick initial setup however comes at the expense of several design decisions that focus on a opinionated workflow. If you agree with the decisions Jenkins X made already for you then there is great value for green field projects. Jenkins X assumes that you work with trunk based development, promote your releases with pull requests on git-based environments and most importantly use only Helm for all deployments (not even plain Kubernetes manifests). Any other project configuration is simply NOT supported.
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.
Codefresh on the other hand does not impose any limitation on your workflow or the deployment targets. You can use Codefresh to deploy to VMs, Nomad clusters, Tomcat servers, FTP sites, S3 buckets and any other target that you want. This is particularly important for big companies with existing projects, as expecting every system to be switched right away to Kubernetes/Helm is an unrealistic proposition (companies still have VM based projects or even bare metal).
In the development part, again Codefresh is very flexible. You can use trunk based development or any other workflow that your company already uses. Single pipelines, manual approvals, continuous deployment are all supported. You can promote releases to other environments with just an API, a CLI or pull requests or any other method that your team agrees on.
Finally, Codefresh offers a graphical view for all major assets such as builds, pipelines, docker images, Helm charts, environments etc. making the CI/CD process accessible by everyone inside a company and not just developers.
In summary if you start working on a brand new cloud application and are just finding your way around Kubernetes, Helm, Docker registries and cloud deployment environments, Jenkins X can greatly help you with the initial setup (especially with small teams composed only from developers). But if you work at an existing company with multiple established projects (cloud and non-cloud, Dockerized or traditional VMs) Codefresh is a much more flexible solution that can adapt to any team workflow and project process. Codefresh is especially powerful in companies where different people manage the infrastructure than those that do application development or companies with legacy/existing projects that are still using VMs or other non-Helm environments.
Codefresh is also a proven solution, used in production deployments for many more years than Jenkins X, which is a new and immature solution. If you are part of a small team that want to manually manage builder nodes, Jenkins X might look tempting if you have nothing to lose when downtime occurs. The SAAS version of Codefresh is fully managed and is used already from companies of all sizes.
In the following table, we summarize the characteristics of Jenkins X vs Codefresh:
Feature | Jenkins X | Codefresh |
---|---|---|
Git repository dashboard | No | Yes |
Git support | Yes | Yes |
Quay/ACR/JFrog/Dockerhub triggers | No | Yes |
GIT flow | Trunk-based | Any |
Versioning | Git tags /semantic | Any |
Pipeline Management | CLI | Graphical and CLI |
Built-in dynamic test environments | Yes | Yes |
Docker-based builds | Yes | Yes |
Native build caching | No | Yes |
Pipelines as code | Groovy | Yaml |
Native Monorepo support | No | Yes |
Extension mechanism | Groovy shared libraries | Docker images |
Installation | Cloud/On-prem | Cloud/On-prem/Hybrid |
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 |
Quick project skeleton creation | Yes | No |
Quick Git repo creation | Yes | No |
Syncing code to Pod | Yes | No |
Built-in Pull-request promotion | Yes | No |
Quick environmenet creation | Yes | No |
Quick cluster creation | Yes | No |
IDE integrations | Yes | No |
New to Codefresh? Create Your Free Account Today!