Skip to content

Commit 642c918

Browse files
authored
Merge pull request kosmos-io#814 from JimDevil/feat-proxy
feat: clusterlink-proxy aggregator apiserver provider resource cache and proxy services
2 parents be465bf + 567829e commit 642c918

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3171
-527
lines changed

cmd/clusterlink/proxy/app/clusterlink-proxy.go

+35-22
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,26 @@ import (
55
"fmt"
66

77
"github.com/spf13/cobra"
8+
genericapiserver "k8s.io/apiserver/pkg/server"
89
cliflag "k8s.io/component-base/cli/flag"
9-
"k8s.io/component-base/term"
10-
"k8s.io/klog/v2"
1110

1211
"github.com/kosmos.io/kosmos/cmd/clusterlink/proxy/app/options"
12+
"github.com/kosmos.io/kosmos/pkg/sharedcli/klogflag"
13+
profileflag "github.com/kosmos.io/kosmos/pkg/sharedcli/profileflag"
14+
"github.com/kosmos.io/kosmos/pkg/utils"
1315
)
1416

1517
// NewClusterLinkProxyCommand creates a *cobra.Command object with default parameters
1618
func NewClusterLinkProxyCommand(ctx context.Context) *cobra.Command {
1719
opts := options.NewOptions()
1820

1921
cmd := &cobra.Command{
20-
Use: "proxy",
21-
Long: `The proxy starts a apiserver for agent access the backend proxy`,
22-
RunE: func(cmd *cobra.Command, args []string) error {
23-
// validate options
24-
/*
25-
if errs := opts.Validate(); len(errs) != 0 {
26-
return errs.ToAggregate()
27-
}
28-
*/
22+
Use: utils.KosmosClusrerLinkRroxyComponentName,
23+
Long: `starts a server for agent kube-apiserver`,
24+
RunE: func(_ *cobra.Command, _ []string) error {
25+
if err := opts.Validate(); err != nil {
26+
return err
27+
}
2928
return run(ctx, opts)
3029
},
3130
Args: func(cmd *cobra.Command, args []string) error {
@@ -37,24 +36,26 @@ func NewClusterLinkProxyCommand(ctx context.Context) *cobra.Command {
3736
return nil
3837
},
3938
}
40-
namedFlagSets := opts.Flags()
4139

42-
fs := cmd.Flags()
43-
for _, f := range namedFlagSets.FlagSets {
44-
fs.AddFlagSet(f)
45-
}
40+
flags := cmd.Flags()
4641

47-
cols, _, err := term.TerminalSize(cmd.OutOrStdout())
48-
if err != nil {
49-
klog.Warning("term.TerminalSize err: %v", err)
50-
} else {
51-
cliflag.SetUsageAndHelpFunc(cmd, namedFlagSets, cols)
52-
}
42+
fss := cliflag.NamedFlagSets{}
43+
genericFlagSet := fss.FlagSet("generic")
44+
opts.AddFlags(genericFlagSet)
45+
46+
logsFlagSet := fss.FlagSet("logs")
47+
klogflag.Add(logsFlagSet)
48+
49+
flags.AddFlagSet(genericFlagSet)
50+
flags.AddFlagSet(logsFlagSet)
5351

5452
return cmd
5553
}
5654

5755
func run(ctx context.Context, opts *options.Options) error {
56+
// pprof
57+
profileflag.ListenAndServe(opts.ProfileOpts)
58+
5859
config, err := opts.Config()
5960
if err != nil {
6061
return err
@@ -65,5 +66,17 @@ func run(ctx context.Context, opts *options.Options) error {
6566
return err
6667
}
6768

69+
server.GenericAPIServer.AddPostStartHookOrDie("start-proxy-controller", func(context genericapiserver.PostStartHookContext) error {
70+
go func() {
71+
config.ExtraConfig.ProxyController.Run(context.StopCh, 1)
72+
}()
73+
return nil
74+
})
75+
76+
server.GenericAPIServer.AddPostStartHookOrDie("start-apiserver-informer", func(context genericapiserver.PostStartHookContext) error {
77+
config.ExtraConfig.KosmosInformerFactory.Start(context.StopCh)
78+
return nil
79+
})
80+
6881
return server.GenericAPIServer.PrepareRun().Run(ctx.Done())
6982
}

cmd/clusterlink/proxy/app/options/options.go

+98-108
Original file line numberDiff line numberDiff line change
@@ -2,118 +2,81 @@ package options
22

33
import (
44
"fmt"
5+
"log"
56
"net"
67
"net/http"
78
"strings"
89

10+
"github.com/spf13/pflag"
911
utilerrors "k8s.io/apimachinery/pkg/util/errors"
10-
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
12+
"k8s.io/apiserver/pkg/endpoints/openapi"
1113
genericrequest "k8s.io/apiserver/pkg/endpoints/request"
12-
genericapiserver "k8s.io/apiserver/pkg/server"
14+
genericserver "k8s.io/apiserver/pkg/server"
1315
genericoptions "k8s.io/apiserver/pkg/server/options"
14-
"k8s.io/apiserver/pkg/util/feature"
15-
cliflag "k8s.io/component-base/cli/flag"
16-
"k8s.io/component-base/featuregate"
17-
"k8s.io/component-base/logs"
18-
logsapi "k8s.io/component-base/logs/api/v1"
16+
"k8s.io/client-go/dynamic"
17+
"k8s.io/klog/v2"
18+
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
1919

20+
"github.com/kosmos.io/kosmos/pkg/apis/proxy/scheme"
21+
proxyScheme "github.com/kosmos.io/kosmos/pkg/apis/proxy/scheme"
2022
"github.com/kosmos.io/kosmos/pkg/clusterlink/proxy"
23+
proxyctl "github.com/kosmos.io/kosmos/pkg/clusterlink/proxy/controller"
24+
kosmosclientset "github.com/kosmos.io/kosmos/pkg/generated/clientset/versioned"
25+
informerfactory "github.com/kosmos.io/kosmos/pkg/generated/informers/externalversions"
26+
generatedopenapi "github.com/kosmos.io/kosmos/pkg/generated/openapi"
27+
profileflag "github.com/kosmos.io/kosmos/pkg/sharedcli/profileflag"
2128
"github.com/kosmos.io/kosmos/pkg/utils"
2229
)
2330

24-
// Options contains command line parameters for clusterlink-proxy
2531
type Options struct {
26-
MaxRequestsInFlight int
27-
MaxMutatingRequestsInFlight int
28-
utils.KubernetesOptions
29-
30-
Logs *logs.Options
31-
SecureServing *genericoptions.SecureServingOptionsWithLoopback
32-
Authentication *genericoptions.DelegatingAuthenticationOptions
33-
Authorization *genericoptions.DelegatingAuthorizationOptions
34-
Audit *genericoptions.AuditOptions
35-
Features *genericoptions.FeatureOptions
36-
CoreAPI *genericoptions.CoreAPIOptions
37-
FeatureGate featuregate.FeatureGate
38-
Admission *genericoptions.AdmissionOptions
32+
// RecommendedOptions *genericoptions.RecommendedOptions
33+
GenericServerRunOptions *genericoptions.ServerRunOptions
34+
SecureServing *genericoptions.SecureServingOptionsWithLoopback
35+
Authentication *genericoptions.DelegatingAuthenticationOptions
36+
Authorization *genericoptions.DelegatingAuthorizationOptions
37+
Audit *genericoptions.AuditOptions
38+
Features *genericoptions.FeatureOptions
39+
CoreAPI *genericoptions.CoreAPIOptions
40+
ServerRunOptions *genericoptions.ServerRunOptions
41+
42+
ProfileOpts profileflag.Options
3943
}
4044

41-
// nolint
42-
func NewOptions() *Options {
43-
sso := genericoptions.NewSecureServingOptions()
44-
45-
// We are composing recommended options for an aggregated api-server,
46-
// whose client is typically a proxy multiplexing many operations ---
47-
// notably including long-running ones --- into one HTTP/2 connection
48-
// into this server. So allow many concurrent operations.
49-
sso.HTTP2MaxStreamsPerConnection = 1000
50-
51-
return &Options{
52-
MaxRequestsInFlight: 0,
53-
MaxMutatingRequestsInFlight: 0,
54-
55-
Logs: logs.NewOptions(),
56-
SecureServing: sso.WithLoopback(),
57-
Authentication: genericoptions.NewDelegatingAuthenticationOptions(),
58-
Authorization: genericoptions.NewDelegatingAuthorizationOptions(),
59-
Audit: genericoptions.NewAuditOptions(),
60-
Features: genericoptions.NewFeatureOptions(),
61-
CoreAPI: genericoptions.NewCoreAPIOptions(),
62-
FeatureGate: feature.DefaultFeatureGate,
63-
Admission: genericoptions.NewAdmissionOptions(),
64-
}
45+
func (o *Options) AddFlags(flags *pflag.FlagSet) {
46+
o.SecureServing.AddFlags(flags)
47+
o.Authentication.AddFlags(flags)
48+
o.Authorization.AddFlags(flags)
49+
o.Audit.AddFlags(flags)
50+
o.Features.AddFlags(flags)
51+
o.CoreAPI.AddFlags(flags)
52+
o.ServerRunOptions.AddUniversalFlags(flags)
53+
o.ProfileOpts.AddFlags(flags)
6554
}
6655

6756
// nolint
68-
func (o *Options) Validate() error {
69-
errors := []error{}
70-
errors = append(errors, o.validateGenericOptions()...)
71-
return utilerrors.NewAggregate(errors)
72-
}
73-
74-
func (o *Options) validateGenericOptions() []error {
75-
errors := []error{}
76-
if o.MaxRequestsInFlight < 0 {
77-
errors = append(errors, fmt.Errorf("--max-requests-inflight can not be negative value"))
78-
}
79-
if o.MaxMutatingRequestsInFlight < 0 {
80-
errors = append(errors, fmt.Errorf("--max-mutating-requests-inflight can not be negative value"))
57+
func NewOptions() *Options {
58+
o := &Options{
59+
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
60+
SecureServing: genericoptions.NewSecureServingOptions().WithLoopback(),
61+
Authentication: genericoptions.NewDelegatingAuthenticationOptions(),
62+
Authorization: genericoptions.NewDelegatingAuthorizationOptions(),
63+
Audit: genericoptions.NewAuditOptions(),
64+
Features: genericoptions.NewFeatureOptions(),
65+
CoreAPI: genericoptions.NewCoreAPIOptions(),
66+
ServerRunOptions: genericoptions.NewServerRunOptions(),
8167
}
82-
83-
errors = append(errors, o.CoreAPI.Validate()...)
84-
errors = append(errors, o.SecureServing.Validate()...)
85-
errors = append(errors, o.Authentication.Validate()...)
86-
errors = append(errors, o.Authorization.Validate()...)
87-
errors = append(errors, o.Audit.Validate()...)
88-
errors = append(errors, o.Features.Validate()...)
89-
return errors
68+
return o
9069
}
9170

9271
// nolint
93-
func (o *Options) Flags() cliflag.NamedFlagSets {
94-
var fss cliflag.NamedFlagSets
95-
96-
genericfs := fss.FlagSet("generic")
97-
genericfs.IntVar(&o.MaxRequestsInFlight, "max-requests-inflight", o.MaxRequestsInFlight, ""+
98-
"Otherwise, this flag limits the maximum number of non-mutating requests in flight, or a zero value disables the limit completely.")
99-
genericfs.IntVar(&o.MaxMutatingRequestsInFlight, "max-mutating-requests-inflight", o.MaxMutatingRequestsInFlight, ""+
100-
"this flag limits the maximum number of mutating requests in flight, or a zero value disables the limit completely.")
101-
102-
globalcfs := fss.FlagSet("global")
103-
globalcfs.Float32Var(&o.KubernetesOptions.QPS, "kube-qps", utils.DefaultKubeQPS, "QPS to use while talking with kube-apiserver.")
104-
globalcfs.IntVar(&o.KubernetesOptions.Burst, "kube-burst", utils.DefaultKubeBurst, "Burst to use while talking with kube-apiserver.")
105-
o.CoreAPI.AddFlags(globalcfs)
106-
o.SecureServing.AddFlags(fss.FlagSet("secure serving"))
107-
o.Authentication.AddFlags(fss.FlagSet("authentication"))
108-
o.Authorization.AddFlags(fss.FlagSet("authorization"))
109-
o.Audit.AddFlags(fss.FlagSet("auditing"))
110-
o.Features.AddFlags(fss.FlagSet("features"))
111-
logsapi.AddFlags(o.Logs, fss.FlagSet("logs"))
112-
113-
// o.Admission.AddFlags(fss.FlagSet("admission"))
114-
// o.Traces.AddFlags(fss.FlagSet("traces"))
115-
116-
return fss
72+
func (o *Options) Validate() error {
73+
errs := []error{}
74+
errs = append(errs, o.SecureServing.Validate()...)
75+
errs = append(errs, o.Authentication.Validate()...)
76+
errs = append(errs, o.Authorization.Validate()...)
77+
errs = append(errs, o.Audit.Validate()...)
78+
errs = append(errs, o.Features.Validate()...)
79+
return utilerrors.NewAggregate(errs)
11780
}
11881

11982
// nolint
@@ -126,52 +89,79 @@ func (o *Options) Config() (*proxy.Config, error) {
12689
return nil, fmt.Errorf("error create self-signed certificates: %v", err)
12790
}
12891

129-
// remove NamespaceLifecycle admission plugin explicitly
130-
// current admission plugins: mutatingwebhook, validatingwebhook
131-
o.Admission.DisablePlugins = append(o.Admission.DisablePlugins, lifecycle.PluginName)
92+
// o.Admission.DisablePlugins = append(o.RecommendedOptions.Admission.DisablePlugins, lifecycle.PluginName)
13293

133-
genericConfig := genericapiserver.NewRecommendedConfig(proxy.Codecs)
134-
// genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(apiserver.Scheme))
135-
// genericConfig.OpenAPIConfig.Info.Title = openAPITitle
136-
// genericConfig.OpenAPIConfig.Info.Version= openAPIVersion
94+
genericConfig := genericserver.NewRecommendedConfig(proxyScheme.Codecs)
95+
genericConfig.OpenAPIConfig = genericserver.DefaultOpenAPIConfig(generatedopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(scheme.Scheme))
96+
genericConfig.OpenAPIConfig.Info.Title = utils.KosmosClusrerLinkRroxyComponentName
97+
genericConfig.OpenAPIConfig.Info.Version = utils.ClusterLinkOpenAPIVersion
13798

13899
// support watch to LongRunningFunc
139100
genericConfig.LongRunningFunc = func(r *http.Request, requestInfo *genericrequest.RequestInfo) bool {
140101
return strings.Contains(r.RequestURI, "watch")
141102
}
142103

143-
if err := o.genericOptionsApplyTo(genericConfig); err != nil {
104+
if err := o.ApplyTo(genericConfig); err != nil {
105+
return nil, err
106+
}
107+
108+
restMapper, err := apiutil.NewDynamicRESTMapper(genericConfig.ClientConfig)
109+
if err != nil {
110+
klog.Errorf("Failed to create REST mapper: %v", err)
111+
return nil, err
112+
}
113+
kosmosClient := kosmosclientset.NewForConfigOrDie(genericConfig.ClientConfig)
114+
kosmosInformerFactory := informerfactory.NewSharedInformerFactory(kosmosClient, 0)
115+
116+
dynamicClient, err := dynamic.NewForConfig(genericConfig.ClientConfig)
117+
if err != nil {
118+
log.Fatal(err)
119+
}
120+
121+
proxyCtl, err := proxyctl.NewResourceCacheController(proxyctl.NewControllerOption{
122+
RestConfig: genericConfig.ClientConfig,
123+
RestMapper: restMapper,
124+
KosmosFactory: kosmosInformerFactory,
125+
DynamicClient: dynamicClient,
126+
})
127+
if err != nil {
144128
return nil, err
145129
}
146130

147131
return &proxy.Config{
148132
GenericConfig: genericConfig,
133+
ExtraConfig: proxy.ExtraConfig{
134+
ProxyController: proxyCtl,
135+
KosmosInformerFactory: kosmosInformerFactory,
136+
},
149137
}, nil
150138
}
151139

152-
func (o *Options) genericOptionsApplyTo(config *genericapiserver.RecommendedConfig) error {
153-
config.MaxRequestsInFlight = o.MaxRequestsInFlight
154-
config.MaxMutatingRequestsInFlight = o.MaxMutatingRequestsInFlight
155-
156-
if err := o.SecureServing.ApplyTo(&config.SecureServing, &config.LoopbackClientConfig); err != nil {
140+
func (o *Options) ApplyTo(config *genericserver.RecommendedConfig) error {
141+
if err := o.SecureServing.ApplyTo(&config.Config.SecureServing, &config.Config.LoopbackClientConfig); err != nil {
157142
return err
158143
}
159-
if err := o.Authentication.ApplyTo(&config.Authentication, config.SecureServing, config.OpenAPIConfig); err != nil {
144+
if err := o.Authentication.ApplyTo(&config.Config.Authentication, config.SecureServing, config.OpenAPIConfig); err != nil {
160145
return err
161146
}
162-
if err := o.Authorization.ApplyTo(&config.Authorization); err != nil {
147+
if err := o.Authorization.ApplyTo(&config.Config.Authorization); err != nil {
163148
return err
164149
}
165150
if err := o.Audit.ApplyTo(&config.Config); err != nil {
166151
return err
167152
}
153+
168154
if err := o.Features.ApplyTo(&config.Config); err != nil {
169155
return err
170156
}
171157
if err := o.CoreAPI.ApplyTo(config); err != nil {
172158
return err
173159
}
174-
175-
utils.SetQPSBurst(config.ClientConfig, o.KubernetesOptions)
176-
return o.Admission.ApplyTo(&config.Config, config.SharedInformerFactory, config.ClientConfig, o.FeatureGate)
160+
if err := o.ServerRunOptions.ApplyTo(&config.Config); err != nil {
161+
return err
162+
}
163+
if err := o.Features.ApplyTo(&config.Config); err != nil {
164+
return err
165+
}
166+
return nil
177167
}

0 commit comments

Comments
 (0)