make watch cache sizes configuratable of kube-apiserver

pull/6/head
magicwang-cn 2016-02-05 15:47:27 +08:00
parent c09b67f60f
commit d2cf858560
23 changed files with 143 additions and 19 deletions

View File

@ -80,6 +80,7 @@ type APIServer struct {
ServiceNodePortRange utilnet.PortRange
StorageVersions string
TokenAuthFile string
WatchCacheSizes []string
}
// NewAPIServer creates a new APIServer object with default parameters
@ -208,4 +209,5 @@ func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
fs.IntVar(&s.KubernetesServiceNodePort, "kubernetes-service-node-port", 0, "If non-zero, the Kubernetes master service (which apiserver creates/maintains) will be of type NodePort, using this as the value of the port. If zero, the Kubernetes master service will be of type ClusterIP.")
// TODO: delete this flag as soon as we identify and fix all clients that send malformed updates, like #14126.
fs.BoolVar(&validation.RepairMalformedUpdates, "repair-malformed-updates", true, "If true, server will do its best to fix the update request to pass the validation, e.g., setting empty UID in update request to its existing value. This flag can be turned off after we fix all the clients that send malformed updates.")
fs.StringSliceVar(&s.WatchCacheSizes, "watch-cache-sizes", s.WatchCacheSizes, "List of watch cache sizes for every resource (pods, nodes, etc.), comma separated. The individual override format: resource#size, where size is a number. It takes effect when watch-cache is enabled.")
}

View File

@ -49,6 +49,7 @@ import (
"k8s.io/kubernetes/pkg/genericapiserver"
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/master"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/storage"
@ -401,10 +402,16 @@ func Run(s *options.APIServer) error {
Tunneler: tunneler,
}
if s.EnableWatchCache {
cachesize.SetWatchCacheSizes(s.WatchCacheSizes)
}
m, err := master.New(config)
if err != nil {
return err
}
m.Run(s.ServerRunOptions)
return nil
}

View File

@ -106,9 +106,10 @@ kube-apiserver
--tls-private-key-file="": File containing x509 private key matching --tls-cert-file.
--token-auth-file="": If set, the file that will be used to secure the secure port of the API server via token authentication.
--watch-cache[=true]: Enable watch caching in the apiserver
--watch-cache-sizes=[]: List of watch cache sizes for every resource (pods, nodes, etc.), comma separated. The individual override format: resource#size, where size is a number. It takes effect when watch-cache is enabled.
```
###### Auto generated by spf13/cobra on 26-Jan-2016
###### Auto generated by spf13/cobra on 5-Feb-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->

View File

@ -372,3 +372,4 @@ leader-elect
leader-elect-lease-duration
leader-elect-renew-deadline
leader-elect-retry-period
watch-cache-sizes

View File

@ -0,0 +1,95 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
//use for --watch-cache-sizes param of kube-apiserver
//make watch cache size of resources configurable
package cachesize
import (
"strconv"
"strings"
"github.com/golang/glog"
)
type Resource string
const (
Controllers Resource = "controllers"
Daemonsets Resource = "daemonsets"
Deployments Resource = "deployments"
Endpoints Resource = "endpoints"
HorizontalPodAutoscalers Resource = "horizontalpodautoscalers"
Ingress Resource = "ingress"
Jobs Resource = "jobs"
LimitRanges Resource = "limitranges"
Namespaces Resource = "namespaces"
Nodes Resource = "nodes"
PersistentVolumes Resource = "persistentvolumes"
PersistentVolumeClaims Resource = "persistentvolumeclaims"
Pods Resource = "pods"
PodTemplates Resource = "podtemplates"
ResourceQuotas Resource = "resourcequotas"
Secrets Resource = "secrets"
ServiceAccounts Resource = "serviceaccounts"
Services Resource = "services"
)
var watchCacheSizes map[Resource]int
func init() {
watchCacheSizes = make(map[Resource]int)
watchCacheSizes[Controllers] = 100
watchCacheSizes[Daemonsets] = 100
watchCacheSizes[Deployments] = 100
watchCacheSizes[Endpoints] = 1000
watchCacheSizes[HorizontalPodAutoscalers] = 100
watchCacheSizes[Ingress] = 100
watchCacheSizes[Jobs] = 100
watchCacheSizes[LimitRanges] = 100
watchCacheSizes[Namespaces] = 100
watchCacheSizes[Nodes] = 1000
watchCacheSizes[PersistentVolumes] = 100
watchCacheSizes[PersistentVolumeClaims] = 100
watchCacheSizes[Pods] = 1000
watchCacheSizes[PodTemplates] = 100
watchCacheSizes[ResourceQuotas] = 100
watchCacheSizes[Secrets] = 100
watchCacheSizes[ServiceAccounts] = 100
watchCacheSizes[Services] = 100
}
func SetWatchCacheSizes(cacheSizes []string) {
for _, c := range cacheSizes {
tokens := strings.Split(c, "#")
if len(tokens) != 2 {
glog.Errorf("invalid value of watch cache capabilities: %s", c)
continue
}
size, err := strconv.Atoi(tokens[1])
if err != nil {
glog.Errorf("invalid size of watch cache capabilities: %s", c)
continue
}
watchCacheSizes[Resource(strings.ToLower(tokens[0]))] = size
}
}
func GetWatchCacheSizeByResource(resource Resource) int {
return watchCacheSizes[resource]
}

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/controller"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &api.ReplicationControllerList{} }
storageInterface := storageDecorator(
s, 100, &api.ReplicationController{}, prefix, controller.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Controllers), &api.ReplicationController{}, prefix, controller.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.ReplicationController{} },

View File

@ -21,6 +21,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/daemonset"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
@ -39,7 +40,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &extensions.DaemonSetList{} }
storageInterface := storageDecorator(
s, 100, &extensions.DaemonSet{}, prefix, daemonset.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Daemonsets), &extensions.DaemonSet{}, prefix, daemonset.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &extensions.DaemonSet{} },

View File

@ -27,6 +27,7 @@ import (
extvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/deployment"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
@ -64,7 +65,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &extensions.DeploymentList{} }
storageInterface := storageDecorator(
s, 100, &extensions.Deployment{}, prefix, deployment.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Deployments), &extensions.Deployment{}, prefix, deployment.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &extensions.Deployment{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/endpoint"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
newListFunc := func() runtime.Object { return &api.EndpointsList{} }
storageInterface := storageDecorator(
s, 1000, &api.Endpoints{}, prefix, endpoint.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Endpoints), &api.Endpoints{}, prefix, endpoint.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Endpoints{} },

View File

@ -21,6 +21,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler"
@ -38,7 +39,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &extensions.HorizontalPodAutoscalerList{} }
storageInterface := storageDecorator(
s, 100, &extensions.HorizontalPodAutoscaler{}, prefix, horizontalpodautoscaler.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.HorizontalPodAutoscalers), &extensions.HorizontalPodAutoscaler{}, prefix, horizontalpodautoscaler.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &extensions.HorizontalPodAutoscaler{} },

View File

@ -21,6 +21,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
ingress "k8s.io/kubernetes/pkg/registry/ingress"
@ -39,7 +40,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &extensions.IngressList{} }
storageInterface := storageDecorator(
s, 100, &extensions.Ingress{}, prefix, ingress.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Ingress), &extensions.Ingress{}, prefix, ingress.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &extensions.Ingress{} },

View File

@ -21,6 +21,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/job"
@ -39,7 +40,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &extensions.JobList{} }
storageInterface := storageDecorator(
s, 100, &extensions.Job{}, prefix, job.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Jobs), &extensions.Job{}, prefix, job.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &extensions.Job{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/limitrange"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
newListFunc := func() runtime.Object { return &api.LimitRangeList{} }
storageInterface := storageDecorator(
s, 100, &api.LimitRange{}, prefix, limitrange.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.LimitRanges), &api.LimitRange{}, prefix, limitrange.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.LimitRange{} },

View File

@ -24,6 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/namespace"
@ -53,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &api.NamespaceList{} }
storageInterface := storageDecorator(
s, 100, &api.Namespace{}, prefix, namespace.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Namespaces), &api.Namespace{}, prefix, namespace.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Namespace{} },

View File

@ -24,6 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/node"
@ -57,7 +58,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, con
newListFunc := func() runtime.Object { return &api.NodeList{} }
storageInterface := storageDecorator(
s, 1000, &api.Node{}, prefix, node.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Nodes), &api.Node{}, prefix, node.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Node{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/persistentvolume"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &api.PersistentVolumeList{} }
storageInterface := storageDecorator(
s, 100, &api.PersistentVolume{}, prefix, persistentvolume.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.PersistentVolumes), &api.PersistentVolume{}, prefix, persistentvolume.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.PersistentVolume{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/persistentvolumeclaim"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &api.PersistentVolumeClaimList{} }
storageInterface := storageDecorator(
s, 100, &api.PersistentVolumeClaim{}, prefix, persistentvolumeclaim.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.PersistentVolumeClaims), &api.PersistentVolumeClaim{}, prefix, persistentvolumeclaim.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.PersistentVolumeClaim{} },

View File

@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/pod"
@ -67,7 +68,7 @@ func NewStorage(
newListFunc := func() runtime.Object { return &api.PodList{} }
storageInterface := storageDecorator(
s, 1000, &api.Pod{}, prefix, pod.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Pods), &api.Pod{}, prefix, pod.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Pod{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/podtemplate"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
newListFunc := func() runtime.Object { return &api.PodTemplateList{} }
storageInterface := storageDecorator(
s, 100, &api.PodTemplate{}, prefix, podtemplate.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.PodTemplates), &api.PodTemplate{}, prefix, podtemplate.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.PodTemplate{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/resourcequota"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &api.ResourceQuotaList{} }
storageInterface := storageDecorator(
s, 100, &api.ResourceQuota{}, prefix, resourcequota.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.ResourceQuotas), &api.ResourceQuota{}, prefix, resourcequota.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.ResourceQuota{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/secret"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
newListFunc := func() runtime.Object { return &api.SecretList{} }
storageInterface := storageDecorator(
s, 100, &api.Secret{}, prefix, secret.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Secrets), &api.Secret{}, prefix, secret.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Secret{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/service"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
newListFunc := func() runtime.Object { return &api.ServiceList{} }
storageInterface := storageDecorator(
s, 100, &api.Service{}, prefix, service.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.Services), &api.Service{}, prefix, service.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Service{} },

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/serviceaccount"
@ -37,7 +38,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
newListFunc := func() runtime.Object { return &api.ServiceAccountList{} }
storageInterface := storageDecorator(
s, 100, &api.ServiceAccount{}, prefix, serviceaccount.Strategy, newListFunc)
s, cachesize.GetWatchCacheSizeByResource(cachesize.ServiceAccounts), &api.ServiceAccount{}, prefix, serviceaccount.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.ServiceAccount{} },