Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
5b4ca143
Commit
5b4ca143
authored
Oct 27, 2017
by
Derek Carr
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update admission control framework for quota
parent
7f88e918
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
51 additions
and
37 deletions
+51
-37
server.go
cmd/kube-apiserver/app/server.go
+2
-4
initializer.go
pkg/kubeapiserver/admission/initializer.go
+8
-8
BUILD
plugin/pkg/admission/resourcequota/BUILD
+1
-3
admission.go
plugin/pkg/admission/resourcequota/admission.go
+16
-12
admission_test.go
plugin/pkg/admission/resourcequota/admission_test.go
+0
-0
controller.go
plugin/pkg/admission/resourcequota/controller.go
+24
-10
No files found.
cmd/kube-apiserver/app/server.go
View file @
5b4ca143
...
...
@@ -506,11 +506,9 @@ func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client interna
// TODO: use a dynamic restmapper. See https://github.com/kubernetes/kubernetes/pull/42615.
restMapper
:=
legacyscheme
.
Registry
.
RESTMapper
()
// NOTE: we do not provide informers to the quota registry because admission level decisions
// do not require us to open watches for all items tracked by quota.
quotaRegistry
:=
quotainstall
.
NewRegistry
(
nil
,
nil
)
quotaConfiguration
:=
quotainstall
.
NewQuotaConfigurationForAdmission
()
pluginInitializer
:=
kubeapiserveradmission
.
NewPluginInitializer
(
client
,
sharedInformers
,
cloudConfig
,
restMapper
,
quota
Registry
,
webhookAuthWrapper
,
serviceResolver
)
pluginInitializer
:=
kubeapiserveradmission
.
NewPluginInitializer
(
client
,
sharedInformers
,
cloudConfig
,
restMapper
,
quota
Configuration
,
webhookAuthWrapper
,
serviceResolver
)
return
pluginInitializer
,
nil
}
...
...
pkg/kubeapiserver/admission/initializer.go
View file @
5b4ca143
...
...
@@ -53,9 +53,9 @@ type WantsRESTMapper interface {
SetRESTMapper
(
meta
.
RESTMapper
)
}
// WantsQuota
Registry defines a function which sets quota registry
for admission plugins that need it.
type
WantsQuota
Registry
interface
{
SetQuota
Registry
(
quota
.
Registry
)
// WantsQuota
Configuration defines a function which sets quota configuration
for admission plugins that need it.
type
WantsQuota
Configuration
interface
{
SetQuota
Configuration
(
quota
.
Configuration
)
admission
.
Validator
}
...
...
@@ -85,7 +85,7 @@ type PluginInitializer struct {
authorizer
authorizer
.
Authorizer
cloudConfig
[]
byte
restMapper
meta
.
RESTMapper
quota
Registry
quota
.
Registry
quota
Configuration
quota
.
Configuration
serviceResolver
webhook
.
ServiceResolver
authenticationInfoResolverWrapper
webhook
.
AuthenticationInfoResolverWrapper
}
...
...
@@ -100,7 +100,7 @@ func NewPluginInitializer(
sharedInformers
informers
.
SharedInformerFactory
,
cloudConfig
[]
byte
,
restMapper
meta
.
RESTMapper
,
quota
Registry
quota
.
Registry
,
quota
Configuration
quota
.
Configuration
,
authenticationInfoResolverWrapper
webhook
.
AuthenticationInfoResolverWrapper
,
serviceResolver
webhook
.
ServiceResolver
,
)
*
PluginInitializer
{
...
...
@@ -109,7 +109,7 @@ func NewPluginInitializer(
informers
:
sharedInformers
,
cloudConfig
:
cloudConfig
,
restMapper
:
restMapper
,
quota
Registry
:
quotaRegistry
,
quota
Configuration
:
quotaConfiguration
,
authenticationInfoResolverWrapper
:
authenticationInfoResolverWrapper
,
serviceResolver
:
serviceResolver
,
}
...
...
@@ -134,8 +134,8 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
wants
.
SetRESTMapper
(
i
.
restMapper
)
}
if
wants
,
ok
:=
plugin
.
(
WantsQuota
Registry
);
ok
{
wants
.
SetQuota
Registry
(
i
.
quotaRegistry
)
if
wants
,
ok
:=
plugin
.
(
WantsQuota
Configuration
);
ok
{
wants
.
SetQuota
Configuration
(
i
.
quotaConfiguration
)
}
if
wants
,
ok
:=
plugin
.
(
WantsServiceResolver
);
ok
{
...
...
plugin/pkg/admission/resourcequota/BUILD
View file @
5b4ca143
...
...
@@ -23,6 +23,7 @@ go_library(
"//pkg/client/listers/core/internalversion:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//pkg/quota:go_default_library",
"//pkg/quota/generic:go_default_library",
"//pkg/util/reflector/prometheus:go_default_library",
"//pkg/util/workqueue/prometheus:go_default_library",
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
...
...
@@ -58,14 +59,11 @@ go_test(
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/quota:go_default_library",
"//pkg/quota/generic:go_default_library",
"//pkg/quota/install:go_default_library",
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
...
...
plugin/pkg/admission/resourcequota/admission.go
View file @
5b4ca143
...
...
@@ -53,16 +53,16 @@ func Register(plugins *admission.Plugins) {
// quotaAdmission implements an admission controller that can enforce quota constraints
type
quotaAdmission
struct
{
*
admission
.
Handler
config
*
resourcequotaapi
.
Configuration
stopCh
<-
chan
struct
{}
registry
quota
.
Registry
numEvaluators
int
quotaAccessor
*
quotaAccessor
evaluator
Evaluator
config
*
resourcequotaapi
.
Configuration
stopCh
<-
chan
struct
{}
quotaConfiguration
quota
.
Configuration
numEvaluators
int
quotaAccessor
*
quotaAccessor
evaluator
Evaluator
}
var
_
=
kubeapiserveradmission
.
WantsInternalKubeClientSet
(
&
quotaAdmission
{})
var
_
=
kubeapiserveradmission
.
WantsQuota
Registry
(
&
quotaAdmission
{})
var
_
=
kubeapiserveradmission
.
WantsQuota
Configuration
(
&
quotaAdmission
{})
type
liveLookupEntry
struct
{
expiry
time
.
Time
...
...
@@ -95,9 +95,9 @@ func (a *quotaAdmission) SetInternalKubeInformerFactory(f informers.SharedInform
a
.
quotaAccessor
.
lister
=
f
.
Core
()
.
InternalVersion
()
.
ResourceQuotas
()
.
Lister
()
}
func
(
a
*
quotaAdmission
)
SetQuota
Registry
(
r
quota
.
Registry
)
{
a
.
registry
=
r
a
.
evaluator
=
NewQuotaEvaluator
(
a
.
quotaAccessor
,
a
.
registry
,
nil
,
a
.
config
,
a
.
numEvaluators
,
a
.
stopCh
)
func
(
a
*
quotaAdmission
)
SetQuota
Configuration
(
c
quota
.
Configuration
)
{
a
.
quotaConfiguration
=
c
a
.
evaluator
=
NewQuotaEvaluator
(
a
.
quotaAccessor
,
a
.
quotaConfiguration
,
nil
,
a
.
config
,
a
.
numEvaluators
,
a
.
stopCh
)
}
// Validate ensures an authorizer is set.
...
...
@@ -111,8 +111,8 @@ func (a *quotaAdmission) Validate() error {
if
a
.
quotaAccessor
.
lister
==
nil
{
return
fmt
.
Errorf
(
"missing quotaAccessor.lister"
)
}
if
a
.
registry
==
nil
{
return
fmt
.
Errorf
(
"missing
registry
"
)
if
a
.
quotaConfiguration
==
nil
{
return
fmt
.
Errorf
(
"missing
quotaConfiguration
"
)
}
if
a
.
evaluator
==
nil
{
return
fmt
.
Errorf
(
"missing evaluator"
)
...
...
@@ -126,5 +126,9 @@ func (a *quotaAdmission) Admit(attr admission.Attributes) (err error) {
if
attr
.
GetSubresource
()
!=
""
{
return
nil
}
// ignore all operations that are not namespaced
if
attr
.
GetNamespace
()
==
""
{
return
nil
}
return
a
.
evaluator
.
Evaluate
(
attr
)
}
plugin/pkg/admission/resourcequota/admission_test.go
View file @
5b4ca143
This diff is collapsed.
Click to expand it.
plugin/pkg/admission/resourcequota/controller.go
View file @
5b4ca143
...
...
@@ -34,6 +34,7 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/quota"
"k8s.io/kubernetes/pkg/quota/generic"
_
"k8s.io/kubernetes/pkg/util/reflector/prometheus"
// for reflector metric registration
_
"k8s.io/kubernetes/pkg/util/workqueue/prometheus"
// for workqueue metric registration
resourcequotaapi
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
...
...
@@ -51,6 +52,9 @@ type quotaEvaluator struct {
// lockAcquisitionFunc acquires any required locks and returns a cleanup method to defer
lockAcquisitionFunc
func
([]
api
.
ResourceQuota
)
func
()
// how quota was configured
quotaConfiguration
quota
.
Configuration
// registry that knows how to measure usage for objects
registry
quota
.
Registry
...
...
@@ -106,16 +110,18 @@ func newAdmissionWaiter(a admission.Attributes) *admissionWaiter {
// NewQuotaEvaluator configures an admission controller that can enforce quota constraints
// using the provided registry. The registry must have the capability to handle group/kinds that
// are persisted by the server this admission controller is intercepting
func
NewQuotaEvaluator
(
quotaAccessor
QuotaAccessor
,
registry
quota
.
Registry
,
lockAcquisitionFunc
func
([]
api
.
ResourceQuota
)
func
(),
config
*
resourcequotaapi
.
Configuration
,
workers
int
,
stopCh
<-
chan
struct
{})
Evaluator
{
func
NewQuotaEvaluator
(
quotaAccessor
QuotaAccessor
,
quotaConfiguration
quota
.
Configuration
,
lockAcquisitionFunc
func
([]
api
.
ResourceQuota
)
func
(),
config
*
resourcequotaapi
.
Configuration
,
workers
int
,
stopCh
<-
chan
struct
{})
Evaluator
{
// if we get a nil config, just create an empty default.
if
config
==
nil
{
config
=
&
resourcequotaapi
.
Configuration
{}
}
return
&
quotaEvaluator
{
quotaAccessor
:
quotaAccessor
,
lockAcquisitionFunc
:
lockAcquisitionFunc
,
registry
:
registry
,
quotaConfiguration
:
quotaConfiguration
,
registry
:
generic
.
NewRegistry
(
quotaConfiguration
.
Evaluators
()),
queue
:
workqueue
.
NewNamed
(
"admission_quota_controller"
),
work
:
map
[
string
][]
*
admissionWaiter
{},
...
...
@@ -365,9 +371,8 @@ func limitedByDefault(usage api.ResourceList, limitedResources []resourcequotaap
// that capture what the usage would be if the request succeeded. It return an error if there is insufficient quota to satisfy the request
func
(
e
*
quotaEvaluator
)
checkRequest
(
quotas
[]
api
.
ResourceQuota
,
a
admission
.
Attributes
)
([]
api
.
ResourceQuota
,
error
)
{
namespace
:=
a
.
GetNamespace
()
evaluators
:=
e
.
registry
.
Evaluators
()
evaluator
,
found
:=
evaluators
[
a
.
GetKind
()
.
GroupKind
()]
if
!
found
{
evaluator
:=
e
.
registry
.
Get
(
a
.
GetResource
()
.
GroupResource
())
if
evaluator
==
nil
{
return
quotas
,
nil
}
...
...
@@ -516,18 +521,27 @@ func (e *quotaEvaluator) Evaluate(a admission.Attributes) error {
go
e
.
run
()
})
// i
f we do not know how to evaluate use for this kind, just ignore
evaluators
:=
e
.
registry
.
Evaluators
()
evaluator
,
found
:=
evaluators
[
a
.
GetKind
()
.
GroupKind
()]
if
!
found
{
// i
s this resource ignored?
gvr
:=
a
.
GetResource
()
gr
:=
gvr
.
GroupResource
()
if
_
,
ok
:=
e
.
quotaConfiguration
.
IgnoredResources
()[
gr
];
ok
{
return
nil
}
// if we do not know how to evaluate use for this resource, create an evaluator
evaluator
:=
e
.
registry
.
Get
(
gr
)
if
evaluator
==
nil
{
// create an object count evaluator if no evaluator previously registered
// note, we do not need aggregate usage here, so we pass a nil infomer func
evaluator
=
generic
.
NewObjectCountEvaluator
(
false
,
gr
,
nil
,
""
)
e
.
registry
.
Add
(
evaluator
)
glog
.
Infof
(
"quota admission added evaluator for: %s"
,
gr
)
}
// for this kind, check if the operation could mutate any quota resources
// if no resources tracked by quota are impacted, then just return
if
!
evaluator
.
Handles
(
a
)
{
return
nil
}
waiter
:=
newAdmissionWaiter
(
a
)
e
.
addWork
(
waiter
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment