RFC: First-class Kubernetes deployment for Foreman, Katello, Candlepin and Pulp
I am actively working on a Kubernetes deployment of Foreman together with Katello, Candlepin and Pulp. The implementation is already running in a real test environment rather than existing only as a collection of manifests or an architectural proposal.
Development and testing are still ongoing. The deployment is being iteratively improved based on behaviour observed in the running environment, while automated tests verify Helm rendering, configuration schemas, security boundaries, runtime contracts, migration ordering and compatibility metadata. End-to-end coverage is being expanded as the required capabilities become available in upstream images.
The project is not yet being presented as production-ready or officially supported. Before publishing the integration repository and the individual upstream pull requests, I would like to get feedback on the overall direction and on the boundaries between the projects.
I am also preparing every generally useful application change as a focused issue and pull request in its respective upstream project rather than maintaining Kubernetes-specific application patches in the integration repository.
The main principle is:
The applications should not need a “Kubernetes mode”.
Users should not have to tell Foreman, Katello, Candlepin or Pulp whether they are running on a traditional host, under systemd, in a container or in Kubernetes.
The same upstream code and published artifacts should work correctly in all supported environments. Existing standalone behaviour should remain the default. Kubernetes should only supply configuration, process arguments, storage and service endpoints through normal application interfaces.
Request for feedback
Before publishing the integration repository, I would like to ask the Foreman team two broader questions:
-
Is a first-class Kubernetes deployment a direction the Foreman project would be interested in pursuing?
-
If the implementation reaches an acceptable level of quality, would there be interest in hosting it as a project repository under the
theforemanGitHub organization?
An official project repository would make it easier to coordinate compatibility across Foreman, Katello and their dependencies, review architectural decisions and avoid creating another unofficial deployment that gradually diverges from upstream.
The main motivation is to make larger Foreman and Katello installations easier to operate. Kubernetes would allow request-serving components and background workers to be scaled independently, provide controlled rollouts and recovery, and make application dependencies and availability contracts explicit.
It would not remove the need to understand Foreman’s architecture, but it could provide a reproducible and testable deployment model for larger environments.
Goals
The proposed integration should provide:
-
official upstream applications and images without downstream forks;
-
independently deployable Foreman/Katello, Candlepin and Pulp components;
-
horizontal scaling where the application architecture allows it;
-
explicit singleton workloads where concurrency is unsafe;
-
support for external PostgreSQL, Redis/Valkey, Artemis and object storage;
-
separate and observable database migrations;
-
graceful startup, readiness, endpoint draining and shutdown;
-
non-root workloads and restricted Kubernetes permissions;
-
upgrade, backup and recovery workflows;
-
compatibility tracking between application and Kubernetes releases;
-
support for both central in-cluster services and external Smart Proxies.
The Kubernetes integration would remain a separate project. Its responsibility would be orchestration, not modification of application code.
High-level architecture
A simplified deployment looks like this:
+----------------------+
Users and clients -----> | Ingress / mTLS edge |
+----------+-----------+
|
+------------------+------------------+
| |
+------v------+ +-------v-------+
| Foreman web | | Pulp content |
| + Katello | | and registry |
+------+------+ +-------+-------+
| |
+---------+----------+ |
| | | |
+------v--+ +----v-----+ +--v-------------+ +------v------+
| Dynflow | | Katello | | Candlepin | | Pulp API |
| workers | | event | | | | and workers |
+---------+ | daemon | +----------------+ +-------------+
+----------+
PostgreSQL, Valkey, Artemis and object storage are
external or independently managed services.
Katello remains a Foreman plugin and therefore runs with Foreman. Candlepin and Pulp remain separate applications with their own images, services and release lifecycles.
No platform selector
This proposal does not add settings such as:
RUNNING_IN_KUBERNETES=true
It also does not make applications query the Kubernetes API or attempt to detect the platform.
Instead, upstream applications expose generic runtime capabilities, for example:
-
a configurable writable runtime directory;
-
an optional readiness signal tied to the actual process lifecycle;
-
a foreground process entry point suitable for any supervisor;
-
an explicit migration command;
-
configurable TLS trust;
-
correct handling of externally supplied service URLs;
-
graceful termination.
A package installed on a normal server continues using its existing defaults. A container supervisor or Kubernetes chart supplies the relevant generic options automatically.
The model is therefore:
Same application, same code paths, different orchestration.
There should be no step in Foreman, Katello, Candlepin or Pulp where the user has to select whether the application runs standalone or in Kubernetes.
Upstream changes
Every generally useful application change will be proposed to its owning project as a separate issue and pull request. Kubernetes-specific application patches will not be stored in the integration repository.
The initial set currently being prepared includes the following changes.
Foreman
-
Allow the Puma runtime directory to be configured while retaining the current
Rails.root/tmpdefault. -
Expose an optional Dynflow readiness file following the real Sidekiq lifecycle.
-
Accept a verified URL-escaped client certificate supplied by a reverse proxy while retaining the existing PEM and DER formats.
-
Allow a custom CA to be used when Dynflow connects to Redis/Valkey over TLS.
These are generic capabilities useful with containers, systemd hardening and external managed services. None of them requires Foreman to know that Kubernetes exists.
Katello
-
Preserve an explicitly configured non-default Pulp API port when constructing Pulp clients.
-
Provide a foreground Katello event-daemon runner with a configurable runtime directory and health heartbeat.
The existing standalone daemon behaviour remains available and remains the default.
Candlepin image
-
Keep the existing Tomcat server command as the default.
-
Provide an explicit database migration entry point.
-
Make the container runtime identity suitable for a non-root orchestrated environment.
Standalone Candlepin startup should not require a different workflow.
Pulpcore packaging and Pulp image
-
Correct the EL10 dependency relationship required by the object-storage Python packages.
-
Package
django-storagesfor Pulpcore without enabling it automatically. -
Include the supported S3 runtime dependencies in the Pulp image.
Filesystem storage remains the default. S3-compatible storage is selected through normal Pulp configuration, not by detecting Kubernetes.
Optional KubeVirt provider
The optional KubeVirt integration also revealed generally applicable correctness issues:
-
discover and use the supported grouped KubeVirt API version;
-
keep namespaced resources scoped to the selected namespace;
-
validate configuration before partially creating resources;
-
clean up partially created volumes safely;
-
avoid deleting storage before VM deletion has succeeded.
These changes belong in the KubeVirt provider and fog adapter, not in the Kubernetes deployment project.
Kubernetes integration repository
The separate integration repository would contain:
-
Helm charts and values schemas;
-
workload definitions and service discovery;
-
Secrets and certificate wiring;
-
migration and registration Jobs;
-
probes based on upstream runtime contracts;
-
persistent and temporary storage definitions;
-
NetworkPolicies and security contexts;
-
disruption budgets and topology rules;
-
autoscaling policies;
-
backup and restore workflows;
-
compatibility and release metadata;
-
integration, upgrade and recovery tests.
It must not contain or inject:
-
replacement Rails initializers;
-
patched Ruby or Python libraries;
-
JVM agents modifying application behaviour;
-
application preload hooks;
-
application source overlays;
-
private forks of Foreman, Katello, Candlepin or Pulp.
The integration will only consume a new runtime capability after it is available in a published upstream release or image.
Kubernetes-specific changes in this repository will be kept as logically separated commits. Application behaviour will remain owned and tested by the appropriate upstream project.
Relationship to foremanctl
This proposal is intended to complement foremanctl, not replace it.
Foremanctl is not limited to Smart Proxy deployment. It is the containerized deployment and lifecycle tool for running the Foreman and Katello stack on conventional hosts using Podman Quadlets, systemd and Ansible. It can also deploy and configure separate Smart Proxy or Capsule systems.
The Kubernetes project would provide a different orchestration layer for the same upstream applications:
| Deployment | Primary orchestration |
|---|---|
| Traditional package installation | foreman-installer and systemd |
| Host-based container deployment | foremanctl, Podman Quadlets and systemd |
| Cluster deployment | Kubernetes and Helm |
All three deployment models should consume the same generic upstream runtime contracts. A foreground process entry point, configurable runtime directory, explicit migration command or external TLS configuration should not be specific to Kubernetes and may also simplify or strengthen foremanctl deployments.
Foremanctl is also a useful existing reference for compatible Foreman, Katello, Candlepin and Pulp image versions, health checks, migrations, certificate handling and upgrade ordering. Where possible, the Kubernetes project should align with those established contracts rather than inventing an incompatible parallel model.
For distributed deployments, foremanctl could continue to manage Smart Proxy nodes outside the Kubernetes cluster. The Kubernetes-hosted Foreman control plane would connect to those proxies in the same way as any other Foreman installation.
Kubernetes control plane
Foreman / Katello / Candlepin / Pulp
|
+--------------+--------------+
| |
foremanctl-managed proxy foremanctl-managed proxy
DHCP / DNS / TFTP / REX DHCP / DNS / TFTP / REX
The initial proposal does not require adding a Kubernetes backend to foremanctl. Kubernetes orchestration can remain in its own project while both projects share upstream application contracts, compatible image sets and operational knowledge.
A deeper integration could be discussed later if the Foreman team considers a common deployment frontend useful.
Decoupling Katello from the Kubernetes node operating system
Another important benefit is reducing the direct dependency between Katello and the operating system installed on the application host.
The current Foreman with Katello documentation supports Enterprise Linux on a specific architecture. This applies to both the package-based installation and the current foremanctl container deployment, because the deployment tooling and host integration still target Enterprise Linux.
In Kubernetes, the application dependencies are delivered inside the upstream container images. Kubernetes nodes do not need Katello, Candlepin, Pulp or Foreman RPM packages installed on the host. The same application release can therefore run on clusters whose nodes use different supported Linux distributions.
This does not mean that every operating system, architecture or Kubernetes distribution would automatically be supported. The project would still need an explicit and tested matrix covering:
-
Kubernetes distributions and versions;
-
Linux node operating systems;
-
CPU architectures for which upstream images are published;
-
container runtimes;
-
ingress implementations;
-
storage classes and access modes;
-
SELinux and other host security integrations.
The important distinction is that application compatibility would primarily depend on the published container images and Kubernetes interfaces rather than on the availability of Katello packages for the node operating system.
This could make Foreman with Katello practical in environments where the organization already operates a supported Kubernetes platform but does not use Enterprise Linux for every cluster node.
Scaling model
Not every process should scale in the same way.
Foreman and Katello
Foreman web replicas can scale horizontally after their database, cache, certificates, runtime configuration and shared Katello hand-off storage are externalized.
Katello continues to run as a Foreman plugin rather than becoming an artificial standalone service.
Dynflow
Dynflow has several distinct roles:
-
exactly one orchestrator;
-
horizontally scalable general workers;
-
independently scalable hosts-queue workers.
Scaling all Sidekiq processes as one Deployment would violate the existing orchestration contract.
Katello event daemon
The event daemon remains a singleton process. Events remain durable outside the pod, while the process receives an explicit supervised foreground lifecycle.
Candlepin
Candlepin can only run with multiple replicas when:
-
embedded messaging is disabled;
-
an external Artemis broker is used;
-
Quartz uses a clustered JDBC job store;
-
every instance receives a unique identifier;
-
schema migration ownership is explicit.
The initial deployment should therefore remain single-replica unless the complete HA contract is enabled.
Pulp
Pulp already separates its API, content and worker processes:
-
API and content replicas can scale independently;
-
workers share the same database, cache and content storage;
-
filesystem storage requires a shared filesystem;
-
object storage removes that shared-filesystem requirement;
-
worker autoscaling should eventually use queue depth rather than CPU alone.
Smart Proxy and network-local services
The Kubernetes deployment would not attempt to move every infrastructure service into the cluster.
DHCP, DNS, TFTP and other network-local provisioning services would continue to be provided by Smart Proxies. These proxies could remain on dedicated machines in the relevant sites, networks or broadcast domains and register with the central Foreman instance running in Kubernetes.
This preserves one of Foreman’s important architectural strengths: the central management plane does not need direct access to every managed network.
Kubernetes cluster
+----------------------------------+
| Foreman, Katello, Candlepin, Pulp|
| Dynflow workers and central APIs |
+----------------+-----------------+
|
Smart Proxy connections
|
+-------------+-------------+
| |
Site A Smart Proxy Site B Smart Proxy
DHCP / DNS / TFTP DHCP / DNS / TFTP
Remote Execution Remote Execution
Some central and container-friendly Smart Proxy functions may also run in Kubernetes, but only where their persistence, networking and job-lifecycle requirements are properly supported.
The deployment must not assume that DHCP, DNS or TFTP belong inside the cluster.
I would therefore also appreciate feedback on whether this separation—central application services in Kubernetes and network-local provisioning through existing Smart Proxies—matches how the Foreman community would expect larger installations to evolve.
Compatibility and releases
The integration repository will maintain an explicit registry of required upstream contracts.
A Kubernetes release will only be declared supported when:
-
every required upstream change has been merged;
-
the change is present in an official release or image;
-
the exact image digest has passed integration testing;
-
migration, upgrade and rollback behaviour has been verified;
-
the compatible versions are recorded in release metadata.
A successful Helm render alone is not sufficient evidence that an application release is supported.
This also avoids assuming that the newest independently published Foreman, Katello, Candlepin and Pulp images are automatically compatible with each other.
Proposed contribution model
The work would be split as follows:
-
Create an issue in the owning upstream for every generic runtime or correctness change.
-
Submit a focused upstream pull request with standalone defaults preserved.
-
Link dependent changes across Foreman, Katello, Candlepin and Pulp.
-
Merge application capabilities before relying on them in a supported Kubernetes release.
-
Keep Kubernetes-only orchestration changes as separate, logically scoped commits in the integration repository.
-
Publish compatibility evidence for exact image versions and digests.
This should make every upstream pull request independently useful and reviewable rather than presenting maintainers with one large Kubernetes-specific patch set.
Non-goals
This proposal is not intended to:
-
replace
foreman-installer; -
replace
foremanctl; -
deprecate standalone installations;
-
merge Foreman, Katello, Candlepin and Pulp into one application or image;
-
introduce Kubernetes-specific branches throughout application code;
-
require DHCP, DNS or TFTP to run inside Kubernetes;
-
claim high availability for singleton processes that cannot safely overlap;
-
maintain downstream application forks.
Feedback requested
I would especially appreciate feedback on:
-
Whether a first-class Kubernetes deployment is a direction the Foreman project would like to pursue.
-
Whether the boundary between generic upstream runtime contracts and Kubernetes orchestration looks appropriate.
-
Whether the proposed capabilities belong in the identified upstream projects.
-
Whether there would be interest in eventually hosting the integration under the
theforemanGitHub organization. -
How the Kubernetes project should relate to foremanctl and whether sharing compatibility metadata or operational tests would be useful.
-
What level of integration and upgrade testing would be required before describing a release as supported.
-
Whether an initial experimental release should target Foreman with Katello first or also include a Foreman-only profile from the beginning.
-
Whether the proposed separation between the central Kubernetes deployment and external network-local Smart Proxies is appropriate.
-
Which Kubernetes distributions, node operating systems and deployment environments should be included in the initial test matrix.
The immediate next step is to publish the individual upstream issues and pull requests, followed by the integration repository and its compatibility matrix.
AI assistance disclosure:
- Assisted by Codex 5.6 Sol High.