Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add namespace selector to admission webhook #54727

Merged
merged 2 commits into from
Nov 11, 2017

Conversation

caesarxuchao
Copy link
Member

@caesarxuchao caesarxuchao commented Oct 27, 2017

Implementing the design.

  • Added the NamespaceSelector field to the webhook configuration API
  • Let the webhook plugin respect the NamespaceSelector
  • Added unit test and e2e test

cc @kubernetes/sig-api-machinery-api-reviews

Added namespaceSelector to externalAdmissionWebhook configuration to allow applying webhooks only to objects in the namespaces that have matching labels.

@caesarxuchao caesarxuchao self-assigned this Oct 27, 2017
@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Oct 27, 2017
@k8s-github-robot k8s-github-robot added the kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API label Oct 27, 2017
@caesarxuchao
Copy link
Member Author

/retest

@cmluciano cmluciano changed the title [WIP] Add amespace selector to admission webhook [WIP] Add namespace selector to admission webhook Oct 30, 2017
@k8s-github-robot k8s-github-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 31, 2017
@k8s-github-robot k8s-github-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 31, 2017
// TestAdmit tests that GenericAdmissionWebhook#Admit works as expected
func TestAdmit(t *testing.T) {
scheme := runtime.NewScheme()
v1alpha1.AddToScheme(scheme)
api.AddToScheme(scheme)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that "api" was just an inappropriate alias.

@caesarxuchao caesarxuchao force-pushed the namespaceSelector branch 2 times, most recently from de768ee to 75730c5 Compare October 31, 2017 23:28
@caesarxuchao caesarxuchao changed the title [WIP] Add namespace selector to admission webhook Add namespace selector to admission webhook Oct 31, 2017
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 31, 2017
if err != nil {
return false, apierrors.NewInternalError(err)
}
namespace, err := a.namespaceLister.Get(namespaceName)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly, the cache namespace can be stale. We tolerate the delay in other plugins like podtolerationrestriction, so I think it's ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caesarxuchao 20 hours ago Member
Admittedly, the cache namespace can be stale. We tolerate the delay in other plugins like podtolerationrestriction, so I think it's ok.

Agree

@@ -165,6 +165,32 @@ type ExternalAdmissionHook struct {
// allowed values are Ignore or Fail. Defaults to Ignore.
// +optional
FailurePolicy *FailurePolicyType

// Selects namespaces that are subjected to this webhook.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably reword this. It might be better to be slightly repetitive with the description so it is clear that it applies to both selectors. Something like "Selects whether to run the webhook on an object based on whether the namespace for that object is/is not labeled with the associated key and the values equals any of the provided values. To run the webhook on any object whose namespace was not associated with 'runlevel' of '0' or '1'; you would set the selector as follows."

"If instead you wanted to only run the the webhook on any objects whose namespace was associated with the 'environment' of 'prod' or 'staging'; you would set the selector as follows."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whether the namespace for that object is/is not labeled with the associated key and the values equals any of the provided values.

This is not accurate, because selector also supports operations like "if key exists/not exists".

I'll just say "whether the namespace for that object matches the selector".

Also, is it intentional to use the past tense?

Updated the comments in types.go, PTAL. Thank you.

// matching, so you can use this selector as a whitelist or a blacklist.
// For example, to apply the webhook to all namespaces except for those have
// labels with key "runlevel" and value equal to "0" or "1":
// metav1.LabelSelctor{MatchExpressions: []LabelSelectorRequirement{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metav1.LabelSelector

// }}
// As another example, to only apply the webhook to the namespaces that have
// labels with key "environment" and value equal to "prod" or "staging":
// metav1.LabelSelctor{MatchExpressions: []LabelSelectorRequirement{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metav1.LabelSelector

a.namespaceLister = namespaceInformer.Lister()
a.SetReadyFunc(namespaceInformer.Informer().HasSynced)
}

// Validator holds Validate functions, which are responsible for validation of initialized shared resources
// and should be implemented on admission plugins
func (a *GenericAdmissionWebhook) Validate() error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add requirement for namespace lister.

// whether the namespace is exempted from the webhook.
func (a *GenericAdmissionWebhook) exemptNamespace(h *v1alpha1.ExternalAdmissionHook, attr admission.Attributes) (bool, error) {
namespaceName := attr.GetNamespace()
if namespaceName == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len(namespaceName) == 0

namespaceName := attr.GetNamespace()
if namespaceName == "" {
// if the request is root scoped, it is not exempted.
return false, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a neat side-effect. A downed admission plugin could prevent the node that would run the admission webhook from running.

I don't think we need to resolve it for beta, but given the switch to a DNS name, perhaps admission plugins that can mess with nodes should be hosted in a way that allows off cluster access.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be solved with the run level concept, like by reserving some nodes for run level 0 items.

@@ -246,7 +259,42 @@ func (a *GenericAdmissionWebhook) Admit(attr admission.Attributes) error {
return errs[0]
}

// whether the namespace is exempted from the webhook.
func (a *GenericAdmissionWebhook) exemptNamespace(h *v1alpha1.ExternalAdmissionHook, attr admission.Attributes) (bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this fail when it restricts namespaces and I'm trying to create a namespace?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I updated the code to use the labels of the namespace object itself if the attr.Object is a namespace.

if err != nil && !apierrors.IsNotFound(err) {
return false, apierrors.NewInternalError(err)
}
if err != nil && apierrors.IsNotFound(err) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just need if apierrors.IsNotFound(err)

@@ -115,12 +157,20 @@ func serve(w http.ResponseWriter, r *http.Request) {
}
}

func servePods(w http.ResponseWriter, r *http.Request) {
serve(w, r, "pods")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe pass the function rather than a resource name. You would then get to lose the switch above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Nov 9, 2017
@k8s-github-robot k8s-github-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 9, 2017
@caesarxuchao
Copy link
Member Author

@cheftako comments addressed. PTAL. Thank you.

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 9, 2017
Copy link
Member

@cheftako cheftako left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: caesarxuchao, cheftako, lavalamp

No associated issue. Update pull-request body to add a reference to an issue, or get approval with /approve no-issue

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Nov 9, 2017
@caesarxuchao
Copy link
Member Author

Applying the approval label based on #54727 (comment).

@caesarxuchao caesarxuchao added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 9, 2017
@k8s-github-robot k8s-github-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 10, 2017
@k8s-github-robot k8s-github-robot removed lgtm "Looks good to me", indicates that a PR is ready to be merged. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Nov 10, 2017
@caesarxuchao
Copy link
Member Author

Adding back the lgtm after rebase.

@caesarxuchao caesarxuchao added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 10, 2017
Chao Xu added 2 commits November 10, 2017 13:40
business logic in webhook plugin and unit test

add a e2e test for namespace selector
@caesarxuchao
Copy link
Member Author

Rebased again.

@k8s-github-robot k8s-github-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 10, 2017
@caesarxuchao caesarxuchao added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 10, 2017
@caesarxuchao
Copy link
Member Author

/retest

@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@k8s-github-robot
Copy link

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here.

@k8s-github-robot k8s-github-robot merged commit e52e793 into kubernetes:master Nov 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants