Skip to content

Commit 899d98a

Browse files
author
Kubernetes Submit Queue
authored
Merge pull request kubernetes#29983 from wojtek-t/configurable_cache_sizes
Automatic merge from submit-queue Configure cache sizes based on cluster size @fabioy <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.kubernetes.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.kubernetes.io/reviews/kubernetes/kubernetes/29983) <!-- Reviewable:end -->
2 parents 94fc389 + 38c2817 commit 899d98a

File tree

12 files changed

+82
-36
lines changed

12 files changed

+82
-36
lines changed

cluster/gce/gci/configure-helper.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,12 @@ function start-kube-apiserver {
635635
if [[ -n "${ENABLE_GARBAGE_COLLECTOR:-}" ]]; then
636636
params+=" --enable-garbage-collector=${ENABLE_GARBAGE_COLLECTOR}"
637637
fi
638+
if [[ -n "${NUM_NODES:-}" ]]; then
639+
# Set amount of memory available for apiserver based on number of nodes.
640+
# TODO: Once we start setting proper requests and limits for apiserver
641+
# we should reuse the same logic here instead of current heuristic.
642+
params+=" --target-ram-mb=$((${NUM_NODES} * 60))"
643+
fi
638644
if [[ -n "${SERVICE_CLUSTER_IP_RANGE:-}" ]]; then
639645
params+=" --service-cluster-ip-range=${SERVICE_CLUSTER_IP_RANGE}"
640646
fi

cluster/gce/trusty/configure-helper.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,12 @@ start_kube_apiserver() {
519519
params="${params} --authorization-policy-file=/etc/srv/kubernetes/abac-authz-policy.jsonl"
520520
params="${params} --etcd-servers-overrides=/events#http://127.0.0.1:4002"
521521

522+
if [ -n "${NUM_NODES:-}" ]; then
523+
# Set amount of memory available for apiserver based on number of nodes.
524+
# TODO: Once we start setting proper requests and limits for apiserver
525+
# we should reuse the same logic here instead of current heuristic.
526+
params="${params} --target-ram-mb=$((${NUM_NODES} * 60))"
527+
fi
522528
if [ -n "${SERVICE_CLUSTER_IP_RANGE:-}" ]; then
523529
params="${params} --service-cluster-ip-range=${SERVICE_CLUSTER_IP_RANGE}"
524530
fi

cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@
5757
{% set etcd_servers = "--etcd-servers=http://127.0.0.1:4001" -%}
5858
{% set etcd_servers_overrides = "--etcd-servers-overrides=/events#http://127.0.0.1:4002" -%}
5959

60+
{% set target_ram_mb = "" -%}
61+
{% if pillar['num_nodes'] is defined -%}
62+
# Set amount of memory available for apiserver based on number of nodes.
63+
# TODO: Once we start setting proper requests and limits for apiserver
64+
# we should reuse the same logic here instead of current heuristic.
65+
{% set tmp_ram_mb = pillar['num_nodes']|int * 60 %}
66+
{% set target_ram_mb = "--target-ram-mb=" + tmp_ram_mb|string -%}
67+
{% endif -%}
68+
6069
{% set service_cluster_ip_range = "" -%}
6170
{% if pillar['service_cluster_ip_range'] is defined -%}
6271
{% set service_cluster_ip_range = "--service-cluster-ip-range=" + pillar['service_cluster_ip_range'] -%}
@@ -124,15 +133,15 @@
124133

125134
{% set enable_garbage_collector = "" -%}
126135
{% if pillar['enable_garbage_collector'] is defined -%}
127-
{% set enable_garbage_collector = "--enable-garbage-collector=" + pillar['enable_garbage_collector'] -%}
136+
{% set enable_garbage_collector = "--enable-garbage-collector=" + pillar['enable_garbage_collector'] -%}
128137
{% endif -%}
129138

130-
{% set params = address + " " + etcd_servers + " " + etcd_servers_overrides + " " + cloud_provider + " " + cloud_config + " " + runtime_config + " " + admission_control + " " + service_cluster_ip_range + " " + client_ca_file + basic_auth_file + " " + min_request_timeout + " " + enable_garbage_collector -%}
139+
{% set params = address + " " + etcd_servers + " " + etcd_servers_overrides + " " + cloud_provider + " " + cloud_config + " " + runtime_config + " " + admission_control + " " + target_ram_mb + " " + service_cluster_ip_range + " " + client_ca_file + basic_auth_file + " " + min_request_timeout + " " + enable_garbage_collector -%}
131140
{% set params = params + " " + cert_file + " " + key_file + " --secure-port=" + secure_port + token_auth_file + " " + bind_address + " " + log_level + " " + advertise_address + " " + proxy_ssh_options + authz_mode + abac_policy_file + webhook_authentication_config + webhook_authorization_config -%}
132141

133142
# test_args has to be kept at the end, so they'll overwrite any prior configuration
134143
{% if pillar['apiserver_test_args'] is defined -%}
135-
{% set params = params + " " + pillar['apiserver_test_args'] -%}
144+
{% set params = params + " " + pillar['apiserver_test_args'] -%}
136145
{% endif -%}
137146

138147
{

cmd/kube-apiserver/app/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ func Run(s *options.APIServer) error {
282282
}
283283

284284
if s.EnableWatchCache {
285+
glog.V(2).Infof("Initalizing cache sizes based on %dMB limit", s.TargetRAMMB)
286+
cachesize.InitializeWatchCacheSizes(s.TargetRAMMB)
285287
cachesize.SetWatchCacheSizes(s.WatchCacheSizes)
286288
}
287289

federation/cmd/federation-apiserver/app/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ func Run(s *genericoptions.ServerRunOptions) error {
142142

143143
// TODO: Move this to generic api server (Need to move the command line flag).
144144
if s.EnableWatchCache {
145+
cachesize.InitializeWatchCacheSizes(s.TargetRAMMB)
145146
cachesize.SetWatchCacheSizes(s.WatchCacheSizes)
146147
}
147148

hack/verify-flags/exceptions.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ cluster/rackspace/util.sh: local node_ip=$(nova show --minimal ${NODE_NAMES[$
3939
cluster/saltbase/salt/cluster-autoscaler/cluster-autoscaler.manifest:{% set params = pillar['autoscaler_mig_config'] + " " + cloud_config -%}
4040
cluster/saltbase/salt/kube-admission-controls/init.sls:{% if 'LimitRanger' in pillar.get('admission_control', '') %}
4141
cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest:{% set enable_garbage_collector = pillar['enable_garbage_collector'] -%}
42-
cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest:{% set params = address + " " + etcd_servers + " " + etcd_servers_overrides + " " + cloud_provider + " " + cloud_config + " " + runtime_config + " " + admission_control + " " + service_cluster_ip_range + " " + client_ca_file + basic_auth_file + " " + min_request_timeout + " " + enable_garbage_collector -%}
42+
cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest:{% set params = address + " " + etcd_servers + " " + etcd_servers_overrides + " " + cloud_provider + " " + cloud_config + " " + runtime_config + " " + admission_control + " " + target_ram_mb + " " + service_cluster_ip_range + " " + client_ca_file + basic_auth_file + " " + min_request_timeout + " " + enable_garbage_collector -%}
4343
cluster/saltbase/salt/kube-controller-manager/kube-controller-manager.manifest:{% set enable_garbage_collector = pillar['enable_garbage_collector'] -%}
4444
cluster/saltbase/salt/kube-controller-manager/kube-controller-manager.manifest:{% set params = "--master=127.0.0.1:8080" + " " + cluster_name + " " + cluster_cidr + " " + allocate_node_cidrs + " " + service_cluster_ip_range + " " + terminated_pod_gc + " " + enable_garbage_collector + " " + cloud_provider + " " + cloud_config + " " + service_account_key + " " + log_level + " " + root_ca_file -%}
4545
cluster/saltbase/salt/kube-proxy/kube-proxy.manifest: {% set api_servers_with_port = api_servers + ":6443" -%}

hack/verify-flags/known-flags.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ system-container
471471
system-pods-startup-timeout
472472
system-reserved
473473
target-port
474+
target-ram-mb
474475
tcp-services
475476
terminated-pod-gc-threshold
476477
test-timeout

pkg/genericapiserver/options/server_run_options.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ type ServerRunOptions struct {
9898
// these; you can change this if you want to change the defaults (e.g.,
9999
// for testing). This is not actually exposed as a flag.
100100
DefaultStorageVersions string
101+
TargetRAMMB int
101102
TLSCertFile string
102103
TLSPrivateKeyFile string
103104
TokenAuthFile string
@@ -304,6 +305,9 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) {
304305
"Per-resource etcd servers overrides, comma separated. The individual override "+
305306
"format: group/resource#servers, where servers are http://ip:port, semicolon separated.")
306307

308+
fs.IntVar(&s.TargetRAMMB, "target-ram-mb", s.TargetRAMMB,
309+
"Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")
310+
307311
fs.StringVar(&s.ExternalHost, "external-hostname", s.ExternalHost,
308312
"The hostname to use when generating externalized URLs for this master (e.g. Swagger API Docs).")
309313

pkg/registry/cachesize/cachesize.go

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
CertificateSigningRequests Resource = "certificatesigningrequests"
3232
ClusterRoles Resource = "clusterroles"
3333
ClusterRoleBindings Resource = "clusterrolebindings"
34+
ConfigMaps Resource = "configmaps"
3435
Controllers Resource = "controllers"
3536
Daemonsets Resource = "daemonsets"
3637
Deployments Resource = "deployments"
@@ -47,6 +48,7 @@ const (
4748
PersistentVolumes Resource = "persistentvolumes"
4849
PersistentVolumeClaims Resource = "persistentvolumeclaims"
4950
Pods Resource = "pods"
51+
PodSecurityPolicies Resource = "podsecuritypolicies"
5052
PodTemplates Resource = "podtemplates"
5153
Replicasets Resource = "replicasets"
5254
ResourceQuotas Resource = "resourcequotas"
@@ -56,40 +58,36 @@ const (
5658
Secrets Resource = "secrets"
5759
ServiceAccounts Resource = "serviceaccounts"
5860
Services Resource = "services"
61+
StorageClasses Resource = "storageclasses"
62+
63+
// Default value of watch cache size for a resource if not specified.
64+
defaultWatchCacheSize = 100
5965
)
6066

67+
// TODO: This shouldn't be a global variable.
6168
var watchCacheSizes map[Resource]int
6269

6370
func init() {
6471
watchCacheSizes = make(map[Resource]int)
65-
watchCacheSizes[CertificateSigningRequests] = 1000
66-
watchCacheSizes[ClusterRoles] = 100
67-
watchCacheSizes[ClusterRoleBindings] = 100
68-
watchCacheSizes[Controllers] = 100
69-
watchCacheSizes[Daemonsets] = 100
70-
watchCacheSizes[Deployments] = 100
71-
watchCacheSizes[Endpoints] = 1000
72-
watchCacheSizes[HorizontalPodAutoscalers] = 100
73-
watchCacheSizes[Ingress] = 100
74-
watchCacheSizes[PetSet] = 100
75-
watchCacheSizes[PodDisruptionBudget] = 100
76-
watchCacheSizes[Jobs] = 100
77-
watchCacheSizes[LimitRanges] = 100
78-
watchCacheSizes[Namespaces] = 100
79-
watchCacheSizes[NetworkPolicys] = 100
80-
watchCacheSizes[Nodes] = 1000
81-
watchCacheSizes[PersistentVolumes] = 100
82-
watchCacheSizes[PersistentVolumeClaims] = 100
83-
watchCacheSizes[Pods] = 1000
84-
watchCacheSizes[PodTemplates] = 100
85-
watchCacheSizes[Replicasets] = 100
86-
watchCacheSizes[ResourceQuotas] = 100
87-
watchCacheSizes[ScheduledJobs] = 100
88-
watchCacheSizes[Roles] = 100
89-
watchCacheSizes[RoleBindings] = 100
90-
watchCacheSizes[Secrets] = 100
91-
watchCacheSizes[ServiceAccounts] = 100
92-
watchCacheSizes[Services] = 100
72+
}
73+
74+
func InitializeWatchCacheSizes(expectedRAMCapacityMB int) {
75+
// This is the heuristics that from memory capacity is trying to infer
76+
// the maximum number of nodes in the cluster and set cache sizes based
77+
// on that value.
78+
// From our documentation, we officially recomment 120GB machines for
79+
// 2000 nodes, and we scale from that point. Thus we assume ~60MB of
80+
// capacity per node.
81+
// TODO: Revisit this heuristics
82+
clusterSize := expectedRAMCapacityMB / 60
83+
84+
// We should specify cache size for a given resource only if it
85+
// is supposed to have non-default value.
86+
//
87+
// TODO: Figure out which resource we should have non-default value.
88+
watchCacheSizes[Endpoints] = maxInt(10*clusterSize, 1000)
89+
watchCacheSizes[Nodes] = maxInt(3*clusterSize, 1000)
90+
watchCacheSizes[Pods] = maxInt(10*clusterSize, 1000)
9391
}
9492

9593
func SetWatchCacheSizes(cacheSizes []string) {
@@ -111,5 +109,15 @@ func SetWatchCacheSizes(cacheSizes []string) {
111109
}
112110

113111
func GetWatchCacheSizeByResource(resource Resource) int {
114-
return watchCacheSizes[resource]
112+
if value, found := watchCacheSizes[resource]; found {
113+
return value
114+
}
115+
return defaultWatchCacheSize
116+
}
117+
118+
func maxInt(a, b int) int {
119+
if a > b {
120+
return a
121+
}
122+
return b
115123
}

pkg/registry/configmap/etcd/etcd.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package etcd
1818

1919
import (
2020
"k8s.io/kubernetes/pkg/api"
21+
"k8s.io/kubernetes/pkg/registry/cachesize"
2122
"k8s.io/kubernetes/pkg/registry/configmap"
2223
"k8s.io/kubernetes/pkg/registry/generic"
2324
"k8s.io/kubernetes/pkg/registry/generic/registry"
@@ -36,7 +37,13 @@ func NewREST(opts generic.RESTOptions) *REST {
3637

3738
newListFunc := func() runtime.Object { return &api.ConfigMapList{} }
3839
storageInterface := opts.Decorator(
39-
opts.Storage, 100, &api.ConfigMap{}, prefix, configmap.Strategy, newListFunc, storage.NoTriggerPublisher)
40+
opts.Storage,
41+
cachesize.GetWatchCacheSizeByResource(cachesize.ConfigMaps),
42+
&api.ConfigMap{},
43+
prefix,
44+
configmap.Strategy,
45+
newListFunc,
46+
storage.NoTriggerPublisher)
4047

4148
store := &registry.Store{
4249
NewFunc: func() runtime.Object {

pkg/registry/podsecuritypolicy/etcd/etcd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package etcd
1919
import (
2020
"k8s.io/kubernetes/pkg/api"
2121
"k8s.io/kubernetes/pkg/apis/extensions"
22+
"k8s.io/kubernetes/pkg/registry/cachesize"
2223
"k8s.io/kubernetes/pkg/registry/generic"
2324
"k8s.io/kubernetes/pkg/registry/generic/registry"
2425
"k8s.io/kubernetes/pkg/registry/podsecuritypolicy"
@@ -38,7 +39,7 @@ func NewREST(opts generic.RESTOptions) *REST {
3839
newListFunc := func() runtime.Object { return &extensions.PodSecurityPolicyList{} }
3940
storageInterface := opts.Decorator(
4041
opts.Storage,
41-
100,
42+
cachesize.GetWatchCacheSizeByResource(cachesize.PodSecurityPolicies),
4243
&extensions.PodSecurityPolicy{},
4344
prefix,
4445
podsecuritypolicy.Strategy,

pkg/registry/storageclass/etcd/etcd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package etcd
1919
import (
2020
"k8s.io/kubernetes/pkg/api"
2121
"k8s.io/kubernetes/pkg/apis/extensions"
22+
"k8s.io/kubernetes/pkg/registry/cachesize"
2223
"k8s.io/kubernetes/pkg/registry/generic"
2324
"k8s.io/kubernetes/pkg/registry/generic/registry"
2425
"k8s.io/kubernetes/pkg/registry/storageclass"
@@ -37,7 +38,7 @@ func NewREST(opts generic.RESTOptions) *REST {
3738
newListFunc := func() runtime.Object { return &extensions.StorageClassList{} }
3839
storageInterface := opts.Decorator(
3940
opts.Storage,
40-
100,
41+
cachesize.GetWatchCacheSizeByResource(cachesize.StorageClasses),
4142
&extensions.StorageClass{},
4243
prefix,
4344
storageclass.Strategy,

0 commit comments

Comments
 (0)