diff --git a/pkg/schema/collection.go b/pkg/schema/collection.go index dfb5fa7c..05a59afd 100644 --- a/pkg/schema/collection.go +++ b/pkg/schema/collection.go @@ -3,6 +3,8 @@ package schema import ( "context" "net/http" + "os" + "strconv" "strings" "sync" @@ -17,6 +19,25 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" ) +const ( + defaultUserSchemasCacheSize = 1000 +) + +var ( + userSchemasCacheSize = defaultUserSchemasCacheSize +) + +func init() { + if size := os.Getenv("CATTLE_USER_SCHEMAS_CACHE_SIZE"); size != "" { + sizeInt, err := strconv.Atoi(size) + if err != nil { + logrus.Errorf("failed to set user schemas cache size: %v", err) + return + } + userSchemasCacheSize = sizeInt + } +} + type Collection struct { toSync int32 baseSchema *types.APISchemas @@ -75,8 +96,8 @@ func NewCollection(ctx context.Context, baseSchema *types.APISchemas, access acc templates: map[string][]*Template{}, byGVR: map[schema.GroupVersionResource]string{}, byGVK: map[schema.GroupVersionKind]string{}, - cache: cache.NewLRUExpireCache(1000), - userCache: cache.NewLRUExpireCache(1000), + cache: cache.NewLRUExpireCache(userSchemasCacheSize), + userCache: cache.NewLRUExpireCache(userSchemasCacheSize), notifiers: map[int]func(){}, ctx: ctx, as: access, diff --git a/pkg/schema/factory.go b/pkg/schema/factory.go index b3fbe4a4..75917fe4 100644 --- a/pkg/schema/factory.go +++ b/pkg/schema/factory.go @@ -5,16 +5,42 @@ import ( "context" "fmt" "net/http" + "os" + "strconv" "time" "github.com/rancher/apiserver/pkg/builtin" "github.com/rancher/apiserver/pkg/types" "github.com/rancher/steve/pkg/accesscontrol" "github.com/rancher/steve/pkg/attributes" + "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authentication/user" ) +const ( + defaultExpiry = 24 * time.Hour +) + +var ( + schemasExpiry = defaultExpiry + logSizeDebug = false +) + +func init() { + if showSizeDebug := os.Getenv("CATTLE_LOG_CACHE_SIZE_DEBUG"); showSizeDebug == "true" { + logSizeDebug = true + } + if expiry := os.Getenv("CATTLE_SCHEMAS_CACHE_EXPIRY"); expiry != "" { + expInt, err := strconv.Atoi(expiry) + if err != nil { + logrus.Errorf("failed to set user schemas cache size: %v", err) + return + } + schemasExpiry = time.Duration(expInt) * time.Hour + } +} + type Factory interface { Schemas(user user.Info) (*types.APISchemas, error) ByGVR(gvr schema.GroupVersionResource) string @@ -63,8 +89,15 @@ func (c *Collection) removeOldRecords(access *accesscontrol.AccessSet, user user } func (c *Collection) addToCache(access *accesscontrol.AccessSet, user user.Info, schemas *types.APISchemas) { - c.cache.Add(access.ID, schemas, 24*time.Hour) - c.userCache.Add(user.GetName(), access.ID, 24*time.Hour) + cacheSize := len(c.cache.Keys()) + if cacheSize >= userSchemasCacheSize { + logrus.Debugf("user schemas cache is full. set size limit [%d], records will be evicted", userSchemasCacheSize) + } + if logSizeDebug { + logrus.Debugf("current size of schemas cache [%d], access ID being added [%s]", cacheSize, access.ID) + } + c.cache.Add(access.ID, schemas, schemasExpiry) + c.userCache.Add(user.GetName(), access.ID, schemasExpiry) } // PurgeUserRecords removes a record from the backing LRU cache before expiry