Securing the Supply Chain in Kubernetes


In Kubernetes, our applications are built and run as containers. Each container comes from an image, and each image is built from layers of other images. This layered process is called the 
software supply chain. Just like a factory assembling a product from parts, container images are assembled from smaller components. If even one part is flawed or tampered with, the final product can be unsafe. That’s why securing the supply chain is critical—it protects our applications from hidden vulnerabilities.

In this blog post, we’ll explore what base and parent images are, and how they shape the containers we use. We’ll look at best practices for building secure images, and how to choose the right parent image for our apps. We’ll also learn how to reduce risk by keeping our images small, modular, and stateless. 


Base vs Parent Images

When we create a container image, we don’t start from zero. We use something called a parent image. This is a starting point that already has some software or libraries inside.

But here’s the key: parent images also have their own parents. This chain continues until we reach the very first image—called the base image. It’s usually built from scratch, meaning it starts empty and adds only what’s needed.

Let’s look at an example:

httpd → debian:buster-slim → scratch

In this case:

  • httpd is the web server image we want to use.
  • It’s built on top of debian:buster-slim, a lightweight Linux system.
  • That Debian image was built from scratch, the base image.
Every image in the chain adds more software. If a security problem hides in any one of them, it affects us. That’s why we must understand where our images come from and what’s inside.


Best Practices When Building Container Images

Let’s have a look at some general recommendations to build safe images


1. Modularity

Avoid building images that include multiple applications, such as combining a web server with other background services in one image. Instead, focus on building modular images that solve a single problem at a time. For example, use one image for the web server and a separate one for the database. This way, each image contains only the libraries and dependencies it needs, without being tied to other components. 

When deployed as containers, these images come together to form a complete application made of distinct services. With this modular design, we can scale or update each service independently, without disrupting the rest of the system.


2. Stateless Containers

Containers are ephemeral in nature, we should be able to destroy them and bring them back online without losing any data. This does not mean that our applications should not deal with data or states, it wouldn’t make sense. It means that, for those applications, we should store data and states in an external volume or some kind of caching service


3. Choose the right Parent Image

Choosing the right parent image is one of the most important decisions. Let’s break it down:
  • Match Technical Needs - Start by checking your app’s requirements. For example, if your app runs on Java, find an image that includes the Java JDK.
  • Authenticity - Always choose official images or images from a verified publisher. These are tested, trusted, and built from known sources.
  • Up-to-Date - Security threats are always changing. Use images that are updated often. These images fix bugs and patch known security holes.


4. Keep It Small

Keep image size as small as possible. Smaller images are pulled faster and deployed more efficiently. Use minimal versions of official operating systems whenever available. They reduce complexity and limit potential vulnerabilities.

Only include the libraries and dependencies that the application strictly needs. After installing them, clean up any leftover files. Remove tools like curl or wget that could let an attacker download files. Also remove shells, network utilities, and text editors that are not needed for the app to run. Package managers like apt or yum should also be excluded, as they can be misused to install malicious software inside the container.

Avoid adding unnecessary files. If you need debugging tools or extra packages during development, do not include them in your production image. Instead, use separate images for production and non-production environments.

Google’s official Distroless images are a good example of this approach. These images contain only the application and its runtime—nothing else. Fewer packages mean fewer vulnerabilities. We can verify this by scanning both minimal and non-minimal images with a tool like Trivy and comparing the results.


Conclusion

In Kubernetes, security begins before we even run our app. It begins when we build our images. By choosing the right parent, staying modular, and keeping our containers clean and stateless, we protect our entire supply chain.
Previous Post Next Post