package options import ( "crypto/tls" "flag" "fmt" "strings" "time" "github.com/spf13/pflag" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/leaderelection" cliflag "k8s.io/component-base/cli/flag" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/metrics/filters" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" "code.gitea.io/gitea/modules/k8s/controller" ) type ControllerManagerOptions struct { KubeConfig string Master string MetricsAddr string HealthProbeAddr string LeaderElect bool LeaderElection *leaderelection.LeaderElectionConfig WebhookCertDir string SecureMetrics bool EnableHTTP2 bool // ControllerGates is the list of controller gates to enable or disable controller. // '*' means "all enabled by default controllers" // 'foo' means "enable 'foo'" // '-foo' means "disable 'foo'" // first item for a particular name wins. ControllerGates []string DebugMode bool } func NewControllerManagerOptions() *ControllerManagerOptions { return &ControllerManagerOptions{ KubeConfig: "", Master: "", MetricsAddr: ":8080", HealthProbeAddr: ":8081", LeaderElect: false, LeaderElection: &leaderelection.LeaderElectionConfig{ LeaseDuration: 30 * time.Second, RenewDeadline: 15 * time.Second, RetryPeriod: 5 * time.Second, }, WebhookCertDir: "", SecureMetrics: true, EnableHTTP2: false, ControllerGates: []string{"*"}, DebugMode: false, } } // Flags 返回一组命名的命令行标志集合 func (s *ControllerManagerOptions) Flags() cliflag.NamedFlagSets { fss := cliflag.NamedFlagSets{} // Kubernetes 相关选项 fs := fss.FlagSet("kubernetes") fs.StringVar(&s.KubeConfig, "kubeconfig", s.KubeConfig, "Path to kubeconfig file with authorization and master location information.") fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server.") // 指标和健康检查 fs = fss.FlagSet("metrics") fs.StringVar(&s.MetricsAddr, "metrics-bind-address", s.MetricsAddr, "The address the metric endpoint binds to. Use :8443 for HTTPS or :8080 for HTTP, or 0 to disable.") fs.StringVar(&s.HealthProbeAddr, "health-probe-bind-address", s.HealthProbeAddr, "The address the probe endpoint binds to.") fs.BoolVar(&s.SecureMetrics, "metrics-secure", s.SecureMetrics, "If set, metrics endpoint is served securely via HTTPS.") // Leader 选举相关选项 fs = fss.FlagSet("leaderelection") fs.BoolVar(&s.LeaderElect, "leader-elect", s.LeaderElect, "Whether to enable leader election. This field should be enabled when controller manager deployed with multiple replicas.") s.bindLeaderElectionFlags(s.LeaderElection, fs) // Webhook 相关选项 fs = fss.FlagSet("webhook") fs.StringVar(&s.WebhookCertDir, "webhook-cert-dir", s.WebhookCertDir, "Certificate directory used to setup webhooks, need tls.crt and tls.key placed inside. If not set, webhook server would look up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs") fs.BoolVar(&s.EnableHTTP2, "enable-http2", s.EnableHTTP2, "If set, HTTP/2 will be enabled for the metrics and webhook servers") // 一般选项 fs = fss.FlagSet("generic") fs.StringSliceVar(&s.ControllerGates, "controllers", s.ControllerGates, fmt.Sprintf("A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller named 'foo', '-foo' disables the controller named 'foo'.\nAll controllers: %s", strings.Join(controller.GetAllControllers().List(), ", "))) fs.BoolVar(&s.DebugMode, "debug", s.DebugMode, "Don't enable this if you don't know what it means.") // klog 选项 kfs := fss.FlagSet("klog") local := flag.NewFlagSet("klog", flag.ExitOnError) klog.InitFlags(local) local.VisitAll(func(fl *flag.Flag) { fl.Name = strings.Replace(fl.Name, "_", "-", -1) kfs.AddGoFlag(fl) }) return fss } // 绑定 Leader 选举相关标志 func (s *ControllerManagerOptions) bindLeaderElectionFlags(l *leaderelection.LeaderElectionConfig, fs *pflag.FlagSet) { fs.DurationVar(&l.LeaseDuration, "leader-elect-lease-duration", l.LeaseDuration, ""+ "The duration that non-leader candidates will wait after observing a leadership "+ "renewal until attempting to acquire leadership of a led but unrenewed leader "+ "slot. This is effectively the maximum duration that a leader can be stopped "+ "before it is replaced by another candidate. This is only applicable if leader "+ "election is enabled.") fs.DurationVar(&l.RenewDeadline, "leader-elect-renew-deadline", l.RenewDeadline, ""+ "The interval between attempts by the acting master to renew a leadership slot "+ "before it stops leading. This must be less than or equal to the lease duration. "+ "This is only applicable if leader election is enabled.") fs.DurationVar(&l.RetryPeriod, "leader-elect-retry-period", l.RetryPeriod, ""+ "The duration the clients should wait between attempting acquisition and renewal "+ "of a leadership. This is only applicable if leader election is enabled.") } // Validate 验证选项 func (s *ControllerManagerOptions) Validate() []error { var errs []error // 验证 ControllerGates allControllersNameSet := controller.GetAllControllers() for _, selector := range s.ControllerGates { if selector == "*" { continue } selector = strings.TrimPrefix(selector, "-") if !allControllersNameSet.Has(selector) { errs = append(errs, fmt.Errorf("%q is not in the list of known controllers", selector)) } } return errs } // IsControllerEnabled 检查指定的控制器是否启用 func (s *ControllerManagerOptions) IsControllerEnabled(name string) bool { allowedAll := false for _, controllerGate := range s.ControllerGates { if controllerGate == name { return true } if controllerGate == "-"+name { return false } if controllerGate == "*" { allowedAll = true } } return allowedAll } // NewControllerManager 创建并返回一个新的控制器管理器 func (s *ControllerManagerOptions) NewControllerManager() (*controller.Manager, error) { cm := &controller.Manager{} // TLS 选项 tlsOpts := []func(*tls.Config){} // 如果未启用 HTTP/2,则禁用它以防止 HTTP/2 流取消和快速重置 CVE 的漏洞 if !s.EnableHTTP2 { disableHTTP2 := func(c *tls.Config) { klog.V(4).Info("disabling http/2") c.NextProtos = []string{"http/1.1"} } tlsOpts = append(tlsOpts, disableHTTP2) } // Webhook 服务器配置 webhookServer := webhook.NewServer(webhook.Options{ CertDir: s.WebhookCertDir, TLSOpts: tlsOpts, Port: 8443, }) // 度量服务器配置 metricsServerOptions := metricsserver.Options{ BindAddress: s.MetricsAddr, SecureServing: s.SecureMetrics, TLSOpts: tlsOpts, } if s.SecureMetrics { // 使用身份验证和授权来保护度量端点 metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization } // 设置控制器管理器选项 controllerOpts := ctrl.Options{ Scheme: controller.Scheme, Metrics: metricsServerOptions, WebhookServer: webhookServer, HealthProbeBindAddress: s.HealthProbeAddr, } // 配置 Leader 选举 if s.LeaderElect { controllerOpts.LeaderElection = s.LeaderElect controllerOpts.LeaderElectionNamespace = "devstar-system" controllerOpts.LeaderElectionID = "devstar-controller-manager-leader-election" leaseDuration := s.LeaderElection.LeaseDuration renewDeadline := s.LeaderElection.RenewDeadline retryPeriod := s.LeaderElection.RetryPeriod controllerOpts.LeaseDuration = &leaseDuration controllerOpts.RenewDeadline = &renewDeadline controllerOpts.RetryPeriod = &retryPeriod } // 创建 controller-runtime 管理器 klog.V(0).Info("setting up manager") ctrl.SetLogger(klog.NewKlogr()) // 获取 Kubernetes 配置 var config *rest.Config var err error if s.KubeConfig != "" { config, err = clientcmd.BuildConfigFromFlags(s.Master, s.KubeConfig) if err != nil { return nil, fmt.Errorf("unable to get kubeconfig: %v", err) } } else { config = ctrl.GetConfigOrDie() } // 创建管理器 mgr, err := ctrl.NewManager(config, controllerOpts) if err != nil { return nil, fmt.Errorf("unable to set up overall controller manager: %v", err) } // 添加健康检查 if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { return nil, fmt.Errorf("unable to set up health check: %v", err) } if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { return nil, fmt.Errorf("unable to set up ready check: %v", err) } // 设置控制器管理器 cm.Manager = mgr cm.IsControllerEnabled = s.IsControllerEnabled return cm, nil }