Hands-on with Microsoft’s CBL-Mariner 2.0 Linux

Microsoft’s CBL-Mariner Linux distribution is becoming more and more important to Azure, both in the cloud and on premises. As well as hosting the GUI features of WSL 2 in Windows 11, it’s the container host in Azure Kubernetes Service and is available as a base container image in the Microsoft Container Registry, plus it supports distro-less containers on Azure. That makes it worth spending time with CBL-Mariner, learning its features and capabilities and seeing how it can affect your code.

Working with CBL-Mariner is a lot easier now with the release of Version 2.0. Early releases needed to be built from scratch, which required a Go-based toolchain running on Linux. Now you can simply download an ISO and install it in your choice of virtual server tools. As I was using Windows, I used Hyper-V to host my install. If you prefer Azure as a host, you can set up your own virtual machine or use a preconfigured installation from Azure’s VM library. An alternative approach is to use Docker to download and run a base image straight from Microsoft’s own Container Registry.

Installing CBL-Mariner on Hyper-V

CBL-Mariner is very much a modern Linux, designed to work with UEFI (Unified Extensible Firmware Interface) systems so you can use a Gen2 Hyper-V virtual disk to get the most from your install. There is one possible pitfall: You need to ensure that your Hyper-V UEFI environment is using the correct certificate; otherwise, the ISO will fail to boot. In the Security section of the Hyper-V settings for your virtual machine, make sure you’re using the Microsoft UEFI Certificate Authority for secure boot, not the default Windows certificate.

On first boot, you’ll be offered the choice of a text-based or graphical installer. The graphical option lets you choose a full install or a core install. I chose the full install to see how much space it used and what services it installed.

Once you’ve chosen your install, select the disk it will use and whether or not it will be encrypted. Encryption is useful in a multitenant environment or where you don’t know who has access to your system disks. The installer then formats your chosen drive and installs CBL-Mariner.  

cbl mariner 01 IDG

The graphical installer offers the choice of a full or core install.

On my test system, a full install took 85 seconds and used 2.2GB of disk space. A CBL-Mariner core install using the text installer took even less time, only 21 seconds, and needed only 297MB of space.

cbl mariner 03 IDG

A full install of CBL-Mariner took less than two minutes.

After it’s installed, one more boot takes you to a log-in prompt. Like Windows Server Core, there’s no desktop. That shouldn’t be surprising. CBL-Mariner is intended to be a headless system running on cloud servers, hosting cloud-native applications that have web UIs. A user-mode desktop only adds security risks, making the system more complex. The big benefit you get with a lightweight, console-only distribution like Microsoft’s is simplicity. If you do feel like experimenting, there is an X11 release in the CBL-Mariner package repository, most likely as part of its role in providing graphics support for WSL 2.

Small, fast, and ideal for containers

A small install like this is important when working with containers. It means that your base image will load quickly, ensuring rapid deployment of containers as applications scale in Kubernetes or in lightweight orchestration environments such as Azure Container Instances, using the default Moby-containerd package. That’s where the core release comes in; it’s small enough that it should download extremely fast over Azure’s internal network or from a local container registry to an Azure Stack HCI system. Small images will allow even greater density on systems like this, a useful feature when you’re running resource-constrained hardware on the edge.

Microsoft recommends prebuilt images like the ISO I downloaded or its own container images. Although you can take the source and customize and build it yourself, it won’t have gone through the validation process used to create Microsoft’s own releases.

To make things easier, CBL-Mariner looks like any other text-mode Linux. It doesn’t have very many services running, mainly basic file system, networking, and handling logs. That’s what you’d expect from a platform like this: the minimum possible set of services to ensure there’s very little attack surface. It’s worth spending time with the basic documentation to understand how to manage your install.

One important philosophical point with CBL-Mariner: This is not a Linux distribution that’s installed once and then continually updated. You can get security updates from Microsoft, but it’s a lot better to treat it as a piece of infrastructure that only changes when you install a whole new version. Anything that needs to live in userland should be installed as a container. The base OS is updated monthly, which gives a schedule for adding new releases to a continuous integration and continuous delivery (CI/CD) process.

Adding packages to CBL-Mariner

That’s not to say you can’t customize it for your own projects. Microsoft provides documentation and tools to add packages or build your own forks. If you are building your own version, you should build on a fork of Microsoft’s code, using git rebase to bring your code and Microsoft’s into sync with security updates and releases so you don’t get left behind with an insecure version of CBL-Mariner.

Now you can add packages to your base install. Microsoft supports RedHat’s RPM package format, with the TDNF package manager installed as part of the base release. If you haven’t used TDNF before, think of it as an updated version of the familiar yum tool. TDNF in CBL-Mariner is configured to use Microsoft’s own repositories, which contain security-patched versions of packages that are tested with CBL-Mariner. Microsoft has a service-level agreement for patching packages, which is based on the severity level of any vulnerabilities.

You can find a directory of the curated packages online. It’s a relatively short list compared to RedHat or Ubuntu, but it’s what you’d expect for a container image running on Azure. Microsoft-specific packages include .NET and ASP.NET Core (along with the Kestrel web server), as well as Microsoft’s OpenJDK release and SQL Server tool, including ODBC connectors. Alongside Microsoft’s own tools, the CBL-Mariner repository contains a long list of common Linux tools and programming environments, including Python 3, Kubernetes, and node.js. Packages are split into base and extended collections, allowing you to host most applications, with the resulting userland a way to build and manage containers for use in Azure.

With Microsoft now rolling out ARM-based servers as part of Azure, it’s good to see ARM builds of many of the CBL-Mariner packages. If you’re building containers intended to run on those new servers, it’s important to check for supported ARM versions of the packages you intend to use.

With containers the foundation of cloud-native development, it’s clear that Microsoft needed its own host OS for Azure, if only to avoid the issues that came with the loss of CoreOS. While the purchase of Kinvolk brought Flatcar in-house, there’s still a need for a tightly focused OS like CBL-Mariner that’s targeted at Azure’s needs, not just any Kubernetes platform. Combined with Kestrel and YARP and running on ARM, CBL-Mariner could also allow more applications to run on fewer servers, using less energy. That’s a very good reason for getting familiar with Microsoft’s own Linux.

Next read this: