werf v1.2 is now stable! Here’s what it is all about
werf is a CLI Open Source tool for building applications and deploying them to Kubernetes clusters. Version 1.2 features many new changes and improvements. We have been thoroughly testing and refining them as part of the Early-Access version over the last eleven months (since January 2021). Finally, we are pleased to announce that it has been promoted to Stable!
There is a fairly detailed changelog in the project documentation for those who are interested in the list of changes introduced in werf v1.2 (meanwhile, the most curious users followed its progress on GitHub and the Telegram chat). This article, however, does not revolve around the changes. Rather, it presents the latest version of werf and discusses its purpose and basic operation principles.
Version 1.1 was more like a constructor. It offered many options for implementing things that were burdened by subsequent potential problems if the user did not take into account all the details of the approach they chose. werf v1.2 takes a step toward systemizing and improving delivery consistency by simplifying it and rendering it more predictable.
What is werf
werf is an Open Source CLI tool for consistent building and delivery of applications in Kubernetes. You can use it to implement a complete CI/CD cycle.
Typically, an engineer has to manually configure and integrate all the CI/CD system components to create a pipeline for an application to be built and deployed using Docker and Helm. They have to manually configure deterministic image tagging, link building, and deployment at the CI system level, set up automatic image cleanup, and much more.
werf provides for ready-made integration of all the CI/CD components. Not only does the user get a fully deterministic, ready-to-use pipeline for creating and delivering theapplication, but also an array of unique features made possible by the tight integration of Git, Docker, Helm, CI system, and the container registry. For example, werf cleanup performs a smart cleanup of the container registry. The command takes into account both the state and history of the Git repository while leaving images currently in use in the cluster intact.
In the case of GitLab CI, you can implement the entire cycle of building an application, deploying it, and automatic images/cache/temporary file cleanup with just three commands:
. $(werf ci-env gitlab --as-file) # Integrating with GitLab CI. werf converge # Building and deploying. werf cleanup # Cleaning up the container registry.
At the same time, with werf, the user can fine-tune the pipeline described above or implement even more complex and non-standard CI/CD schemes. We’ll discuss them in greater detail in the “Principle #3. Various delivery methods” section.
Principle #1. Giterminism
What is the main factor in ensuring that builds can be reproduced in any environment? The answer is obvious: the single “source of truth” must be immutable and unique. Git is such a “source of truth” for werf.
We use the concept of Giterminism (Git + determinism) to describe werf’s basic operation principle. You can think of Giterminism as a mode of an operation whose parameters are all determined by Git. werf reads configurations and build context files from the current Git commit, thus excluding external dependencies.
Giterminism is ensured by:
- werf reading the all the configuration and build context directly from Git;
- most non-deterministic entities (e.g., environment variables and unversioned files) being restricted by default during both deploying and building;
- the Docker images to be built and the Kubernetes resources to be deployed are fully determined by Git. Consequently, a) werf manages image tags (the user gets the tagged images); b) content-based tagging* is used to ensure that tags meet reassembly and reproducibility needs as well as implement the principle of image immutability.
* A few words about werf tags. You can use aliases to create custom tags in addition to content-based tags. You can also export images from the werf ecosystem using the
werf export command if content-based tagging is not necessary.
With Giterminism, you can control an application’s predictability, reproducibility, and ease of maintenance. Thus, determinism refers to certain input data and the environment for a deterministic algorithm (an algorithmic process that produces a unique, predetermined result for given input data).
The default settings are as strict as possible in order to alert the user to potential problems and to prevent the creation of unreliable, unpredictable automation.
At the same time, you do not have to stick to the default deterministic configuration. For example, you can use uncommitted and untracked files or add external dependencies. But this must be explicitly specified (declared) in
Principle #2. Common technologies
werf integrates many well-known tools that are popular among developers and DevOps/SRE engineers. Each tool plays a specific role in the CI/CD process.
|Technology||What it does when werf is in use|
|Git||Stores code and configurations. werf uses the history and state of the Git repository to build, cache, and clean up images.|
|Kubernetes||A platform for running containerized applications.|
|Container registry||Stores bundles, containers, cache, and metadata.|
|Docker||Builds and runs images.|
|Helm||Deploys applications. Manages configuration for Kubernetes including templating, parameterization, and dependency management.|
|CI system||Continuous code integration (werf is compatible with any CI system; it integrates with GitLab and GitHub Actions in a single command).|
|Docker Compose||Facilitates local development.|
Let’s take a closer look at how werf uses and extends Docker, Helm, and the container registry.
werf supports building based on regular Dockerfiles. You can use the existing files as is; no modifications are required.
An alternate syntax, Stapel, is also supported. It is fully consistent with the Dockerfile instructions’ capabilities (while extending them and making them more flexible) and provides additional functionality.
The key feature of Stapel is close integration with Git in image building. You can add files to the build in a floating fashion (instead of adding them at a specific build stage, as with Docker): define the dependencies for the commands and the files will be added in an optimal way. The result is significantly shorter build times due to incremental changes to the source code stored in the Git repository.
Moreover, Stapel syntax is easy to maintain thanks to its YAML format and templating capabilities.
The article “werf vs. Docker: What is the difference when it comes to building images?” contains a detailed description of all the differences between the two tools and discusses the peculiarities of using werf.
Helm is a popular solution for deploying applications to Kubernetes. werf leverages an extended and improved Helm (we have forked the upstream project, enhanced it with some patches, and built it into werf) for its deployment needs.
- Backward compatibility: you can use Helm charts with werf as is without tweaking them in any way. werf supports regular Helm templates and handles values similarly.
- Integration with the built images: access dynamically generated image tags via values.
- werf supports advanced status tracking and enhanced resource deployment configurations. Furthermore, it can output the logs of running Pods (we have developed a separate Open Source library for this called kubedog).
- werf can handle secrets out of the box.
- werf can automatically attach annotations and labels with valuable information (e.g., a link to the job in the CI/CD system and the Git commit used as the basis for a deployed resource) to resources.
- werf protects against conflicts for parallel deployments to the same environment: thanks to distributed locking, different hosts can now be used for deployment.
The article “werf vs. Helm: Should you even compare them?” explains in detail how Helm is integrated into werf processes.
werf stores final images, bundles (more about them below), build caches, and metadata in the container registry. Metadata allows werf to build images efficiently and clean them up based on their Git history.
In addition to storing artifacts, werf uses the container registry to ensure the performance and reproducibility of all shared builds. Thus, with werf, the user gets a ready-to-use, flexible, scalable, and productive CI/CD process – no need for any additional customizations.
It supports different storage schemes based on various container registry types.
Principle #3. Various delivery methods
werf provides several methods for setting up a pipeline. The user can use basic commands and supplement them with various options.
The first method is based on the
werf converge command. With it, you can build images and deploy them to a Kubernetes cluster “with a click of a button.” For the user, the process is straightforward, but for werf, it is more complicated, since it:
- analyzes the current state of the configuration in the Git commit;
- builds missing images and publishes them to the repository;
- brings the Kubernetes cluster to its most up-to-date state.
The second method is based on the
werf bundle publish and
werf bundle apply commands. With bundles, you can deploy an application even if you do not have access to the Git repository where the application was built. Here is what each command does:
werf bundle publishmakes and publishes bundles (built images and instructions for deploying them, packaged into artifacts) to the container registry;
werf bundle applydeploys the bundle from the container registry (access to the Git repository is no longer required).
In addition, there are commands for using werf in combination with other deployment tools:
werf export— for building werf-independent images;
werf render— for building images and generating manifests (no deployment);
werf run— for building images and running containers.
How to try werf
Quick start instructions for the current version of werf are available on the project website.
You can also find a detailed hands-on guide for developers using different languages/frameworks*. With it, you can learn how to use werf in practice – it’s a perfect starting point for people who are interested in werf’s features but have never tried it before. It should work even for those who have no experience with Kubernetes at the moment.
* The “First steps” section of the guide is available for all frameworks, while the “Real-world apps” section is currently available for Node.js, Laravel, and Ruby on Rails only.
Despite the stable status of werf v1.2, we continue to expand its functionality and refine it. We also plan to integrate with Buildah in the following areas:
- Dockerfile support (done).
- Stapel support.
- Instructions for running inside a Docker container (dind) and in Kubernetes (WIP).
- An efficient, versioned cache in the container registry instead of mounts and multi-stage builds.
We have been using werf v1.2 in production for a long time and are very confident in its robustness and stability. However, this does not mean that werf is completely immune to any issues. If you have any questions about its latest release or about werf in general, feel free to contact us via the project’s Telegram chat. We’ll be happy to help!
P.S. Follow @werf_io to stay updated about project news as well.