Getting Started with the Cilium Chainguard Images

Tutorial on the Cilium Chainguard Images

Cilium is open source software for transparently securing the network connectivity between application services deployed using Linux container management platforms like Docker and Kubernetes. At the foundation of Cilium is a new Linux kernel technology called eBPF, which enables the dynamic insertion of powerful security visibility and control logic within Linux itself. Because eBPF runs inside the Linux kernel, Cilium security policies can be applied and updated without any changes to the application code or container configuration.

Chainguard offers a set of minimal, security-hardened Cilium images, built on top the Wolfi OS.

We will demonstrate how to get started with the Chainguard Cilium images on an example K3s cluster. To get started, you’ll need Docker, k3d (a CLI tool to install k3s), kubectl, and the cilium CLI installed.

Note: In November 2024, after this article was first written, Chainguard made changes to its free tier of Developer Images. In order to access the non-free images used in this guide, you will need to be part of an organization that has access to them. For a full list of Developer Images that will remain in Chainguard's free tier, please refer to this support page.

What is Wolfi Wolfi is a community Linux undistro created specifically for containers. This brings distroless to a new level, including additional features targeted at securing the software supply chain of your application environment: comprehensive SBOMs, signatures, daily updates, and timely CVE fixes.
Chainguard Images Chainguard Images are a mix of distroless and development images based on Wolfi. Nightly builds make sure images are up-to-date with the latest package versions and patches from upstream Wolfi.

Start up a K3s cluster

Cilium does not work with the default Container Network Interface (CNI) plugin in K3s, so we’ll start up a CNI for our K3s cluster and disable the network policy.

To do so, create a YAML manifest named k3d.yaml with the following command:

cat > k3d.yaml <<EOF
apiVersion: k3d.io/v1alpha5
kind: Simple
image: cgr.dev/chainguard/k3s:latest
servers: 1
options:
  k3s:
    extraArgs:
      # Cilium requires network policy and CNI to be turned off
      - arg: --disable-network-policy
        nodeFilters:
          - server:*
      - arg: --flannel-backend=none
        nodeFilters:
          - server:*
EOF

Then, we’ll start up the cluster:

k3d cluster create --config k3d.yaml

If cluster creation fails with errors, check that Docker is running.

Next, Cilium requires some system mounts for the nodes. Run the following command to configure the mounts:

for node in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do
    echo "Configuring mounts for $node"
    docker exec -i $node /bin/sh <<-EOF
        mount bpffs -t bpf /sys/fs/bpf
        mount --make-shared /sys/fs/bpf
        mkdir -p /run/cilium/cgroupv2
        mount -t cgroup2 none /run/cilium/cgroupv2
        mount --make-shared /run/cilium/cgroupv2/
EOF
done

For more information, refer to the settings suggested in the Cilium documentation.

With that, you’re ready to install Cilium.

Install Cilium using Chainguard Images

We will use the Cilium CLI to install Cilium. In order to use Chainguard Images, we must first set the following values:

export ORGANIZATION=<your-Chainguard-organization>
export AGENT_IMAGE=cgr.dev/$ORGANIZATION/cilium-agent:latest
export HUBBLE_RELAY_IMAGE=cgr.dev/$ORGANIZATION/cilium-hubble-relay:latest
export HUBBLE_UI_IMAGE=cgr.dev/$ORGANIZATION/cilium-hubble-ui:latest
export HUBBLE_UI_BACKEND_IMAGE=cgr.dev/$ORGANIZATION/cilium-hubble-ui-backend:latest
export OPERATOR_IMAGE=cgr.dev/$ORGANIZATION/cilium-operator-generic:latest

Note: If you don’t remember the name of your Chainguard organization, you can find it by running chainctl iam organizations list -o table.

After that, install Cilium using the following command:

cilium install \
    --helm-set hubble.relay.enabled=true \
    --helm-set hubble.ui.enabled=true \
    --helm-set image.override=$AGENT_IMAGE \
    --helm-set hubble.relay.image.override=$HUBBLE_RELAY_IMAGE \
    --helm-set hubble.ui.frontend.image.override=$HUBBLE_UI_IMAGE \
    --helm-set hubble.ui.backend.image.override=$HUBBLE_UI_BACKEND_IMAGE \
    --helm-set operator.image.override=$OPERATOR_IMAGE

This will return output similar to the following:

🔮 Auto-detected Kubernetes kind: K3s
ℹ️  Using Cilium version 1.14.2
🔮 Auto-detected cluster name: k3d-k3s-default

Now that your cluster has a CNI plugin installed, the Pods will start to transition to the Running state. This may take a few minutes. Run the following command to check the status of the Pods:

watch kubectl get pods --all-namespaces

When all the Pods have have a status of Running or Completed, press Ctrl+C to exit the watch.

Verify that the Cilium installation is successful

Cilium comes with the connectivity test command, which is useful for verifying whether the Cilium installation was successful. Run the following command to run the connectivity test:

# We skip one of the tests because it needs `jq` util on the agent image, which we don't bundle.
cilium connectivity test \
    --external-cidr 8.0.0.0/8 \
    --external-ip 8.8.8.8 \
    --external-other-ip 8.8.4.4 \
    --test \!no-unexpected-packet-drops

This should takes about 5 minutes to complete. It will return output similar to the following:

ℹ️  Single-node environment detected, enabling single-node connectivity test
ℹ️  Monitor aggregation detected, will skip some flow validation steps
✨ [k3d-k3s-default] Creating namespace cilium-test for connectivity check...
✨ [k3d-k3s-default] Deploying echo-same-node service...
✨ [k3d-k3s-default] Deploying DNS test server configmap...
✨ [k3d-k3s-default] Deploying same-node deployment...
✨ [k3d-k3s-default] Deploying client deployment...
✨ [k3d-k3s-default] Deploying client2 deployment...
⌛ [k3d-k3s-default] Waiting for deployment cilium-test/client to become ready...
⌛ [k3d-k3s-default] Waiting for deployment cilium-test/client2 to become ready...
...

✅ All 32 tests (263 actions) successful, 2 tests skipped, 1 scenarios skipped.

Note that the exact output and results of individual tests may differ based on your local machine’s configuration.

Exploring the Cilium Hubble UI

Before you can explore the Hubble user interface, you will need to enable it with the cilium command:

cilium hubble enable --ui

Then run the following command to bring up the Hubble UI:

cilium hubble ui

A new browser window will open showing the Hubble UI. You can explore the Hubble UI to see the network traffic in your cluster. If you are running this during the connectivity test, it will show a visualization of the test traffic.

Screenshot showing a browser window with Hubble UI

Clean up your K3s cluster

Once you are done exploring Cilium, you can clean up your K3s cluster by running the following command:

k3d cluster delete

Advanced Usage

If your project requires a more specific set of packages that aren't included within the general-purpose Cilium Chainguard Image, you'll first need to check if the package you want is already available on the wolfi-os repository.

Note: If you're building on top of an image other than the wolfi-base image, the image will run as a non-root user. Because of this, if you need to install packages with apk install you need to use the USER root directive.

If the package is available, you can use the wolfi-base image in a Dockerfile and install what you need with apk, then use the resulting image as base for your app. Check the "Using the wolfi-base Image" section of our images quickstart guide for more information.

If the packages you need are not available, you can build your own apks using melange. Please refer to this guide for more information.

Last updated: 2023-12-14 00:00