From 44db52ab5bcfdc42fe9bdf8a9d6842817dd25608 Mon Sep 17 00:00:00 2001 From: Igor Sutton Date: Thu, 7 Apr 2022 12:03:27 +0200 Subject: [PATCH] feat: add configuration for client-side throttling limit Client-side throttling seems to be an issue in larger environments such as OpenShift clusters, where it is common to have several hundreds CRDs out-of-the-box. From this view point, it is fair that clients should be able to fine tune this accordingly should the environment they work on evolves, which is currently not possible, and quite frustrating. This change introduces the --default-burst-limit option to helm (and its counterpart HELM_DEFAULT_BURST_LIMIT environment variable) to address that issue, allowing clients to properly tune their client usage as their environment evolves. Signed-off-by: Igor Sutton --- cmd/helm/root.go | 1 + pkg/cli/environment.go | 59 ++++++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/cmd/helm/root.go b/cmd/helm/root.go index 394f241d5..505ba431c 100644 --- a/cmd/helm/root.go +++ b/cmd/helm/root.go @@ -67,6 +67,7 @@ Environment variables: | $HELM_KUBEASUSER | set the Username to impersonate for the operation. | | $HELM_KUBECONTEXT | set the name of the kubeconfig context. | | $HELM_KUBETOKEN | set the Bearer KubeToken used for authentication. | +| $HELM_DEFAULT_BURST_LIMIT | set the default burst limit in the case the server contains many CRDs | Helm stores cache, configuration, and data based on the following configuration order: diff --git a/pkg/cli/environment.go b/pkg/cli/environment.go index d5b208015..827cd2f7d 100644 --- a/pkg/cli/environment.go +++ b/pkg/cli/environment.go @@ -30,6 +30,7 @@ import ( "github.com/spf13/pflag" "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/rest" "helm.sh/helm/v3/pkg/helmpath" ) @@ -37,6 +38,9 @@ import ( // defaultMaxHistory sets the maximum number of releases to 0: unlimited const defaultMaxHistory = 10 +// defaultBurstLimit sets the default client-side throttling limit +const defaultBurstLimit = 250 + // EnvSettings describes all of the environment settings. type EnvSettings struct { namespace string @@ -68,22 +72,25 @@ type EnvSettings struct { PluginsDirectory string // MaxHistory is the max release history maintained. MaxHistory int + // DefaultBurstLimit is the default client-side throttling limit. + DefaultBurstLimit int } func New() *EnvSettings { env := &EnvSettings{ - namespace: os.Getenv("HELM_NAMESPACE"), - MaxHistory: envIntOr("HELM_MAX_HISTORY", defaultMaxHistory), - KubeContext: os.Getenv("HELM_KUBECONTEXT"), - KubeToken: os.Getenv("HELM_KUBETOKEN"), - KubeAsUser: os.Getenv("HELM_KUBEASUSER"), - KubeAsGroups: envCSV("HELM_KUBEASGROUPS"), - KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"), - KubeCaFile: os.Getenv("HELM_KUBECAFILE"), - PluginsDirectory: envOr("HELM_PLUGINS", helmpath.DataPath("plugins")), - RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")), - RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")), - RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")), + namespace: os.Getenv("HELM_NAMESPACE"), + MaxHistory: envIntOr("HELM_MAX_HISTORY", defaultMaxHistory), + KubeContext: os.Getenv("HELM_KUBECONTEXT"), + KubeToken: os.Getenv("HELM_KUBETOKEN"), + KubeAsUser: os.Getenv("HELM_KUBEASUSER"), + KubeAsGroups: envCSV("HELM_KUBEASGROUPS"), + KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"), + KubeCaFile: os.Getenv("HELM_KUBECAFILE"), + PluginsDirectory: envOr("HELM_PLUGINS", helmpath.DataPath("plugins")), + RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")), + RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")), + RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")), + DefaultBurstLimit: envIntOr("HELM_DEFAULT_BURST_LIMIT", defaultBurstLimit), } env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG")) @@ -97,6 +104,10 @@ func New() *EnvSettings { KubeConfig: &env.KubeConfig, Impersonate: &env.KubeAsUser, ImpersonateGroup: &env.KubeAsGroups, + WrapConfigFn: func(config *rest.Config) *rest.Config { + config.Burst = env.DefaultBurstLimit + return config + }, } return env } @@ -115,6 +126,7 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.RegistryConfig, "registry-config", s.RegistryConfig, "path to the registry config file") fs.StringVar(&s.RepositoryConfig, "repository-config", s.RepositoryConfig, "path to the file containing repository names and URLs") fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes") + fs.IntVar(&s.DefaultBurstLimit, "default-burst-limit", s.DefaultBurstLimit, "client-side default throttling limit") } func envOr(name, def string) string { @@ -146,17 +158,18 @@ func envCSV(name string) (ls []string) { func (s *EnvSettings) EnvVars() map[string]string { envvars := map[string]string{ - "HELM_BIN": os.Args[0], - "HELM_CACHE_HOME": helmpath.CachePath(""), - "HELM_CONFIG_HOME": helmpath.ConfigPath(""), - "HELM_DATA_HOME": helmpath.DataPath(""), - "HELM_DEBUG": fmt.Sprint(s.Debug), - "HELM_PLUGINS": s.PluginsDirectory, - "HELM_REGISTRY_CONFIG": s.RegistryConfig, - "HELM_REPOSITORY_CACHE": s.RepositoryCache, - "HELM_REPOSITORY_CONFIG": s.RepositoryConfig, - "HELM_NAMESPACE": s.Namespace(), - "HELM_MAX_HISTORY": strconv.Itoa(s.MaxHistory), + "HELM_BIN": os.Args[0], + "HELM_CACHE_HOME": helmpath.CachePath(""), + "HELM_CONFIG_HOME": helmpath.ConfigPath(""), + "HELM_DATA_HOME": helmpath.DataPath(""), + "HELM_DEBUG": fmt.Sprint(s.Debug), + "HELM_PLUGINS": s.PluginsDirectory, + "HELM_REGISTRY_CONFIG": s.RegistryConfig, + "HELM_REPOSITORY_CACHE": s.RepositoryCache, + "HELM_REPOSITORY_CONFIG": s.RepositoryConfig, + "HELM_NAMESPACE": s.Namespace(), + "HELM_MAX_HISTORY": strconv.Itoa(s.MaxHistory), + "HELM_DEFAULT_BURST_LIMIT": strconv.Itoa(s.DefaultBurstLimit), // broken, these are populated from helm flags and not kubeconfig. "HELM_KUBECONTEXT": s.KubeContext,