mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
feat: add separate reports-controller (#5352)
* feat: add separate reports-controller Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * controllers Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * remove commented code Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * update code Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * update code Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * update code Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * exit Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
36abeaecf9
commit
ef81344c32
3 changed files with 403 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,6 +8,7 @@ cmd/cli/kubectl-kyverno/kubectl-kyverno
|
|||
cmd/initContainer/kyvernopre
|
||||
cmd/kyverno/kyverno
|
||||
cmd/cleanup-controller/cleanup-controller
|
||||
cmd/reports-controller/reports-controller
|
||||
/release
|
||||
.DS_Store
|
||||
.tools
|
||||
|
|
44
Makefile
44
Makefile
|
@ -26,10 +26,12 @@ KYVERNOPRE_IMAGE := kyvernopre
|
|||
KYVERNO_IMAGE := kyverno
|
||||
CLI_IMAGE := kyverno-cli
|
||||
CLEANUP_IMAGE := cleanup-controller
|
||||
REPORTS_IMAGE := reports-controller
|
||||
REPO_KYVERNOPRE := $(REGISTRY)/$(REPO)/$(KYVERNOPRE_IMAGE)
|
||||
REPO_KYVERNO := $(REGISTRY)/$(REPO)/$(KYVERNO_IMAGE)
|
||||
REPO_CLI := $(REGISTRY)/$(REPO)/$(CLI_IMAGE)
|
||||
REPO_CLEANUP := $(REGISTRY)/$(REPO)/$(CLEANUP_IMAGE)
|
||||
REPO_REPORTS := $(REGISTRY)/$(REPO)/$(REPORTS_IMAGE)
|
||||
USE_CONFIG ?= standard
|
||||
|
||||
#########
|
||||
|
@ -136,10 +138,12 @@ KYVERNO_DIR := $(CMD_DIR)/kyverno
|
|||
KYVERNOPRE_DIR := $(CMD_DIR)/initContainer
|
||||
CLI_DIR := $(CMD_DIR)/cli/kubectl-kyverno
|
||||
CLEANUP_DIR := $(CMD_DIR)/cleanup-controller
|
||||
REPORTS_DIR := $(CMD_DIR)/reports-controller
|
||||
KYVERNO_BIN := $(KYVERNO_DIR)/kyverno
|
||||
KYVERNOPRE_BIN := $(KYVERNOPRE_DIR)/kyvernopre
|
||||
CLI_BIN := $(CLI_DIR)/kubectl-kyverno
|
||||
CLEANUP_BIN := $(CLEANUP_DIR)/cleanup-controller
|
||||
REPORTS_BIN := $(REPORTS_DIR)/reports-controller
|
||||
PACKAGE ?= github.com/kyverno/kyverno
|
||||
CGO_ENABLED ?= 0
|
||||
LD_FLAGS = "-s -w -X $(PACKAGE)/pkg/version.BuildVersion=$(GIT_VERSION) -X $(PACKAGE)/pkg/version.BuildHash=$(GIT_HASH) -X $(PACKAGE)/pkg/version.BuildTime=$(TIMESTAMP)"
|
||||
|
@ -199,6 +203,10 @@ $(CLEANUP_BIN): fmt vet
|
|||
@echo Build cleanup controller binary... >&2
|
||||
@CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) go build -o $(CLEANUP_BIN) -ldflags=$(LD_FLAGS) $(CLEANUP_DIR)
|
||||
|
||||
$(REPORTS_BIN): fmt vet
|
||||
@echo Build reports controller binary... >&2
|
||||
@CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) go build -o $(REPORTS_BIN) -ldflags=$(LD_FLAGS) $(REPORTS_DIR)
|
||||
|
||||
.PHONY: build-kyvernopre
|
||||
build-kyvernopre: $(KYVERNOPRE_BIN) ## Build kyvernopre binary
|
||||
|
||||
|
@ -211,7 +219,10 @@ build-cli: $(CLI_BIN) ## Build cli binary
|
|||
.PHONY: build-cleanup-controller
|
||||
build-cleanup-controller: $(CLEANUP_BIN) ## Build cleanup controller binary
|
||||
|
||||
build-all: build-kyvernopre build-kyverno build-cli build-cleanup-controller ## Build all binaries
|
||||
.PHONY: build-reports-controller
|
||||
build-reports-controller: $(REPORTS_BIN) ## Build reports controller binary
|
||||
|
||||
build-all: build-kyvernopre build-kyverno build-cli build-cleanup-controller build-reports-controller ## Build all binaries
|
||||
|
||||
##############
|
||||
# BUILD (KO) #
|
||||
|
@ -242,8 +253,13 @@ ko-build-cleanup-controller: $(KO) ## Build cleanup controller local image (with
|
|||
@echo Build cleanup controller local image with ko... >&2
|
||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=ko.local $(KO) build $(CLEANUP_DIR) --preserve-import-paths --tags=$(KO_TAGS_DEV) --platform=$(LOCAL_PLATFORM)
|
||||
|
||||
.PHONY: ko-build-reports-controller
|
||||
ko-build-reports-controller: $(KO) ## Build reports controller local image (with ko)
|
||||
@echo Build reports controller local image with ko... >&2
|
||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=ko.local $(KO) build $(REPORTS_DIR) --preserve-import-paths --tags=$(KO_TAGS_DEV) --platform=$(LOCAL_PLATFORM)
|
||||
|
||||
.PHONY: ko-build-all
|
||||
ko-build-all: ko-build-kyvernopre ko-build-kyverno ko-build-cli ko-build-cleanup-controller ## Build all local images (with ko)
|
||||
ko-build-all: ko-build-kyvernopre ko-build-kyverno ko-build-cli ko-build-cleanup-controller ko-build-reports-controller ## Build all local images (with ko)
|
||||
|
||||
################
|
||||
# PUBLISH (KO) #
|
||||
|
@ -253,6 +269,7 @@ REGISTRY_USERNAME ?= dummy
|
|||
KO_KYVERNOPRE_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/initcontainer
|
||||
KO_KYVERNO_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/kyverno
|
||||
KO_CLEANUP_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/cleanup-controller
|
||||
KO_REPORTS_IMAGE := ko.local/github.com/kyverno/kyverno/cmd/reports-controller
|
||||
|
||||
.PHONY: ko-login
|
||||
ko-login: $(KO)
|
||||
|
@ -274,6 +291,10 @@ ko-publish-cli: ko-login ## Build and publish cli image (with ko)
|
|||
ko-publish-cleanup-controller: ko-login ## Build and publish cleanup controller image (with ko)
|
||||
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLEANUP) $(KO) build $(CLEANUP_DIR) --bare --tags=$(KO_TAGS) --platform=$(PLATFORMS)
|
||||
|
||||
.PHONY: ko-publish-reports-controller
|
||||
ko-publish-reports-controller: ko-login ## Build and publish reports controller image (with ko)
|
||||
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_REPORTS) $(KO) build $(REPORTS_DIR) --bare --tags=$(KO_TAGS) --platform=$(PLATFORMS)
|
||||
|
||||
.PHONY: ko-publish-kyvernopre-dev
|
||||
ko-publish-kyvernopre-dev: ko-login ## Build and publish kyvernopre dev image (with ko)
|
||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_KYVERNOPRE) $(KO) build $(KYVERNOPRE_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
||||
|
@ -290,11 +311,15 @@ ko-publish-cli-dev: ko-login ## Build and publish cli dev image (with ko)
|
|||
ko-publish-cleanup-controller-dev: ko-login ## Build and publish cleanup controller dev image (with ko)
|
||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_CLEANUP) $(KO) build $(CLEANUP_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
||||
|
||||
.PHONY: ko-publish-reports-controller-dev
|
||||
ko-publish-reports-controller-dev: ko-login ## Build and publish reports controller dev image (with ko)
|
||||
@LD_FLAGS=$(LD_FLAGS_DEV) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_REPORTS) $(KO) build $(REPORTS_DIR) --bare --tags=$(KO_TAGS_DEV) --platform=$(PLATFORMS)
|
||||
|
||||
.PHONY: ko-publish-all
|
||||
ko-publish-all: ko-publish-kyvernopre ko-publish-kyverno ko-publish-cli ko-publish-cleanup-controller ## Build and publish all images (with ko)
|
||||
ko-publish-all: ko-publish-kyvernopre ko-publish-kyverno ko-publish-cli ko-publish-cleanup-controller ko-publish-reports-controller ## Build and publish all images (with ko)
|
||||
|
||||
.PHONY: ko-publish-all-dev
|
||||
ko-publish-all-dev: ko-publish-kyvernopre-dev ko-publish-kyverno-dev ko-publish-cli-dev ko-publish-cleanup-controller-dev ## Build and publish all dev images (with ko)
|
||||
ko-publish-all-dev: ko-publish-kyvernopre-dev ko-publish-kyverno-dev ko-publish-cli-dev ko-publish-cleanup-controller-dev ko-publish-reports-controller-dev ## Build and publish all dev images (with ko)
|
||||
|
||||
#################
|
||||
# BUILD (IMAGE) #
|
||||
|
@ -303,6 +328,7 @@ ko-publish-all-dev: ko-publish-kyvernopre-dev ko-publish-kyverno-dev ko-publish-
|
|||
LOCAL_KYVERNOPRE_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_KYVERNOPRE_IMAGE)
|
||||
LOCAL_KYVERNO_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_KYVERNO_IMAGE)
|
||||
LOCAL_CLEANUP_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_CLEANUP_IMAGE)
|
||||
LOCAL_REPORTS_IMAGE := $($(shell echo $(BUILD_WITH) | tr '[:lower:]' '[:upper:]')_REPORTS_IMAGE)
|
||||
|
||||
.PHONY: image-build-kyvernopre
|
||||
image-build-kyvernopre: $(BUILD_WITH)-build-kyvernopre
|
||||
|
@ -316,6 +342,9 @@ image-build-cli: $(BUILD_WITH)-build-cli
|
|||
.PHONY: image-build-cleanup-controller
|
||||
image-build-cleanup-controller: $(BUILD_WITH)-build-cleanup-controller
|
||||
|
||||
.PHONY: image-build-reports-controller
|
||||
image-build-reports-controller: $(BUILD_WITH)-build-reports-controller
|
||||
|
||||
.PHONY: image-build-all
|
||||
image-build-all: $(BUILD_WITH)-build-all
|
||||
|
||||
|
@ -726,8 +755,13 @@ kind-load-cleanup-controller: $(KIND) image-build-cleanup-controller ## Build cl
|
|||
@echo Load cleanup controller image... >&2
|
||||
@$(KIND) load docker-image --name $(KIND_NAME) $(LOCAL_CLEANUP_IMAGE):$(IMAGE_TAG_DEV)
|
||||
|
||||
.PHONY: kind-load-reports-controller
|
||||
kind-load-reports-controller: $(KIND) image-build-reports-controller ## Build reports controller image and load it in kind cluster
|
||||
@echo Load reports controller image... >&2
|
||||
@$(KIND) load docker-image --name $(KIND_NAME) $(LOCAL_REPORTS_IMAGE):$(IMAGE_TAG_DEV)
|
||||
|
||||
.PHONY: kind-load-all
|
||||
kind-load-all: kind-load-kyvernopre kind-load-kyverno kind-load-cleanup-controller ## Build images and load them in kind cluster
|
||||
kind-load-all: kind-load-kyvernopre kind-load-kyverno kind-load-cleanup-controller kind-load-reports-controller ## Build images and load them in kind cluster
|
||||
|
||||
.PHONY: kind-deploy-kyverno
|
||||
kind-deploy-kyverno: $(HELM) kind-load-all ## Build images, load them in kind cluster and deploy kyverno helm chart
|
||||
|
|
363
cmd/reports-controller/main.go
Normal file
363
cmd/reports-controller/main.go
Normal file
|
@ -0,0 +1,363 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/cmd/internal"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
dynamicclient "github.com/kyverno/kyverno/pkg/clients/dynamic"
|
||||
kubeclient "github.com/kyverno/kyverno/pkg/clients/kube"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/clients/kyverno"
|
||||
metadataclient "github.com/kyverno/kyverno/pkg/clients/metadata"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
admissionreportcontroller "github.com/kyverno/kyverno/pkg/controllers/report/admission"
|
||||
aggregatereportcontroller "github.com/kyverno/kyverno/pkg/controllers/report/aggregate"
|
||||
backgroundscancontroller "github.com/kyverno/kyverno/pkg/controllers/report/background"
|
||||
resourcereportcontroller "github.com/kyverno/kyverno/pkg/controllers/report/resource"
|
||||
"github.com/kyverno/kyverno/pkg/cosign"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context/resolvers"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/leaderelection"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
kubeinformers "k8s.io/client-go/informers"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
metadatainformers "k8s.io/client-go/metadata/metadatainformer"
|
||||
kyamlopenapi "sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
)
|
||||
|
||||
const (
|
||||
resyncPeriod = 15 * time.Minute
|
||||
)
|
||||
|
||||
func setupRegistryClient(ctx context.Context, logger logr.Logger, lister corev1listers.SecretNamespaceLister, imagePullSecrets string, allowInsecureRegistry bool) (registryclient.Client, error) {
|
||||
logger = logger.WithName("registry-client")
|
||||
logger.Info("setup registry client...", "secrets", imagePullSecrets, "insecure", allowInsecureRegistry)
|
||||
registryOptions := []registryclient.Option{
|
||||
registryclient.WithTracing(),
|
||||
}
|
||||
secrets := strings.Split(imagePullSecrets, ",")
|
||||
if imagePullSecrets != "" && len(secrets) > 0 {
|
||||
registryOptions = append(registryOptions, registryclient.WithKeychainPullSecrets(ctx, lister, secrets...))
|
||||
}
|
||||
if allowInsecureRegistry {
|
||||
registryOptions = append(registryOptions, registryclient.WithAllowInsecureRegistry())
|
||||
}
|
||||
return registryclient.New(registryOptions...)
|
||||
}
|
||||
|
||||
func setupCosign(logger logr.Logger, imageSignatureRepository string) {
|
||||
logger = logger.WithName("cosign")
|
||||
logger.Info("setup cosign...", "repository", imageSignatureRepository)
|
||||
if imageSignatureRepository != "" {
|
||||
cosign.ImageSignatureRepository = imageSignatureRepository
|
||||
}
|
||||
}
|
||||
|
||||
func createReportControllers(
|
||||
backgroundScan bool,
|
||||
admissionReports bool,
|
||||
reportsChunkSize int,
|
||||
backgroundScanWorkers int,
|
||||
client dclient.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
rclient registryclient.Client,
|
||||
metadataFactory metadatainformers.SharedInformerFactory,
|
||||
kubeInformer kubeinformers.SharedInformerFactory,
|
||||
kyvernoInformer kyvernoinformer.SharedInformerFactory,
|
||||
configMapResolver resolvers.ConfigmapResolver,
|
||||
backgroundScanInterval time.Duration,
|
||||
configuration config.Configuration,
|
||||
eventGenerator event.Interface,
|
||||
) ([]internal.Controller, func(context.Context) error) {
|
||||
var ctrls []internal.Controller
|
||||
var warmups []func(context.Context) error
|
||||
kyvernoV1 := kyvernoInformer.Kyverno().V1()
|
||||
kyvernoV2Alpha1 := kyvernoInformer.Kyverno().V2alpha1()
|
||||
if backgroundScan || admissionReports {
|
||||
resourceReportController := resourcereportcontroller.NewController(
|
||||
client,
|
||||
kyvernoV1.Policies(),
|
||||
kyvernoV1.ClusterPolicies(),
|
||||
)
|
||||
warmups = append(warmups, func(ctx context.Context) error {
|
||||
return resourceReportController.Warmup(ctx)
|
||||
})
|
||||
ctrls = append(ctrls, internal.NewController(
|
||||
resourcereportcontroller.ControllerName,
|
||||
resourceReportController,
|
||||
resourcereportcontroller.Workers,
|
||||
))
|
||||
ctrls = append(ctrls, internal.NewController(
|
||||
aggregatereportcontroller.ControllerName,
|
||||
aggregatereportcontroller.NewController(
|
||||
kyvernoClient,
|
||||
metadataFactory,
|
||||
kyvernoV1.Policies(),
|
||||
kyvernoV1.ClusterPolicies(),
|
||||
resourceReportController,
|
||||
reportsChunkSize,
|
||||
),
|
||||
aggregatereportcontroller.Workers,
|
||||
))
|
||||
if admissionReports {
|
||||
ctrls = append(ctrls, internal.NewController(
|
||||
admissionreportcontroller.ControllerName,
|
||||
admissionreportcontroller.NewController(
|
||||
kyvernoClient,
|
||||
metadataFactory,
|
||||
resourceReportController,
|
||||
),
|
||||
admissionreportcontroller.Workers,
|
||||
))
|
||||
}
|
||||
if backgroundScan {
|
||||
ctrls = append(ctrls, internal.NewController(
|
||||
backgroundscancontroller.ControllerName,
|
||||
backgroundscancontroller.NewController(
|
||||
client,
|
||||
kyvernoClient,
|
||||
rclient,
|
||||
metadataFactory,
|
||||
kyvernoV1.Policies(),
|
||||
kyvernoV1.ClusterPolicies(),
|
||||
kubeInformer.Core().V1().Namespaces(),
|
||||
kyvernoV2Alpha1.PolicyExceptions(),
|
||||
resourceReportController,
|
||||
configMapResolver,
|
||||
backgroundScanInterval,
|
||||
configuration,
|
||||
eventGenerator,
|
||||
),
|
||||
backgroundScanWorkers,
|
||||
))
|
||||
}
|
||||
}
|
||||
return ctrls, func(ctx context.Context) error {
|
||||
for _, warmup := range warmups {
|
||||
if err := warmup(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func createrLeaderControllers(
|
||||
backgroundScan bool,
|
||||
admissionReports bool,
|
||||
reportsChunkSize int,
|
||||
backgroundScanWorkers int,
|
||||
kubeInformer kubeinformers.SharedInformerFactory,
|
||||
kyvernoInformer kyvernoinformer.SharedInformerFactory,
|
||||
metadataInformer metadatainformers.SharedInformerFactory,
|
||||
kyvernoClient versioned.Interface,
|
||||
dynamicClient dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
configuration config.Configuration,
|
||||
eventGenerator event.Interface,
|
||||
configMapResolver resolvers.ConfigmapResolver,
|
||||
backgroundScanInterval time.Duration,
|
||||
) ([]internal.Controller, func(context.Context) error, error) {
|
||||
reportControllers, warmup := createReportControllers(
|
||||
backgroundScan,
|
||||
admissionReports,
|
||||
reportsChunkSize,
|
||||
backgroundScanWorkers,
|
||||
dynamicClient,
|
||||
kyvernoClient,
|
||||
rclient,
|
||||
metadataInformer,
|
||||
kubeInformer,
|
||||
kyvernoInformer,
|
||||
configMapResolver,
|
||||
backgroundScanInterval,
|
||||
configuration,
|
||||
eventGenerator,
|
||||
)
|
||||
return reportControllers, warmup, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
leaderElectionRetryPeriod time.Duration
|
||||
imagePullSecrets string
|
||||
imageSignatureRepository string
|
||||
allowInsecureRegistry bool
|
||||
backgroundScan bool
|
||||
admissionReports bool
|
||||
reportsChunkSize int
|
||||
backgroundScanWorkers int
|
||||
backgroundScanInterval time.Duration
|
||||
maxQueuedEvents int
|
||||
)
|
||||
flagset := flag.NewFlagSet("reports-controller", flag.ExitOnError)
|
||||
flagset.DurationVar(&leaderElectionRetryPeriod, "leaderElectionRetryPeriod", leaderelection.DefaultRetryPeriod, "Configure leader election retry period.")
|
||||
flagset.StringVar(&imagePullSecrets, "imagePullSecrets", "", "Secret resource names for image registry access credentials.")
|
||||
flagset.StringVar(&imageSignatureRepository, "imageSignatureRepository", "", "Alternate repository for image signatures. Can be overridden per rule via `verifyImages.Repository`.")
|
||||
flagset.BoolVar(&allowInsecureRegistry, "allowInsecureRegistry", false, "Whether to allow insecure connections to registries. Don't use this for anything but testing.")
|
||||
flagset.BoolVar(&backgroundScan, "backgroundScan", true, "Enable or disable backgound scan.")
|
||||
flagset.BoolVar(&admissionReports, "admissionReports", true, "Enable or disable admission reports.")
|
||||
flagset.IntVar(&reportsChunkSize, "reportsChunkSize", 1000, "Max number of results in generated reports, reports will be split accordingly if there are more results to be stored.")
|
||||
flagset.IntVar(&backgroundScanWorkers, "backgroundScanWorkers", backgroundscancontroller.Workers, "Configure the number of background scan workers.")
|
||||
flagset.DurationVar(&backgroundScanInterval, "backgroundScanInterval", time.Hour, "Configure background scan interval.")
|
||||
flagset.IntVar(&maxQueuedEvents, "maxQueuedEvents", 1000, "Maximum events to be queued.")
|
||||
// config
|
||||
appConfig := internal.NewConfiguration(
|
||||
internal.WithProfiling(),
|
||||
internal.WithMetrics(),
|
||||
internal.WithTracing(),
|
||||
internal.WithKubeconfig(),
|
||||
internal.WithFlagSets(flagset),
|
||||
)
|
||||
// parse flags
|
||||
internal.ParseFlags(appConfig)
|
||||
// setup logger
|
||||
// show version
|
||||
// start profiling
|
||||
// setup signals
|
||||
// setup maxprocs
|
||||
// setup metrics
|
||||
ctx, logger, metricsConfig, sdown := internal.Setup()
|
||||
defer sdown()
|
||||
// create instrumented clients
|
||||
kubeClient := internal.CreateKubernetesClient(logger, kubeclient.WithMetrics(metricsConfig, metrics.KubeClient), kubeclient.WithTracing())
|
||||
leaderElectionClient := internal.CreateKubernetesClient(logger, kubeclient.WithMetrics(metricsConfig, metrics.KubeClient), kubeclient.WithTracing())
|
||||
kyvernoClient := internal.CreateKyvernoClient(logger, kyvernoclient.WithMetrics(metricsConfig, metrics.KyvernoClient), kyvernoclient.WithTracing())
|
||||
metadataClient := internal.CreateMetadataClient(logger, metadataclient.WithMetrics(metricsConfig, metrics.KyvernoClient), metadataclient.WithTracing())
|
||||
dynamicClient := internal.CreateDynamicClient(logger, dynamicclient.WithMetrics(metricsConfig, metrics.KyvernoClient), dynamicclient.WithTracing())
|
||||
dClient, err := dclient.NewClient(ctx, dynamicClient, kubeClient, 15*time.Minute)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create dynamic client")
|
||||
os.Exit(1)
|
||||
}
|
||||
// THIS IS AN UGLY FIX
|
||||
// ELSE KYAML IS NOT THREAD SAFE
|
||||
kyamlopenapi.Schema()
|
||||
// informer factories
|
||||
kubeKyvernoInformer := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, resyncPeriod, kubeinformers.WithNamespace(config.KyvernoNamespace()))
|
||||
kyvernoInformer := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod)
|
||||
cacheInformer, err := resolvers.GetCacheInformerFactory(kubeClient, resyncPeriod)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create cache informer factory")
|
||||
os.Exit(1)
|
||||
}
|
||||
secretLister := kubeKyvernoInformer.Core().V1().Secrets().Lister().Secrets(config.KyvernoNamespace())
|
||||
// setup registry client
|
||||
rclient, err := setupRegistryClient(ctx, logger, secretLister, imagePullSecrets, allowInsecureRegistry)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to setup registry client")
|
||||
os.Exit(1)
|
||||
}
|
||||
// setup cosign
|
||||
setupCosign(logger, imageSignatureRepository)
|
||||
informerBasedResolver, err := resolvers.NewInformerBasedResolver(cacheInformer.Core().V1().ConfigMaps().Lister())
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create informer based resolver")
|
||||
os.Exit(1)
|
||||
}
|
||||
clientBasedResolver, err := resolvers.NewClientBasedResolver(kubeClient)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create client based resolver")
|
||||
os.Exit(1)
|
||||
}
|
||||
configMapResolver, err := resolvers.NewResolverChain(informerBasedResolver, clientBasedResolver)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create config map resolver")
|
||||
os.Exit(1)
|
||||
}
|
||||
configuration, err := config.NewConfiguration(kubeClient)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to initialize configuration")
|
||||
os.Exit(1)
|
||||
}
|
||||
eventGenerator := event.NewEventGenerator(
|
||||
dClient,
|
||||
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kyvernoInformer.Kyverno().V1().Policies(),
|
||||
maxQueuedEvents,
|
||||
logging.WithName("EventGenerator"),
|
||||
)
|
||||
// setup leader election
|
||||
le, err := leaderelection.New(
|
||||
logger.WithName("leader-election"),
|
||||
"kyverno-reports-controller",
|
||||
config.KyvernoNamespace(),
|
||||
leaderElectionClient,
|
||||
config.KyvernoPodName(),
|
||||
leaderElectionRetryPeriod,
|
||||
func(ctx context.Context) {
|
||||
logger := logger.WithName("leader")
|
||||
// create leader factories
|
||||
kubeInformer := kubeinformers.NewSharedInformerFactory(kubeClient, resyncPeriod)
|
||||
kubeKyvernoInformer := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, resyncPeriod, kubeinformers.WithNamespace(config.KyvernoNamespace()))
|
||||
kyvernoInformer := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod)
|
||||
metadataInformer := metadatainformers.NewSharedInformerFactory(metadataClient, 15*time.Minute)
|
||||
// create leader controllers
|
||||
leaderControllers, warmup, err := createrLeaderControllers(
|
||||
backgroundScan,
|
||||
admissionReports,
|
||||
reportsChunkSize,
|
||||
backgroundScanWorkers,
|
||||
kubeInformer,
|
||||
kyvernoInformer,
|
||||
metadataInformer,
|
||||
kyvernoClient,
|
||||
dClient,
|
||||
rclient,
|
||||
configuration,
|
||||
eventGenerator,
|
||||
configMapResolver,
|
||||
backgroundScanInterval,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create leader controllers")
|
||||
os.Exit(1)
|
||||
}
|
||||
// start informers and wait for cache sync
|
||||
if !internal.StartInformersAndWaitForCacheSync(ctx, kyvernoInformer, kubeInformer, kubeKyvernoInformer) {
|
||||
logger.Error(errors.New("failed to wait for cache sync"), "failed to wait for cache sync")
|
||||
os.Exit(1)
|
||||
}
|
||||
internal.StartInformers(ctx, metadataInformer)
|
||||
if !internal.CheckCacheSync(metadataInformer.WaitForCacheSync(ctx.Done())) {
|
||||
logger.Error(errors.New("failed to wait for cache sync"), "failed to wait for cache sync")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := warmup(ctx); err != nil {
|
||||
logger.Error(err, "failed to run warmup")
|
||||
os.Exit(1)
|
||||
}
|
||||
// start leader controllers
|
||||
var wg sync.WaitGroup
|
||||
for _, controller := range leaderControllers {
|
||||
controller.Run(ctx, logger.WithName("controllers"), &wg)
|
||||
}
|
||||
// wait all controllers shut down
|
||||
wg.Wait()
|
||||
},
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to initialize leader election")
|
||||
os.Exit(1)
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
le.Run(ctx)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue