first-commit
This commit is contained in:
256
modules/k8s/cmd/controller-manager/app/options/options.go
Normal file
256
modules/k8s/cmd/controller-manager/app/options/options.go
Normal file
@@ -0,0 +1,256 @@
|
||||
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
|
||||
}
|
71
modules/k8s/cmd/controller-manager/app/server.go
Normal file
71
modules/k8s/cmd/controller-manager/app/server.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/component-base/term"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
|
||||
|
||||
"code.gitea.io/gitea/modules/k8s/cmd/controller-manager/app/options"
|
||||
"code.gitea.io/gitea/modules/k8s/controller"
|
||||
"code.gitea.io/gitea/modules/k8s/controller/application"
|
||||
"code.gitea.io/gitea/modules/k8s/controller/devcontainer"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 在初始化时注册所有控制器
|
||||
runtime.Must(controller.Register(&devcontainer.Controller{}))
|
||||
runtime.Must(controller.Register(&application.Controller{}))
|
||||
}
|
||||
|
||||
// NewControllerManagerCommand 创建一个启动 controller manager 的命令
|
||||
func NewControllerManagerCommand() *cobra.Command {
|
||||
s := options.NewControllerManagerOptions()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "controller-manager",
|
||||
Long: `DevStar controller manager is a daemon that embeds the control loops shipped with DevStar.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if errs := s.Validate(); len(errs) != 0 {
|
||||
return errors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
return Run(signals.SetupSignalHandler(), s)
|
||||
},
|
||||
}
|
||||
|
||||
fs := cmd.Flags()
|
||||
namedFlagSets := s.Flags()
|
||||
for _, f := range namedFlagSets.FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
usageFmt := "Usage:\n %s\n"
|
||||
cols, _, _ := term.TerminalSize(cmd.OutOrStdout())
|
||||
cmd.SetUsageFunc(func(cmd *cobra.Command) error {
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStderr(), usageFmt, cmd.UseLine())
|
||||
cliflag.PrintSections(cmd.OutOrStderr(), namedFlagSets, cols)
|
||||
return nil
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run 启动控制器管理器
|
||||
func Run(ctx context.Context, s *options.ControllerManagerOptions) error {
|
||||
klog.InfoS("Starting DevStar controller manager")
|
||||
|
||||
cm, err := s.NewControllerManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 启动控制器管理器
|
||||
return cm.Start(ctx)
|
||||
}
|
Reference in New Issue
Block a user