Kyverno and Private Registry
Clusters that download images from a private registry need to provide access credentials to each workload.
In an environment with many components—such as TDP Kubernetes—repeating this configuration manually in each chart is inefficient and creates risks of inconsistency.
Kyverno solves this problem as a cluster policy engine: it intercepts the creation of Pods and automatically injects the necessary imagePullSecrets, based on a centralized ClusterPolicy.
This way, all components start using the registry credentials without each manifest needing to declare them individually.
This adjustment is conditional: it only applies when the environment requires authentication to download images from a private registry.
Environments that use public registries or that configure imagePullSecrets directly in each chart do not need this step.
When to Consider This Adjustment
Consider this configuration when:
-
images are distributed via a private registry
-
the cluster needs to reuse the same credentials across multiple components
-
the platform policy requires standardization of the use of
imagePullSecrets -
you want to centralize the maintenance of these credentials
Kyverno's Role in this Context
The Secret remains the object that stores the registry credentials.
Kyverno's role is to enforce and standardize the use of this Secret across the cluster through a ClusterPolicy.
Thus, new Pods created in the configured namespaces can automatically receive a reference to imagePullSecrets.
Kubernetes only uses an imagePullSecrets if the referenced Secret exists in the same namespace as the Pod.
If the tdp-registry Secret does not exist in the namespace where the Pod will be created, the image download will fail even with the ClusterPolicy active.
Create the Secret in each TDP namespace before creating the Pods in that namespace.
Kyverno's ClusterPolicy acts at the time of Pod creation.
Existing workloads are not affected — only new Pods created after the policy is applied will receive the imagePullSecrets.
To apply the credentials to existing workloads, it is necessary to recreate them (e.g., kubectl rollout restart deployment/<NAME> -n <NAMESPACE>).
Configuration Overview
The flow consists of three steps:
- Install Kyverno on the cluster
- Create the registry secret in each TDP namespace
- Create a
ClusterPolicythat automatically injectsimagePullSecretsinto the Pods
1. Install Kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace
2. Create the registry secret in each namespace
The secret file contains registry access credentials in plain text. Never version this file in the Git repository. Manage credentials via a specialized tool (Sealed Secrets, External Secrets Operator, HashiCorp Vault) or create the Secret manually in each namespace.
Create the Secret with the registry credentials in each TDP namespace where the components will be installed:
kubectl create secret docker-registry tdp-registry \
--docker-server=registry.tecnisys.com.br \
--docker-username='<USERNAME>' \
--docker-password='<PASSWORD>' \
-n <NAMESPACE>
Repeat the command for each TDP namespace (e.g., tdp, tdp-kafka, tdp-airflow, etc.) or automate with a bootstrap script.
Kyverno also supports automatic copying of Secrets between namespaces using a ClusterPolicy of type clone.
With this approach, you simply create the Secret in a source namespace (e.g., kyverno) and Kyverno automatically replicates it to the destination namespaces.
See the Kyverno documentation for details on generate and clone.
3. Create the policy to inject imagePullSecrets
Create a policy-kyverno.yaml file:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: inject-tecnisys-registry-secret
annotations:
policies.kyverno.io/title: Inject Image Pull Secrets
policies.kyverno.io/description: Automatically adds the Tecnisys secret to all pods.
spec:
background: false
rules:
- name: inject-secret
matches:
any:
- resources:
kinds:
-Pod
mutate:
patchStrategicMerge:
spec:
imagePullSecrets:
- name: tdp-registry
Apply the policy:
kubectl apply -f policy-kyverno.yaml
Expected Result
After applying the ClusterPolicy, new Pods created in the cluster will receive the imagePullSecrets named tdp-registry, allowing the download of private images from the Tecnisys registry.
The Secret must exist in the Pod's namespace for Kubernetes to use it — confirm the creation of the Secret in all TDP namespaces before installing the components.
Where to Store in the GitOps Repository
Version only the policy-kyverno.yaml file in the GitOps repository within a policies/ folder:
tdp-gitops/
├── app-of-apps.yaml
├── apps/
├── values/
└── policies/
└── kyverno-registry.yaml
Do not version the tdp-registry.yaml file with credentials.
These policy files are applied with kubectl apply -f, as part of the environment bootstrap—they are not managed directly by Argo CD like Applications.
The manifests in the policies/ folder are applied once, during the environment bootstrap. They don't need to be managed by an Argo CD Application, but they can be if there is a platform Application responsible for managing cluster policies.