Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Deploying Pulp on Kubernetes with the operator

By updated

Improve this page

Pulp logo

This guide deploys Pulp on Kubernetes with the official operator: you install the controller with Helm, then describe the instance in a Pulp custom resource, and the operator provisions the whole stack (API, content, workers, PostgreSQL, Redis, reverse proxy). Intended audience: platform teams that want a declarative, scalable artifact manager. Prerequisites: a Kubernetes cluster, kubectl and helm. You will see the installation with the right versions pinned, the Pulp resource, access to the instance, and the PostgreSQL version setting that conditions both startup and backup.

On Kubernetes, you do not install Pulp by hand: you install the Pulp Operator, a controller that watches Pulp resources and reconciles the cluster to match them. This is the operator model, declarative and self-healing.

What you will learn

  • Install the Pulp Operator with Helm, pinning the right versions.
  • Describe an instance with a Pulp custom resource.
  • Access the API and retrieve the admin password.
  • Choose the PostgreSQL version that is compatible with backup.

Prerequisites

  • A working Kubernetes cluster and kubectl configured.
  • Helm 3+ installed.
  • An available StorageClass. On a single-node cluster (k3d, Minikube), the local-path class in ReadWriteOnce is enough.

Installing the operator

The operator is deployed through its Helm chart. It installs the controller and the custom resource definitions (pulps, pulpbackups, pulprestores).

One point deserves to be made upfront: the published Helm chart pins old default versions (operator 1.3 and PostgreSQL 13). But pulpcore requires PostgreSQL 14 or later. So you install by overriding the operator image (latest version, here 2.0) and the PostgreSQL image (version 15).

  1. Add the Helm repository and create a namespace:

    Terminal window
    helm repo add pulp-operator https://github.com/pulp/pulp-k8s-resources/raw/main/helm-charts/ --force-update
    kubectl create namespace pulp
  2. Install the operator with the versions pinned:

    Terminal window
    helm -n pulp install pulp pulp-operator/pulp-operator \
    --set image=quay.io/pulp/pulp-operator:v2.0.0 \
    --set operator.relatedImages.postgres=docker.io/library/postgres:15
  3. Check that the controller is running:

    Terminal window
    kubectl -n pulp rollout status deploy/pulp-operator-controller-manager
    kubectl get crd | grep pulpproject

    The three CRDs pulps, pulpbackups and pulprestores must appear: the operator is ready to receive a Pulp resource.

Deploying Pulp with a custom resource

The instance is described in a Pulp object. The operator reads this resource and creates the matching deployments, services, secrets and volumes.

pulp.yaml
apiVersion: repo-manager.pulpproject.org/v1
kind: Pulp
metadata:
name: pulp
namespace: pulp
spec:
image_version: stable
ingress_type: nodeport
api:
replicas: 1
content:
replicas: 1
worker:
replicas: 1
file_storage_access_mode: "ReadWriteOnce"
file_storage_size: "10Gi"
file_storage_storage_class: local-path
database:
postgres_storage_class: local-path
postgres_image: docker.io/library/postgres:15
Terminal window
kubectl apply -f pulp.yaml

Two settings in the database section are decisive:

  • postgres_storage_class is mandatory. Without it, the operator stops with the error could not find any storage definition for Database.
  • postgres_image: postgres:15 aligns the database with the same version as the backup tooling (see the box above). Keep this value consistent with the --set operator.relatedImages.postgres of the installation.

Following the deployment and connecting

The operator provisions the components in order: database, migrations, content, API, workers, reverse proxy. The first deployment downloads large images, so allow a few minutes.

  1. Wait for the pods to be ready:

    Terminal window
    kubectl -n pulp get pods -w

    You should see pulp-database-0, pulp-api, pulp-content and pulp-worker as Running, and the migration and reset-admin-password jobs as Completed.

  2. Retrieve the admin password, automatically generated in a secret:

    Terminal window
    kubectl -n pulp get secret pulp-admin-password \
    -o jsonpath='{.data.password}' | base64 -d
  3. Test the API. The pulp-web-svc service (here in NodePort) exposes the instance; for a quick test, a port-forward is enough:

    Terminal window
    kubectl -n pulp port-forward svc/pulp-api-svc 24817:24817 &
    curl -s http://localhost:24817/pulp/api/v3/status/ | head

    A 200 response listing the components (core, file, container...) confirms that the instance is operational.

Troubleshooting

SymptomCauseSolution
Operator stuck, could not find any storage definition for Databasepostgres_storage_class missingAdd it under database: in the Pulp resource
pulp-api in CrashLoopBackOff, log PostgreSQL 14 or later is requiredPostgreSQL 13 image, the chart defaultPin postgres:15 at installation and in the CR
pulp-database in CrashLoop, data directory ... version X ... not compatibleLeftover PVC from another major versionDelete the Pulp resource and the PVC, redeploy
PulpBackup fails, Failed to run pg_dumpDatabase on 16 against a pg_dump 15Use PostgreSQL 15 for the database
api/worker pods Pending on volumeReadWriteOnce on a multi-node clusterSwitch to ReadWriteMany or to S3 object storage

Key takeaways

  • On Kubernetes, Pulp is deployed through the Pulp Operator and a declarative Pulp custom resource.
  • The Helm chart pins old versions: override the operator image (2.0) and PostgreSQL (15) at installation.
  • The operator provisions the whole stack: API, content, workers, PostgreSQL, Redis, reverse proxy.
  • postgres_storage_class is mandatory; PostgreSQL 15 satisfies pulpcore and the backup tool.
  • In multi-node production, artifact storage must be ReadWriteMany or S3, never local ReadWriteOnce.

Knowledge check

Six questions on what the operator provisions, what it does not take off your hands, and the storage access mode that decides whether the instance holds on several nodes.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn