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
81ba522b
Commit
81ba522b
authored
Jul 11, 2017
by
Daniel Fernandes Martins
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make NodeRestriction admission allow evictions for bounded pods
parent
088141ca
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
105 additions
and
2 deletions
+105
-2
BUILD
plugin/pkg/admission/noderestriction/BUILD
+2
-0
admission.go
plugin/pkg/admission/noderestriction/admission.go
+45
-0
admission_test.go
plugin/pkg/admission/noderestriction/admission_test.go
+0
-0
policy.go
plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go
+3
-0
cluster-roles.yaml
...thorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml
+6
-0
BUILD
test/integration/auth/BUILD
+1
-0
node_test.go
test/integration/auth/node_test.go
+48
-2
No files found.
plugin/pkg/admission/noderestriction/BUILD
View file @
81ba522b
...
@@ -15,6 +15,7 @@ go_library(
...
@@ -15,6 +15,7 @@ go_library(
deps = [
deps = [
"//pkg/api:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/pod:go_default_library",
"//pkg/api/pod:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
...
@@ -32,6 +33,7 @@ go_test(
...
@@ -32,6 +33,7 @@ go_test(
tags = ["automanaged"],
tags = ["automanaged"],
deps = [
deps = [
"//pkg/api:go_default_library",
"//pkg/api:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
...
...
plugin/pkg/admission/noderestriction/admission.go
View file @
81ba522b
...
@@ -25,6 +25,7 @@ import (
...
@@ -25,6 +25,7 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
podutil
"k8s.io/kubernetes/pkg/api/pod"
podutil
"k8s.io/kubernetes/pkg/api/pod"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
coreinternalversion
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
coreinternalversion
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
...
@@ -102,6 +103,8 @@ func (c *nodePlugin) Admit(a admission.Attributes) error {
...
@@ -102,6 +103,8 @@ func (c *nodePlugin) Admit(a admission.Attributes) error {
return
c
.
admitPod
(
nodeName
,
a
)
return
c
.
admitPod
(
nodeName
,
a
)
case
"status"
:
case
"status"
:
return
c
.
admitPodStatus
(
nodeName
,
a
)
return
c
.
admitPodStatus
(
nodeName
,
a
)
case
"eviction"
:
return
c
.
admitPodEviction
(
nodeName
,
a
)
default
:
default
:
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"unexpected pod subresource %q"
,
a
.
GetSubresource
()))
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"unexpected pod subresource %q"
,
a
.
GetSubresource
()))
}
}
...
@@ -161,6 +164,9 @@ func (c *nodePlugin) admitPod(nodeName string, a admission.Attributes) error {
...
@@ -161,6 +164,9 @@ func (c *nodePlugin) admitPod(nodeName string, a admission.Attributes) error {
if
errors
.
IsNotFound
(
err
)
{
if
errors
.
IsNotFound
(
err
)
{
// wasn't found in the server cache, do a live lookup before forbidding
// wasn't found in the server cache, do a live lookup before forbidding
existingPod
,
err
=
c
.
podsGetter
.
Pods
(
a
.
GetNamespace
())
.
Get
(
a
.
GetName
(),
v1
.
GetOptions
{})
existingPod
,
err
=
c
.
podsGetter
.
Pods
(
a
.
GetNamespace
())
.
Get
(
a
.
GetName
(),
v1
.
GetOptions
{})
if
errors
.
IsNotFound
(
err
)
{
return
err
}
}
}
if
err
!=
nil
{
if
err
!=
nil
{
return
admission
.
NewForbidden
(
a
,
err
)
return
admission
.
NewForbidden
(
a
,
err
)
...
@@ -195,6 +201,45 @@ func (c *nodePlugin) admitPodStatus(nodeName string, a admission.Attributes) err
...
@@ -195,6 +201,45 @@ func (c *nodePlugin) admitPodStatus(nodeName string, a admission.Attributes) err
}
}
}
}
func
(
c
*
nodePlugin
)
admitPodEviction
(
nodeName
string
,
a
admission
.
Attributes
)
error
{
switch
a
.
GetOperation
()
{
case
admission
.
Create
:
// require eviction to an existing pod object
eviction
,
ok
:=
a
.
GetObject
()
.
(
*
policy
.
Eviction
)
if
!
ok
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"unexpected type %T"
,
a
.
GetObject
()))
}
// use pod name from the admission attributes, if set, rather than from the submitted Eviction object
podName
:=
a
.
GetName
()
if
len
(
podName
)
==
0
{
if
len
(
eviction
.
Name
)
==
0
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"could not determine pod from request data"
))
}
podName
=
eviction
.
Name
}
// get the existing pod from the server cache
existingPod
,
err
:=
c
.
podsGetter
.
Pods
(
a
.
GetNamespace
())
.
Get
(
podName
,
v1
.
GetOptions
{
ResourceVersion
:
"0"
})
if
errors
.
IsNotFound
(
err
)
{
// wasn't found in the server cache, do a live lookup before forbidding
existingPod
,
err
=
c
.
podsGetter
.
Pods
(
a
.
GetNamespace
())
.
Get
(
podName
,
v1
.
GetOptions
{})
if
errors
.
IsNotFound
(
err
)
{
return
err
}
}
if
err
!=
nil
{
return
admission
.
NewForbidden
(
a
,
err
)
}
// only allow a node to evict a pod bound to itself
if
existingPod
.
Spec
.
NodeName
!=
nodeName
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"node %s can only evict pods with spec.nodeName set to itself"
,
nodeName
))
}
return
nil
default
:
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"unexpected operation %s"
,
a
.
GetOperation
()))
}
}
func
(
c
*
nodePlugin
)
admitNode
(
nodeName
string
,
a
admission
.
Attributes
)
error
{
func
(
c
*
nodePlugin
)
admitNode
(
nodeName
string
,
a
admission
.
Attributes
)
error
{
requestedName
:=
a
.
GetName
()
requestedName
:=
a
.
GetName
()
...
...
plugin/pkg/admission/noderestriction/admission_test.go
View file @
81ba522b
This diff is collapsed.
Click to expand it.
plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go
View file @
81ba522b
...
@@ -113,6 +113,9 @@ func NodeRules() []rbac.PolicyRule {
...
@@ -113,6 +113,9 @@ func NodeRules() []rbac.PolicyRule {
// Needed for the node to report status of pods it is running.
// Needed for the node to report status of pods it is running.
// Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself.
// Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself.
rbac
.
NewRule
(
"update"
)
.
Groups
(
legacyGroup
)
.
Resources
(
"pods/status"
)
.
RuleOrDie
(),
rbac
.
NewRule
(
"update"
)
.
Groups
(
legacyGroup
)
.
Resources
(
"pods/status"
)
.
RuleOrDie
(),
// Needed for the node to create pod evictions.
// Use the NodeRestriction admission plugin to limit a node to creating evictions for pods bound to itself.
rbac
.
NewRule
(
"create"
)
.
Groups
(
legacyGroup
)
.
Resources
(
"pods/eviction"
)
.
RuleOrDie
(),
// Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs
// Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs
// Needed for configmap volume and envs
// Needed for configmap volume and envs
...
...
plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml
View file @
81ba522b
...
@@ -689,6 +689,12 @@ items:
...
@@ -689,6 +689,12 @@ items:
-
apiGroups
:
-
apiGroups
:
-
"
"
-
"
"
resources
:
resources
:
-
pods/eviction
verbs
:
-
create
-
apiGroups
:
-
"
"
resources
:
-
configmaps
-
configmaps
-
secrets
-
secrets
verbs
:
verbs
:
...
...
test/integration/auth/BUILD
View file @
81ba522b
...
@@ -27,6 +27,7 @@ go_test(
...
@@ -27,6 +27,7 @@ go_test(
"//pkg/apis/authorization:go_default_library",
"//pkg/apis/authorization:go_default_library",
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/auth/authorizer/abac:go_default_library",
"//pkg/auth/authorizer/abac:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
...
...
test/integration/auth/node_test.go
View file @
81ba522b
...
@@ -32,6 +32,7 @@ import (
...
@@ -32,6 +32,7 @@ import (
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authentication/user"
restclient
"k8s.io/client-go/rest"
restclient
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
informers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
...
@@ -224,6 +225,30 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -224,6 +225,30 @@ func TestNodeAuthorizer(t *testing.T) {
deleteNode2
:=
func
(
client
clientset
.
Interface
)
error
{
deleteNode2
:=
func
(
client
clientset
.
Interface
)
error
{
return
client
.
Core
()
.
Nodes
()
.
Delete
(
"node2"
,
nil
)
return
client
.
Core
()
.
Nodes
()
.
Delete
(
"node2"
,
nil
)
}
}
createNode2NormalPodEviction
:=
func
(
client
clientset
.
Interface
)
error
{
return
client
.
Policy
()
.
Evictions
(
"ns"
)
.
Evict
(
&
policy
.
Eviction
{
TypeMeta
:
metav1
.
TypeMeta
{
APIVersion
:
"policy/v1beta1"
,
Kind
:
"Eviction"
,
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"node2normalpod"
,
Namespace
:
"ns"
,
},
})
}
createNode2MirrorPodEviction
:=
func
(
client
clientset
.
Interface
)
error
{
return
client
.
Policy
()
.
Evictions
(
"ns"
)
.
Evict
(
&
policy
.
Eviction
{
TypeMeta
:
metav1
.
TypeMeta
{
APIVersion
:
"policy/v1beta1"
,
Kind
:
"Eviction"
,
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"node2mirrorpod"
,
Namespace
:
"ns"
,
},
})
}
nodeanonClient
:=
clientsetForToken
(
tokenNodeUnknown
,
clientConfig
)
nodeanonClient
:=
clientsetForToken
(
tokenNodeUnknown
,
clientConfig
)
node1Client
:=
clientsetForToken
(
tokenNode1
,
clientConfig
)
node1Client
:=
clientsetForToken
(
tokenNode1
,
clientConfig
)
...
@@ -237,7 +262,9 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -237,7 +262,9 @@ func TestNodeAuthorizer(t *testing.T) {
expectForbidden
(
t
,
getPV
(
nodeanonClient
))
expectForbidden
(
t
,
getPV
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPodEviction
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2
(
nodeanonClient
))
expectForbidden
(
t
,
updateNode2Status
(
nodeanonClient
))
expectForbidden
(
t
,
updateNode2Status
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2
(
nodeanonClient
))
...
@@ -249,7 +276,8 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -249,7 +276,8 @@ func TestNodeAuthorizer(t *testing.T) {
expectForbidden
(
t
,
getPV
(
node1Client
))
expectForbidden
(
t
,
getPV
(
node1Client
))
expectForbidden
(
t
,
createNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPod
(
node1Client
))
expectForbidden
(
t
,
createNode2MirrorPod
(
node1Client
))
expectForbidden
(
t
,
deleteNode2MirrorPod
(
node1Client
))
expectNotFound
(
t
,
deleteNode2MirrorPod
(
node1Client
))
expectNotFound
(
t
,
createNode2MirrorPodEviction
(
node1Client
))
expectForbidden
(
t
,
createNode2
(
node1Client
))
expectForbidden
(
t
,
createNode2
(
node1Client
))
expectForbidden
(
t
,
updateNode2Status
(
node1Client
))
expectForbidden
(
t
,
updateNode2Status
(
node1Client
))
expectForbidden
(
t
,
deleteNode2
(
node1Client
))
expectForbidden
(
t
,
deleteNode2
(
node1Client
))
...
@@ -264,6 +292,8 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -264,6 +292,8 @@ func TestNodeAuthorizer(t *testing.T) {
// mirror pod and self node lifecycle is allowed
// mirror pod and self node lifecycle is allowed
expectAllowed
(
t
,
createNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
createNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
deleteNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
deleteNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
createNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
createNode2MirrorPodEviction
(
node2Client
))
expectAllowed
(
t
,
createNode2
(
node2Client
))
expectAllowed
(
t
,
createNode2
(
node2Client
))
expectAllowed
(
t
,
updateNode2Status
(
node2Client
))
expectAllowed
(
t
,
updateNode2Status
(
node2Client
))
expectAllowed
(
t
,
deleteNode2
(
node2Client
))
expectAllowed
(
t
,
deleteNode2
(
node2Client
))
...
@@ -280,8 +310,10 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -280,8 +310,10 @@ func TestNodeAuthorizer(t *testing.T) {
expectForbidden
(
t
,
createNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
updateNode2NormalPodStatus
(
nodeanonClient
))
expectForbidden
(
t
,
updateNode2NormalPodStatus
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2NormalPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2NormalPodEviction
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
deleteNode2MirrorPod
(
nodeanonClient
))
expectForbidden
(
t
,
createNode2MirrorPodEviction
(
nodeanonClient
))
expectForbidden
(
t
,
getSecret
(
node1Client
))
expectForbidden
(
t
,
getSecret
(
node1Client
))
expectForbidden
(
t
,
getPVSecret
(
node1Client
))
expectForbidden
(
t
,
getPVSecret
(
node1Client
))
...
@@ -291,8 +323,10 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -291,8 +323,10 @@ func TestNodeAuthorizer(t *testing.T) {
expectForbidden
(
t
,
createNode2NormalPod
(
node1Client
))
expectForbidden
(
t
,
createNode2NormalPod
(
node1Client
))
expectForbidden
(
t
,
updateNode2NormalPodStatus
(
node1Client
))
expectForbidden
(
t
,
updateNode2NormalPodStatus
(
node1Client
))
expectForbidden
(
t
,
deleteNode2NormalPod
(
node1Client
))
expectForbidden
(
t
,
deleteNode2NormalPod
(
node1Client
))
expectForbidden
(
t
,
createNode2NormalPodEviction
(
node1Client
))
expectForbidden
(
t
,
createNode2MirrorPod
(
node1Client
))
expectForbidden
(
t
,
createNode2MirrorPod
(
node1Client
))
expectForbidden
(
t
,
deleteNode2MirrorPod
(
node1Client
))
expectNotFound
(
t
,
deleteNode2MirrorPod
(
node1Client
))
expectNotFound
(
t
,
createNode2MirrorPodEviction
(
node1Client
))
// node2 can get referenced objects now
// node2 can get referenced objects now
expectAllowed
(
t
,
getSecret
(
node2Client
))
expectAllowed
(
t
,
getSecret
(
node2Client
))
...
@@ -305,6 +339,11 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -305,6 +339,11 @@ func TestNodeAuthorizer(t *testing.T) {
expectAllowed
(
t
,
deleteNode2NormalPod
(
node2Client
))
expectAllowed
(
t
,
deleteNode2NormalPod
(
node2Client
))
expectAllowed
(
t
,
createNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
createNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
deleteNode2MirrorPod
(
node2Client
))
expectAllowed
(
t
,
deleteNode2MirrorPod
(
node2Client
))
// recreate as an admin to test eviction
expectAllowed
(
t
,
createNode2NormalPod
(
superuserClient
))
expectAllowed
(
t
,
createNode2MirrorPod
(
superuserClient
))
expectAllowed
(
t
,
createNode2NormalPodEviction
(
node2Client
))
expectAllowed
(
t
,
createNode2MirrorPodEviction
(
node2Client
))
}
}
func
expectForbidden
(
t
*
testing
.
T
,
err
error
)
{
func
expectForbidden
(
t
*
testing
.
T
,
err
error
)
{
...
@@ -314,6 +353,13 @@ func expectForbidden(t *testing.T, err error) {
...
@@ -314,6 +353,13 @@ func expectForbidden(t *testing.T, err error) {
}
}
}
}
func
expectNotFound
(
t
*
testing
.
T
,
err
error
)
{
if
!
errors
.
IsNotFound
(
err
)
{
_
,
file
,
line
,
_
:=
runtime
.
Caller
(
1
)
t
.
Errorf
(
"%s:%d: Expected notfound error, got %v"
,
filepath
.
Base
(
file
),
line
,
err
)
}
}
func
expectAllowed
(
t
*
testing
.
T
,
err
error
)
{
func
expectAllowed
(
t
*
testing
.
T
,
err
error
)
{
if
err
!=
nil
{
if
err
!=
nil
{
_
,
file
,
line
,
_
:=
runtime
.
Caller
(
1
)
_
,
file
,
line
,
_
:=
runtime
.
Caller
(
1
)
...
...
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