Skip to main content
Version 3.0.0

Kyverno and private registry

Clusters that pull images from a private registry must provide access credentials to each workload. In an environment with many components — such as TDP Kubernetes — repeating that configuration manually in each chart is inefficient and error-prone.

Kyverno solves this problem as a cluster policy engine: it intercepts Pod creation and automatically injects the required imagePullSecrets, based on a centralized ClusterPolicy. This way, all components gain access to the private registry without each manifest declaring the credentials individually.

This adjustment is conditional: it only applies when the environment requires authentication to pull images from a private registry. Environments using 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 through a private registry
  • the cluster must reuse the same credentials across multiple components
  • the platform policy requires standardized use of imagePullSecrets
  • credential maintenance should be centralized

Role of Kyverno in this context

The Secret remains the object that stores registry credentials. Kyverno standardizes and enforces the use of that Secret in the cluster through a ClusterPolicy. As a result, new Pods can automatically receive the imagePullSecrets reference without repeating the same configuration in each component manifest.

Configuration overview

The flow has three steps:

  1. Install Kyverno in the cluster
  2. Create a Kubernetes Secret with the registry credentials
  3. Create a ClusterPolicy that automatically injects imagePullSecrets into all Pods

1. Install Kyverno

Terminal input
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

Create a file named tdp-registry.yaml with the content below:

tdp-registry.yaml
apiVersion: v1
kind: Secret
metadata:
name: tdp-registry
type: kubernetes.io/dockerconfigjson
stringData:
.dockerconfigjson: |
{
"auths": {
"registry.tecnisys.com.br": {
"username": "user@tecnisys.com.br",
"password": "xxxxxxxxxxx"
}
}
}

Then apply the Secret to the cluster:

Terminal input
kubectl apply -f tdp-registry.yaml

3. Create the policy to inject imagePullSecrets

Create a file named policy-kyverno.yaml:

policy-kyverno.yaml
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
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
spec:
imagePullSecrets:
- name: tdp-registry

Apply the policy:

Terminal input
kubectl apply -f policy-kyverno.yaml

Expected result

After the ClusterPolicy is applied, new Pods created in the cluster automatically receive the imagePullSecrets entry named tdp-registry, allowing private images from the Tecnisys registry to be pulled without repeating the configuration in every chart.

Where to store in the GitOps repository

Version the tdp-registry.yaml and policy-kyverno.yaml files in the GitOps repository under a policies/ folder:

tdp-gitops/
├── app-of-apps.yaml
├── apps/
├── values/
└── policies/
├── tdp-registry.yaml
└── kyverno-registry.yaml

These files are applied with kubectl apply -f, not by Argo CD. Keeping them in the repository ensures that private image credentials and policies are versioned alongside the rest of the configuration.