-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Set controllerRef in RCs owned by DC #14322
Set controllerRef in RCs owned by DC #14322
Conversation
@@ -631,7 +631,7 @@ func GetOpenshiftBootstrapClusterRoles() []authorizationapi.ClusterRole { | |||
}, | |||
}, | |||
Rules: []authorizationapi.PolicyRule{ | |||
authorizationapi.NewRule("get", "list", "watch", "update").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), | |||
authorizationapi.NewRule("get", "list", "watch", "update", "delete").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does the deployer need to delete RCs now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kargakis you can't set controller ref on a resource you aren't allowed to delete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the deployer setting owner references?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't it create RCs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the RCs are created by the DC controller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right; I forgot which SA am I talking about. This one needs it because otherwise I get
oc logs po/busyapp-1-deploy
--> Scaling busyapp-1 to 5
error: couldn't scale busyapp-1 to 5: Scaling the resource failed with: replicationcontrollers "busyapp-1" is forbidden: cannot set an ownerRef on a resource you can't delete: User "system:serviceaccount:test:deployer" cannot delete replicationcontrollers in project "test", <nil>; Current resource version 848
As it is not creating the resource and RC already has ownerRef set it might be because it is trying to remove it. This might happen if it forgets to do a deepcopy while updating since this is a pointer field. I will investigate it further
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kargakis what I've found out so far is that openshift-deploy
tries to do a PUT on RC without the ownerReferences and gets 403
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openshift/origin/blob/master/pkg/cmd/server/bootstrappolicy/controller_policy.go#L67 seems to be fixed in HEAD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mfojtik actually I think that's a different one and that one needs the "delete" as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error: couldn't scale busyapp-1 to 5: Scaling the resource failed with: replicationcontrollers "busyapp-1" is forbidden: cannot set an ownerRef on a resource you can't delete: User "system:serviceaccount:test:deployer" cannot delete replicationcontrollers in project "test", <nil>; Current resource version 848
say whaaat?
@@ -64,7 +64,7 @@ func init() { | |||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + InfraDeployerControllerServiceAccountName}, | |||
Rules: []rbac.PolicyRule{ | |||
rbac.NewRule("create", "get", "list", "watch", "patch", "delete").Groups(kapiGroup).Resources("pods").RuleOrDie(), | |||
rbac.NewRule("get", "list", "watch", "update").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), | |||
rbac.NewRule("get", "list", "watch", "update", "delete").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that you need this permission. The owner references should be set by the DC controller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is fine to investigate later, please create issue (most likely you need delete to create ownerRef)
70f8e15
to
5e54a0d
Compare
[test] |
5e54a0d
to
c29a4af
Compare
[test] |
c29a4af
to
f8c5f25
Compare
[test] |
@Kargakis @mfojtik I believe I've found the issue with
(It seemed to work with elevated permissions because DC controller created the controllerRef, than Deployer deleted it and DC controller adopted it because it didn't have any controllerRef and matched the selector.) |
@tnozicka nice. This means that if we don't provide the permissions in the deployer sa, we are going to break older images :( |
This lacks an extended test and you also need to set finalizers like in kubernetes/kubernetes#45764 |
s/extended/integration/ |
@Kargakis i'm fine with adding more permissions there with reasonable explanation/todo to remove them after all users are migrated. Having more escalated privileges is still better than having no privileges at all. I would defer all tests as follow ups as we need to unblock the UI team and web console. I think this PR will qualify as blocker bug fix. |
Ok, I have looked into it and it seems like the deployer image version and name come from master config. That kind of complicates things because we might not get rid those old images any time soon. But the real issues seems to be that the deployer images are not backwards compatible (or forwards - depends how you look at it). Meaning: if you do a forwards compatible API change they will delete the new data and act as nothing happened. This is a data loss. In this case it gets filled back when adopted back by DC but it might be more serious in other cases. The reason is the PUT call. Whenever you do GET+PUT on a resource (and you don't want to completely overwrite it) you break compatibility! You loose any fields you don't know about. Especially with deployer images which are decoupled from the master binary and you run different versions. But this is also applicable elsewhere - if you do a rollback of infra and use PUT on such resources you loose the data that has been added by the newer version. My take: don't use PUT, but PATCH. As we are already in that situation, here is a proposed path forward:
|
If all the deployer does is scaling the RC then it should use its scale endpoint. The fact that we are adding priviledges because we need to keep old images working worries me but I don't see any other solution now. cc: @smarterclayton |
@tnozicka agree, lets move this forward, don't have to be perfect but we need to unblock UI team and have the owner refs. We can fiddle the permissions and tests later. |
f8c5f25
to
6e11d12
Compare
I added the comments and I've tried to setup the finalizer but I've got:
Tried prefixing it with kubernetes.io/ it just doesn't do anything. We migh be missing that finalizer in origin but I wasn't able to confirm it yet. |
Ok I got to the bottom of this - seems like upstream is broken https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/pkg/api/helper/helpers.go#L224 They are missing that finalizer in standardFinalizers. It works perfectly if add I will send an PR and see. |
@mfojtik @Kargakis should we have admissionControl to add Right now it deletes DC, then PODs (that may take long time - default is 30 s) and then RCs. If in the interim user does |
I pushed literally just those 2 comments. |
[test] |
flake #13980 |
// "delete" is required here for compatibility with older deployer images | ||
// (see https://github.com/openshift/origin/pull/14322#issuecomment-303968976) | ||
// TODO: remove "delete" few releases after 3.6 | ||
rbac.NewRule("get", "list", "watch", "update", "delete").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would make this an extra rule just with delete
rbac.NewRule("delete").Group(kapi).Resources("replicationcontrollers")
// "delete" is required here for compatibility with older deployer images | ||
// (see https://github.com/openshift/origin/pull/14322#issuecomment-303968976) | ||
// TODO: remove "delete" few releases after 3.6 | ||
authorizationapi.NewRule("get", "list", "watch", "update", "delete").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, i would separate this from the rest of rbac
444b402
to
84cbbfa
Compare
…rDeleteDependents (Note: it is in different files from upstream because they moved helpers.go into helper/helpers.go)
84cbbfa
to
13326de
Compare
Evaluated for origin test up to 3ace21a |
continuous-integration/openshift-jenkins/test Running (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin/1841/) (Base Commit: 39664e5) |
continuous-integration/openshift-jenkins/test SUCCESS |
@mfojtik good to go? For the record: GC client seems to work fine as tried with upgrade from 1.4; order of deletion will be decided on separately. |
tnozicka yeah, please make sure you have follow up issue for the tests for this... I think this is good base and we can build on this. Mo removed tag to make bot happy
|
[merge][severity: blocker] See previous comments. |
[merge] against (seems like tagging screwup) |
Flake #14122 |
Flake #14418 |
[merge] |
Evaluated for origin merge up to 3ace21a |
continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/merge_pull_request_origin/866/) (Base Commit: b6fd9db) (Extended Tests: blocker) (Image: devenv-rhel7_6290) |
@@ -125,6 +148,15 @@ func (c *DeploymentConfigController) Handle(config *deployapi.DeploymentConfig) | |||
if err != nil { | |||
return err | |||
} | |||
// We need to make sure we own that RC or adopt it if possible | |||
isOurs, err := cm.ClaimReplicationController(rc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have already claimed those RCs above, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kargakis the one we get with the Get
could be a different one. What if it no longer matches the selector and was/should be released or it could have been changed, deleted/+created and we don't own it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about having the RC diverge just a couple of Go code after the initial adoption and this is a cache lookup but maybe this doesn't hurt as a last line of defense? What happens if the cache copy is not yet updated with the owner reference you set above? Will the 2nd patch simply succeed because there is no diff with the server copy or is there an actual error returned?
Now I am thinking that we never supported adopting RCs for DCs, before owner refs, so I am wondering if we are going to break users that have fiddled with RC labels. Maybe warn in the release notes since we are departing from the old way of selecting RCs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I am thinking that we never supported adopting RCs for DCs, before owner refs, so I am wondering if we are going to break users that have fiddled with RC labels. Maybe warn in the release notes since we are departing from the old way of selecting RCs.
Nevermind this one, rechecked and you merely add owner refs on top - should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if the cache copy is not yet updated with the owner reference you set above?
This is in RetryOnConflict
block so in the worst case caches should propagate while doing the backoff, right? We could use an uncached client here.
What happens if the cache copy is not yet updated with the owner reference you set above?
I think that the second patch should result in noop (and succeed).
Not sure about having the RC diverge just a couple of Go code after the initial adoption and this is a cache lookup but maybe this doesn't hurt as a last line of defense?
Well not doing this and patching a RC we don't own due to race condition would break 2. or 3. controller rule
But that also gets me thinking that we can break it under some conditions. There is still race condition in the patches we use (taken from upstream). I think they should really use optimistic concurrency in form of resourceVersion to be completely correct. Hope that works with PATCH
. I'll take the discussion upstream to figure it out because the do the same.
@@ -239,6 +287,18 @@ func (c *DeploymentConfigController) reconcileDeployments(existingDeployments [] | |||
if err != nil { | |||
return err | |||
} | |||
// We need to make sure we own that RC or adopt it if possible | |||
isOurs, err := cm.ClaimReplicationController(rc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as well :)
// If the deployment was already created, just move on. The cache could be | ||
// stale, or another process could have already handled this update. | ||
return c.updateStatus(config, existingDeployments) | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know, I have changed it 2 times while writing it but somehow I wanted to explicitly state that this is for the case where it isn't ours :) and to be resilient to future changes
Automatic merge from submit-queue (batch tested with PRs 46648, 46500, 46238, 46668, 46557) Fix standardFinalizers - add missing metav1.FinalizerDeleteDependents **What this PR does / why we need it**: It adds [FinalizerDeleteDependents](https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go#L77) to [standardFinalizers](https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/pkg/api/helper/helpers.go#L222) otherwise this finalizer is unusable because apiserver will fail validation because it is not fully qualified name - but it is a standard Kubernetes finalizer [used by garbage collector](https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/pkg/controller/garbagecollector/garbagecollector.go#L389) but it can't be set. It's sibling [FinalizerOrphanDependents](https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go#L76) is already [there](https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/pkg/api/helper/helpers.go#L224). I suppose this is a bug because otherwise `FinalizerDeleteDependents` is unusable. Fixes openshift/origin#14322 Might fix #45764 **Not for the reviewer:** [This same definition is also in staging.](https://github.com/kubernetes/kubernetes/blob/58167fcfa10551cc092ee7484e8b41082d0ac223/staging/src/k8s.io/client-go/pkg/api/helper/helpers.go#L222) Does it get propagated to staging automatically? Editing the same file twice doesn't seem like the intended option.
TODO:
Goals
The main goal of ControllerRef (controller reference) is to solve the problem
of controllers that fight over controlled objects due to overlapping selectors.
Fighting controllers can destabilize the apiserver,
thrash objects back-and-forth,
or cause controller operations to hang.
A secondary goal of ControllerRef is to provide back-links from a given object
to the controller that manages it, which can be used for:
third-party controller types in advance.
By being a subtype of OwnerReference it fixes a bug when the underlying RC are not removed when the object is deleted using API.
CC @mfojtik @Kargakis