2023-01-20 15:53:27 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"flag"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/kyverno/kyverno/cmd/internal"
|
|
|
|
"github.com/kyverno/kyverno/pkg/background"
|
|
|
|
"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"
|
|
|
|
kyvernoclient "github.com/kyverno/kyverno/pkg/clients/kyverno"
|
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
|
|
|
policymetricscontroller "github.com/kyverno/kyverno/pkg/controllers/metrics/policy"
|
2023-01-31 07:46:38 +00:00
|
|
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
2023-01-20 15:53:27 +00:00
|
|
|
"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/policy"
|
|
|
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
|
|
|
kubeinformers "k8s.io/client-go/informers"
|
|
|
|
kyamlopenapi "sigs.k8s.io/kustomize/kyaml/openapi"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
resyncPeriod = 15 * time.Minute
|
|
|
|
)
|
|
|
|
|
|
|
|
func createrLeaderControllers(
|
2023-02-03 05:01:11 +00:00
|
|
|
eng engineapi.Engine,
|
2023-02-07 13:44:51 +00:00
|
|
|
genWorkers int,
|
2023-01-20 15:53:27 +00:00
|
|
|
kubeInformer kubeinformers.SharedInformerFactory,
|
|
|
|
kyvernoInformer kyvernoinformer.SharedInformerFactory,
|
|
|
|
kyvernoClient versioned.Interface,
|
|
|
|
dynamicClient dclient.Interface,
|
|
|
|
rclient registryclient.Client,
|
|
|
|
configuration config.Configuration,
|
|
|
|
metricsConfig metrics.MetricsConfigManager,
|
|
|
|
eventGenerator event.Interface,
|
|
|
|
) ([]internal.Controller, error) {
|
|
|
|
policyCtrl, err := policy.NewPolicyController(
|
|
|
|
kyvernoClient,
|
|
|
|
dynamicClient,
|
2023-02-03 05:01:11 +00:00
|
|
|
eng,
|
2023-01-20 15:53:27 +00:00
|
|
|
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
|
|
|
kyvernoInformer.Kyverno().V1().Policies(),
|
|
|
|
kyvernoInformer.Kyverno().V1beta1().UpdateRequests(),
|
|
|
|
configuration,
|
|
|
|
eventGenerator,
|
|
|
|
kubeInformer.Core().V1().Namespaces(),
|
|
|
|
logging.WithName("PolicyController"),
|
|
|
|
time.Hour,
|
|
|
|
metricsConfig,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-02-07 13:44:51 +00:00
|
|
|
backgroundController := background.NewController(
|
|
|
|
kyvernoClient,
|
|
|
|
dynamicClient,
|
|
|
|
eng,
|
|
|
|
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
|
|
|
kyvernoInformer.Kyverno().V1().Policies(),
|
|
|
|
kyvernoInformer.Kyverno().V1beta1().UpdateRequests(),
|
|
|
|
kubeInformer.Core().V1().Namespaces(),
|
|
|
|
eventGenerator,
|
|
|
|
configuration,
|
|
|
|
)
|
2023-01-20 15:53:27 +00:00
|
|
|
return []internal.Controller{
|
|
|
|
internal.NewController("policy-controller", policyCtrl, 2),
|
2023-02-07 13:44:51 +00:00
|
|
|
internal.NewController("background-controller", backgroundController, genWorkers),
|
2023-01-20 15:53:27 +00:00
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
var (
|
2023-04-11 17:44:49 +00:00
|
|
|
genWorkers int
|
|
|
|
maxQueuedEvents int
|
2023-01-20 15:53:27 +00:00
|
|
|
)
|
|
|
|
flagset := flag.NewFlagSet("updaterequest-controller", flag.ExitOnError)
|
2023-02-07 13:44:51 +00:00
|
|
|
flagset.IntVar(&genWorkers, "genWorkers", 10, "Workers for the background controller.")
|
2023-01-20 15:53:27 +00:00
|
|
|
flagset.IntVar(&maxQueuedEvents, "maxQueuedEvents", 1000, "Maximum events to be queued.")
|
|
|
|
// config
|
|
|
|
appConfig := internal.NewConfiguration(
|
|
|
|
internal.WithProfiling(),
|
|
|
|
internal.WithMetrics(),
|
|
|
|
internal.WithTracing(),
|
|
|
|
internal.WithKubeconfig(),
|
2023-04-11 07:12:05 +00:00
|
|
|
internal.WithPolicyExceptions(),
|
|
|
|
internal.WithConfigMapCaching(),
|
2023-04-11 14:37:46 +00:00
|
|
|
internal.WithCosign(),
|
2023-04-11 13:32:17 +00:00
|
|
|
internal.WithRegistryClient(),
|
2023-04-11 17:44:49 +00:00
|
|
|
internal.WithLeaderElection(),
|
2023-01-20 15:53:27 +00:00
|
|
|
internal.WithFlagSets(flagset),
|
|
|
|
)
|
|
|
|
// parse flags
|
|
|
|
internal.ParseFlags(appConfig)
|
2023-04-11 13:32:17 +00:00
|
|
|
// setup
|
|
|
|
signalCtx, setup, sdown := internal.Setup(appConfig, "kyverno-background-controller", false)
|
2023-01-20 15:53:27 +00:00
|
|
|
defer sdown()
|
|
|
|
// create instrumented clients
|
2023-04-11 12:05:20 +00:00
|
|
|
kyvernoClient := internal.CreateKyvernoClient(setup.Logger, kyvernoclient.WithMetrics(setup.MetricsManager, metrics.KyvernoClient), kyvernoclient.WithTracing())
|
|
|
|
dynamicClient := internal.CreateDynamicClient(setup.Logger, dynamicclient.WithMetrics(setup.MetricsManager, metrics.KyvernoClient), dynamicclient.WithTracing())
|
|
|
|
dClient, err := dclient.NewClient(signalCtx, dynamicClient, setup.KubeClient, 15*time.Minute)
|
2023-01-20 15:53:27 +00:00
|
|
|
if err != nil {
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.Logger.Error(err, "failed to create dynamic client")
|
2023-01-20 15:53:27 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
// THIS IS AN UGLY FIX
|
|
|
|
// ELSE KYAML IS NOT THREAD SAFE
|
|
|
|
kyamlopenapi.Schema()
|
|
|
|
// informer factories
|
|
|
|
kyvernoInformer := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod)
|
|
|
|
eventGenerator := event.NewEventGenerator(
|
|
|
|
dClient,
|
|
|
|
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
|
|
|
kyvernoInformer.Kyverno().V1().Policies(),
|
|
|
|
maxQueuedEvents,
|
|
|
|
logging.WithName("EventGenerator"),
|
|
|
|
)
|
|
|
|
// this controller only subscribe to events, nothing is returned...
|
2023-03-17 10:48:48 +00:00
|
|
|
var wg sync.WaitGroup
|
2023-01-20 15:53:27 +00:00
|
|
|
policymetricscontroller.NewController(
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.MetricsManager,
|
2023-01-20 15:53:27 +00:00
|
|
|
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
|
|
|
kyvernoInformer.Kyverno().V1().Policies(),
|
2023-03-17 10:48:48 +00:00
|
|
|
&wg,
|
2023-01-20 15:53:27 +00:00
|
|
|
)
|
2023-04-11 07:12:05 +00:00
|
|
|
engine := internal.NewEngine(
|
|
|
|
signalCtx,
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.Logger,
|
|
|
|
setup.Configuration,
|
|
|
|
setup.MetricsConfiguration,
|
2023-02-07 15:09:15 +00:00
|
|
|
dClient,
|
2023-04-11 13:32:17 +00:00
|
|
|
setup.RegistryClient,
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.KubeClient,
|
2023-04-11 07:12:05 +00:00
|
|
|
kyvernoClient,
|
2023-02-03 05:01:11 +00:00
|
|
|
)
|
2023-01-20 15:53:27 +00:00
|
|
|
// start informers and wait for cache sync
|
2023-04-11 13:32:17 +00:00
|
|
|
if !internal.StartInformersAndWaitForCacheSync(signalCtx, setup.Logger, kyvernoInformer) {
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.Logger.Error(errors.New("failed to wait for cache sync"), "failed to wait for cache sync")
|
2023-01-20 15:53:27 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
// start event generator
|
2023-03-17 10:48:48 +00:00
|
|
|
go eventGenerator.Run(signalCtx, 3, &wg)
|
2023-01-20 15:53:27 +00:00
|
|
|
// setup leader election
|
|
|
|
le, err := leaderelection.New(
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.Logger.WithName("leader-election"),
|
2023-02-07 13:44:51 +00:00
|
|
|
"kyverno-background-controller",
|
2023-01-20 15:53:27 +00:00
|
|
|
config.KyvernoNamespace(),
|
2023-04-11 17:44:49 +00:00
|
|
|
setup.LeaderElectionClient,
|
2023-01-20 15:53:27 +00:00
|
|
|
config.KyvernoPodName(),
|
2023-04-11 17:44:49 +00:00
|
|
|
internal.LeaderElectionRetryPeriod(),
|
2023-01-20 15:53:27 +00:00
|
|
|
func(ctx context.Context) {
|
2023-04-11 12:05:20 +00:00
|
|
|
logger := setup.Logger.WithName("leader")
|
2023-01-20 15:53:27 +00:00
|
|
|
// create leader factories
|
2023-04-11 12:05:20 +00:00
|
|
|
kubeInformer := kubeinformers.NewSharedInformerFactory(setup.KubeClient, resyncPeriod)
|
2023-01-20 15:53:27 +00:00
|
|
|
kyvernoInformer := kyvernoinformer.NewSharedInformerFactory(kyvernoClient, resyncPeriod)
|
|
|
|
// create leader controllers
|
|
|
|
leaderControllers, err := createrLeaderControllers(
|
2023-02-03 05:01:11 +00:00
|
|
|
engine,
|
2023-02-07 13:44:51 +00:00
|
|
|
genWorkers,
|
2023-01-20 15:53:27 +00:00
|
|
|
kubeInformer,
|
|
|
|
kyvernoInformer,
|
|
|
|
kyvernoClient,
|
|
|
|
dClient,
|
2023-04-11 13:32:17 +00:00
|
|
|
setup.RegistryClient,
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.Configuration,
|
|
|
|
setup.MetricsManager,
|
2023-01-20 15:53:27 +00:00
|
|
|
eventGenerator,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to create leader controllers")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
// start informers and wait for cache sync
|
2023-02-09 15:53:27 +00:00
|
|
|
if !internal.StartInformersAndWaitForCacheSync(signalCtx, logger, kyvernoInformer, kubeInformer) {
|
2023-01-20 15:53:27 +00:00
|
|
|
logger.Error(errors.New("failed to wait for cache sync"), "failed to wait for cache sync")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
// start leader controllers
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
for _, controller := range leaderControllers {
|
|
|
|
controller.Run(signalCtx, logger.WithName("controllers"), &wg)
|
|
|
|
}
|
|
|
|
// wait all controllers shut down
|
|
|
|
wg.Wait()
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
if err != nil {
|
2023-04-11 12:05:20 +00:00
|
|
|
setup.Logger.Error(err, "failed to initialize leader election")
|
2023-01-20 15:53:27 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
// start leader election
|
2023-04-03 15:17:44 +00:00
|
|
|
le.Run(signalCtx)
|
|
|
|
wg.Wait()
|
2023-01-20 15:53:27 +00:00
|
|
|
}
|