Add --burst-limit option for client-side throttling limit configuration (#10842)

* 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 <isuttonl@redhat.com>

* chore: change DefaultBurstLimit to BurstLimit

Signed-off-by: Igor Sutton <isuttonl@redhat.com>

* chore: add HELM_BURST_LIMIT to golden file

Signed-off-by: Igor Sutton <isuttonl@redhat.com>

* chore: add burst limit tests

Signed-off-by: Igor Sutton <isuttonl@redhat.com>

* docs: add burst limit default value to documentation

Signed-off-by: Igor Sutton <isuttonl@redhat.com>

* refactor: change burst limit default value to 100 per review instructions

Signed-off-by: Igor Sutton <isuttonl@redhat.com>
pull/10944/head
Igor Sutton 3 years ago committed by GitHub
parent c05bf275df
commit 823d929421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -46,7 +46,7 @@ Common actions for Helm:
Environment variables: Environment variables:
| Name | Description | | Name | Description |
|------------------------------------|-----------------------------------------------------------------------------------| |------------------------------------|---------------------------------------------------------------------------------------------------|
| $HELM_CACHE_HOME | set an alternative location for storing cached files. | | $HELM_CACHE_HOME | set an alternative location for storing cached files. |
| $HELM_CONFIG_HOME | set an alternative location for storing Helm configuration. | | $HELM_CONFIG_HOME | set an alternative location for storing Helm configuration. |
| $HELM_DATA_HOME | set an alternative location for storing Helm data. | | $HELM_DATA_HOME | set an alternative location for storing Helm data. |
@ -67,6 +67,7 @@ Environment variables:
| $HELM_KUBEASUSER | set the Username to impersonate for the operation. | | $HELM_KUBEASUSER | set the Username to impersonate for the operation. |
| $HELM_KUBECONTEXT | set the name of the kubeconfig context. | | $HELM_KUBECONTEXT | set the name of the kubeconfig context. |
| $HELM_KUBETOKEN | set the Bearer KubeToken used for authentication. | | $HELM_KUBETOKEN | set the Bearer KubeToken used for authentication. |
| $HELM_BURST_LIMIT | set the default burst limit in the case the server contains many CRDs (default 100, -1 to disable)|
Helm stores cache, configuration, and data based on the following configuration order: Helm stores cache, configuration, and data based on the following configuration order:

@ -1,4 +1,5 @@
HELM_BIN HELM_BIN
HELM_BURST_LIMIT
HELM_CACHE_HOME HELM_CACHE_HOME
HELM_CONFIG_HOME HELM_CONFIG_HOME
HELM_DATA_HOME HELM_DATA_HOME

@ -30,6 +30,7 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest"
"helm.sh/helm/v3/pkg/helmpath" "helm.sh/helm/v3/pkg/helmpath"
) )
@ -37,6 +38,9 @@ import (
// defaultMaxHistory sets the maximum number of releases to 0: unlimited // defaultMaxHistory sets the maximum number of releases to 0: unlimited
const defaultMaxHistory = 10 const defaultMaxHistory = 10
// defaultBurstLimit sets the default client-side throttling limit
const defaultBurstLimit = 100
// EnvSettings describes all of the environment settings. // EnvSettings describes all of the environment settings.
type EnvSettings struct { type EnvSettings struct {
namespace string namespace string
@ -68,6 +72,8 @@ type EnvSettings struct {
PluginsDirectory string PluginsDirectory string
// MaxHistory is the max release history maintained. // MaxHistory is the max release history maintained.
MaxHistory int MaxHistory int
// BurstLimit is the default client-side throttling limit.
BurstLimit int
} }
func New() *EnvSettings { func New() *EnvSettings {
@ -84,6 +90,7 @@ func New() *EnvSettings {
RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")), RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")),
RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")), RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")),
RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")), RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")),
BurstLimit: envIntOr("HELM_BURST_LIMIT", defaultBurstLimit),
} }
env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG")) env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG"))
@ -97,6 +104,10 @@ func New() *EnvSettings {
KubeConfig: &env.KubeConfig, KubeConfig: &env.KubeConfig,
Impersonate: &env.KubeAsUser, Impersonate: &env.KubeAsUser,
ImpersonateGroup: &env.KubeAsGroups, ImpersonateGroup: &env.KubeAsGroups,
WrapConfigFn: func(config *rest.Config) *rest.Config {
config.Burst = env.BurstLimit
return config
},
} }
return env 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.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.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.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes")
fs.IntVar(&s.BurstLimit, "burst-limit", s.BurstLimit, "client-side default throttling limit")
} }
func envOr(name, def string) string { func envOr(name, def string) string {
@ -157,6 +169,7 @@ func (s *EnvSettings) EnvVars() map[string]string {
"HELM_REPOSITORY_CONFIG": s.RepositoryConfig, "HELM_REPOSITORY_CONFIG": s.RepositoryConfig,
"HELM_NAMESPACE": s.Namespace(), "HELM_NAMESPACE": s.Namespace(),
"HELM_MAX_HISTORY": strconv.Itoa(s.MaxHistory), "HELM_MAX_HISTORY": strconv.Itoa(s.MaxHistory),
"HELM_BURST_LIMIT": strconv.Itoa(s.BurstLimit),
// broken, these are populated from helm flags and not kubeconfig. // broken, these are populated from helm flags and not kubeconfig.
"HELM_KUBECONTEXT": s.KubeContext, "HELM_KUBECONTEXT": s.KubeContext,

@ -54,27 +54,31 @@ func TestEnvSettings(t *testing.T) {
kubeAsUser string kubeAsUser string
kubeAsGroups []string kubeAsGroups []string
kubeCaFile string kubeCaFile string
burstLimit int
}{ }{
{ {
name: "defaults", name: "defaults",
ns: "default", ns: "default",
maxhistory: defaultMaxHistory, maxhistory: defaultMaxHistory,
burstLimit: defaultBurstLimit,
}, },
{ {
name: "with flags set", name: "with flags set",
args: "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/tmp/ca.crt", args: "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/tmp/ca.crt --burst-limit 100",
ns: "myns", ns: "myns",
debug: true, debug: true,
maxhistory: defaultMaxHistory, maxhistory: defaultMaxHistory,
burstLimit: 100,
kubeAsUser: "poro", kubeAsUser: "poro",
kubeAsGroups: []string{"admins", "teatime", "snackeaters"}, kubeAsGroups: []string{"admins", "teatime", "snackeaters"},
kubeCaFile: "/tmp/ca.crt", kubeCaFile: "/tmp/ca.crt",
}, },
{ {
name: "with envvars set", name: "with envvars set",
envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt"}, envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt", "HELM_BURST_LIMIT": "150"},
ns: "yourns", ns: "yourns",
maxhistory: 5, maxhistory: 5,
burstLimit: 150,
debug: true, debug: true,
kubeAsUser: "pikachu", kubeAsUser: "pikachu",
kubeAsGroups: []string{"operators", "snackeaters", "partyanimals"}, kubeAsGroups: []string{"operators", "snackeaters", "partyanimals"},
@ -82,11 +86,12 @@ func TestEnvSettings(t *testing.T) {
}, },
{ {
name: "with flags and envvars set", name: "with flags and envvars set",
args: "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/my/ca.crt", args: "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters --kube-ca-file=/my/ca.crt --burst-limit 175",
envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt"}, envvars: map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5", "HELM_KUBECAFILE": "/tmp/ca.crt", "HELM_BURST_LIMIT": "200"},
ns: "myns", ns: "myns",
debug: true, debug: true,
maxhistory: 5, maxhistory: 5,
burstLimit: 175,
kubeAsUser: "poro", kubeAsUser: "poro",
kubeAsGroups: []string{"admins", "teatime", "snackeaters"}, kubeAsGroups: []string{"admins", "teatime", "snackeaters"},
kubeCaFile: "/my/ca.crt", kubeCaFile: "/my/ca.crt",
@ -128,6 +133,9 @@ func TestEnvSettings(t *testing.T) {
if tt.kubeCaFile != settings.KubeCaFile { if tt.kubeCaFile != settings.KubeCaFile {
t.Errorf("expected kCaFile %q, got %q", tt.kubeCaFile, settings.KubeCaFile) t.Errorf("expected kCaFile %q, got %q", tt.kubeCaFile, settings.KubeCaFile)
} }
if tt.burstLimit != settings.BurstLimit {
t.Errorf("expected BurstLimit %d, got %d", tt.burstLimit, settings.BurstLimit)
}
}) })
} }
} }

Loading…
Cancel
Save