diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go
index 69ec349248..c4bc567e32 100755
--- a/cmd/kyverno/main.go
+++ b/cmd/kyverno/main.go
@@ -24,6 +24,7 @@ import (
 	kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
 	"github.com/kyverno/kyverno/pkg/common"
 	"github.com/kyverno/kyverno/pkg/config"
+	"github.com/kyverno/kyverno/pkg/controllers/certmanager"
 	"github.com/kyverno/kyverno/pkg/cosign"
 	dclient "github.com/kyverno/kyverno/pkg/dclient"
 	event "github.com/kyverno/kyverno/pkg/event"
@@ -342,13 +343,7 @@ func main() {
 	)
 
 	certRenewer := ktls.NewCertRenewer(kubeClient, clientConfig, ktls.CertRenewalInterval, ktls.CertValidityDuration, serverIP, log.Log.WithName("CertRenewer"))
-	certManager, err := webhookconfig.NewCertManager(
-		kubeKyvernoInformer.Core().V1().Secrets(),
-		kubeClient,
-		certRenewer,
-		log.Log.WithName("CertManager"),
-		stopCh,
-	)
+	certManager, err := certmanager.NewController(kubeKyvernoInformer.Core().V1().Secrets(), kubeClient, certRenewer)
 	if err != nil {
 		setupLog.Error(err, "failed to initialize CertManager")
 		os.Exit(1)
diff --git a/pkg/webhookconfig/certmanager.go b/pkg/controllers/certmanager/controller.go
similarity index 62%
rename from pkg/webhookconfig/certmanager.go
rename to pkg/controllers/certmanager/controller.go
index 1db964eb88..1387f90b46 100644
--- a/pkg/webhookconfig/certmanager.go
+++ b/pkg/controllers/certmanager/controller.go
@@ -1,4 +1,4 @@
-package webhookconfig
+package certmanager
 
 import (
 	"os"
@@ -6,7 +6,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/go-logr/logr"
 	"github.com/kyverno/kyverno/pkg/common"
 	"github.com/kyverno/kyverno/pkg/config"
 	"github.com/kyverno/kyverno/pkg/tls"
@@ -16,7 +15,7 @@ import (
 	"k8s.io/client-go/tools/cache"
 )
 
-type Interface interface {
+type Controller interface {
 	// Run starts the certManager
 	Run(stopCh <-chan struct{})
 
@@ -27,143 +26,119 @@ type Interface interface {
 	// GetTLSPemPair gets the existing TLSPemPair from the secret
 	GetTLSPemPair() (*tls.PemPair, error)
 }
-type certManager struct {
+
+type controller struct {
 	renewer        *tls.CertRenewer
 	secretInformer informerv1.SecretInformer
 	secretQueue    chan bool
-	stopCh         <-chan struct{}
-	log            logr.Logger
 }
 
-func NewCertManager(secretInformer informerv1.SecretInformer, kubeClient kubernetes.Interface, certRenewer *tls.CertRenewer, log logr.Logger, stopCh <-chan struct{}) (Interface, error) {
-	manager := &certManager{
+func NewController(secretInformer informerv1.SecretInformer, kubeClient kubernetes.Interface, certRenewer *tls.CertRenewer) (Controller, error) {
+	manager := &controller{
 		renewer:        certRenewer,
 		secretInformer: secretInformer,
 		secretQueue:    make(chan bool, 1),
-		stopCh:         stopCh,
-		log:            log,
 	}
-
 	secretInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 		AddFunc:    manager.addSecretFunc,
 		UpdateFunc: manager.updateSecretFunc,
 	})
-
 	return manager, nil
 }
 
-func (m *certManager) addSecretFunc(obj interface{}) {
+func (m *controller) addSecretFunc(obj interface{}) {
 	secret := obj.(*v1.Secret)
 	if secret.GetNamespace() != config.KyvernoNamespace {
 		return
 	}
-
 	val, ok := secret.GetAnnotations()[tls.SelfSignedAnnotation]
 	if !ok || val != "true" {
 		return
 	}
-
 	m.secretQueue <- true
 }
 
-func (m *certManager) updateSecretFunc(oldObj interface{}, newObj interface{}) {
+func (m *controller) updateSecretFunc(oldObj interface{}, newObj interface{}) {
 	old := oldObj.(*v1.Secret)
 	new := newObj.(*v1.Secret)
 	if new.GetNamespace() != config.KyvernoNamespace {
 		return
 	}
-
 	val, ok := new.GetAnnotations()[tls.SelfSignedAnnotation]
 	if !ok || val != "true" {
 		return
 	}
-
 	if reflect.DeepEqual(old.DeepCopy().Data, new.DeepCopy().Data) {
 		return
 	}
-
 	m.secretQueue <- true
-	m.log.V(4).Info("secret updated, reconciling webhook configurations")
+	logger.V(4).Info("secret updated, reconciling webhook configurations")
 }
 
-func (m *certManager) InitTLSPemPair() {
+func (m *controller) InitTLSPemPair() {
 	_, err := m.renewer.InitTLSPemPair()
 	if err != nil {
-		m.log.Error(err, "initialization error")
+		logger.Error(err, "initialization error")
 		os.Exit(1)
 	}
 }
 
-func (m *certManager) GetTLSPemPair() (*tls.PemPair, error) {
+func (m *controller) GetTLSPemPair() (*tls.PemPair, error) {
 	var keyPair *tls.PemPair
 	var err error
-
 	retryReadTLS := func() error {
 		keyPair, err = tls.ReadTLSPair(m.renewer.ClientConfig(), m.renewer.Client())
 		if err != nil {
 			return err
 		}
-
-		m.log.Info("read TLS pem pair from the secret")
+		logger.Info("read TLS pem pair from the secret")
 		return nil
 	}
-
 	msg := "failed to read TLS pair"
-	f := common.RetryFunc(time.Second, time.Minute, retryReadTLS, msg, m.log.WithName("GetTLSPemPair/Retry"))
-	err = f()
-
-	return keyPair, err
+	f := common.RetryFunc(time.Second, time.Minute, retryReadTLS, msg, logger.WithName("GetTLSPemPair/Retry"))
+	return keyPair, f()
 }
 
-func (m *certManager) Run(stopCh <-chan struct{}) {
-	m.log.Info("start managing certificate")
+func (m *controller) Run(stopCh <-chan struct{}) {
+	logger.Info("start managing certificate")
 	certsRenewalTicker := time.NewTicker(tls.CertRenewalInterval)
 	defer certsRenewalTicker.Stop()
-
 	for {
 		select {
 		case <-certsRenewalTicker.C:
 			valid, err := m.renewer.ValidCert()
 			if err != nil {
-				m.log.Error(err, "failed to validate cert")
-
+				logger.Error(err, "failed to validate cert")
 				if !strings.Contains(err.Error(), tls.ErrorsNotFound) {
 					continue
 				}
 			}
-
 			if valid {
 				continue
 			}
-
-			m.log.Info("rootCA is about to expire, trigger a rolling update to renew the cert")
+			logger.Info("rootCA is about to expire, trigger a rolling update to renew the cert")
 			if err := m.renewer.RollingUpdate(); err != nil {
-				m.log.Error(err, "unable to trigger a rolling update to renew rootCA, force restarting")
+				logger.Error(err, "unable to trigger a rolling update to renew rootCA, force restarting")
 				os.Exit(1)
 			}
-
 		case <-m.secretQueue:
 			valid, err := m.renewer.ValidCert()
 			if err != nil {
-				m.log.Error(err, "failed to validate cert")
-
+				logger.Error(err, "failed to validate cert")
 				if !strings.Contains(err.Error(), tls.ErrorsNotFound) {
 					continue
 				}
 			}
-
 			if valid {
 				continue
 			}
-
-			m.log.Info("rootCA has changed, updating webhook configurations")
+			logger.Info("rootCA has changed, updating webhook configurations")
 			if err := m.renewer.RollingUpdate(); err != nil {
-				m.log.Error(err, "unable to trigger a rolling update to re-register webhook server, force restarting")
+				logger.Error(err, "unable to trigger a rolling update to re-register webhook server, force restarting")
 				os.Exit(1)
 			}
-
-		case <-m.stopCh:
-			m.log.V(2).Info("stopping cert renewer")
+		case <-stopCh:
+			logger.V(2).Info("stopping cert renewer")
 			return
 		}
 	}
diff --git a/pkg/controllers/certmanager/log.go b/pkg/controllers/certmanager/log.go
new file mode 100644
index 0000000000..16e79a765b
--- /dev/null
+++ b/pkg/controllers/certmanager/log.go
@@ -0,0 +1,5 @@
+package certmanager
+
+import "sigs.k8s.io/controller-runtime/pkg/log"
+
+var logger = log.Log.WithName("certmanager-controller")
diff --git a/pkg/controllers/controller.go b/pkg/controllers/controller.go
new file mode 100644
index 0000000000..64eedb03cd
--- /dev/null
+++ b/pkg/controllers/controller.go
@@ -0,0 +1,6 @@
+package controllers
+
+type Controller interface {
+	// Run starts the controller
+	Run(stopCh <-chan struct{})
+}