package controllers import ( "flag" "net/http" "net/http/pprof" "os" certmgr "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" serverv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta1" serverauthv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1" "github.com/peterbourgon/ff/v3" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "edge-infra.dev/pkg/edge/component/build" "edge-infra.dev/pkg/edge/linkerd" l5dv1alpha1 "edge-infra.dev/pkg/edge/linkerd/k8s/apis/linkerd/v1alpha1" l5dmetrics "edge-infra.dev/pkg/edge/linkerd/k8s/controllers/metrics" "edge-infra.dev/pkg/k8s/runtime/controller" "edge-infra.dev/pkg/k8s/runtime/controller/metrics" "edge-infra.dev/pkg/k8s/runtime/events" "edge-infra.dev/pkg/lib/logging" ) type Config struct { Registry *string L5dDirPath *string Pprof *bool } func config() (Config, error) { fs := flag.NewFlagSet("linkerdctl", flag.ExitOnError) c := Config{ Registry: fs.String("registry", build.DefaultPublicContainerRegistry, "the registry to pull container images from i.e. us-east1-docker.pkg.dev/ret-edge-pltf-infra/thirdparty"), L5dDirPath: fs.String("l5d-dir", "/etc/l5d", "l5d persistent volume dir path"), Pprof: fs.Bool("enable-pprof", false, "enables pprod endpoint"), } if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarNoPrefix(), ff.WithIgnoreUndefined(true)); err != nil { return Config{}, err } return c, nil } // Run creates the manager, sets up the controller, and then starts // everything. It returns the created manager for testing purposes func Run(opts ...controller.Option) error { ctrl.SetLogger(logging.NewLogger().Logger) log := ctrl.Log.WithName("setup") l5dcfg, err := config() if err != nil { log.Error(err, "failed to parse startup configuration") return err } if l5dcfg.Pprof != nil && *l5dcfg.Pprof { log.Info("serving pprof on /debug/pprof/") opts = append(opts, controller.WithPProf("/", handlerPprof())) } mgr, err := CreateControllerManager(opts...) if err != nil { log.Error(err, "failed to create controller manager") return err } mgr, err = RegisterControllers(l5dcfg, mgr) if err != nil { log.Error(err, "failed to register controllers") return err } log.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { log.Error(err, "failed to start contoller manager") return err } return nil } // handlePprof returns a HTTP multiplexer with required pprof endpoints. func handlerPprof() *http.ServeMux { pprofMux := http.NewServeMux() pprofMux.HandleFunc("/debug/pprof/", pprof.Index) pprofMux.HandleFunc("/debug/pprof/{action}", pprof.Index) pprofMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) return pprofMux } // create wires up the reconciler(s) with a created manager and returns the // manager + setup logger func CreateControllerManager(o ...controller.Option) (ctrl.Manager, error) { cfg, opts := controller.ProcessOptions(o...) opts.LeaderElectionID = "linkerd103zx.edge.ncr.com" opts.Scheme = createScheme() return ctrl.NewManager(cfg, opts) } func RegisterControllers(l5dcfg Config, mgr ctrl.Manager) (ctrl.Manager, error) { ctrl.SetLogger(logging.NewLogger().Logger) log := ctrl.Log.WithName("setup") metrics := metrics.New(mgr, "linkerd", metrics.WithSuspend(), metrics.WithCollectors( l5dmetrics.LinkerdReadinessMetric, l5dmetrics.TrustAnchorExpiry, l5dmetrics.WorkloadInjectionReadinessMetric, ), ) eventRecorder := events.NewRecorder(mgr, ctrl.Log, linkerd.LinkerdControllerName) if err := newL5dReconciler(mgr, l5dcfg, metrics, eventRecorder).SetupWithManager(mgr); err != nil { log.Error(err, "unable to create linkerd controller") return nil, err } if err := newL5dWorkloadInjectionReconciler(mgr, metrics, eventRecorder).SetupWithManager(mgr); err != nil { log.Error(err, "unable to create workloadinjection controller") return nil, err } return mgr, nil } func createScheme() *runtime.Scheme { scheme := runtime.NewScheme() utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(v1.AddToScheme(scheme)) utilruntime.Must(l5dv1alpha1.AddToScheme(scheme)) utilruntime.Must(certmgr.AddToScheme(scheme)) utilruntime.Must(serverv1beta1.AddToScheme(scheme)) utilruntime.Must(serverauthv1beta1.AddToScheme(scheme)) return scheme }