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

Garbage collector behavior on invalid ownerReferences for existing uids across namespaces and across kinds is non-deterministic #65200

Closed
caesarxuchao opened this issue Jun 18, 2018 · 36 comments · Fixed by #92743
Assignees
Labels
kind/bug Categorizes issue or PR as related to a bug. lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. priority/critical-urgent Highest priority. Must be actively worked on as someone's top priority right now. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery.
Milestone

Comments

@caesarxuchao
Copy link
Member

caesarxuchao commented Jun 18, 2018

If an object with a given uid is already in the garbage collector uid map, a child object created with an ownerReference pointing to that uid is not treated as having a non-existent parent, even if:

  1. the ownerReference refers to a cluster-scoped kind and no cluster-scoped kind with that name exists
  2. the child is namespaced, and the ownerReference refers to a namespaced kind and no namespace-scoped kind with that name exists in the same namespace
  3. the child is cluster-scoped, and the ownerReference refers to a namespaced kind (since the namespace of the parent is ambiguous, it should be treated as not existing)

Original description follows

Forked from #63386 (comment).

Garbage collector should work for three cases: (a) cluster-scoped owner with namespaced dependents, (b) namespaced owner and namespaced dependents that are in the same namespace, and (c) cluster-scoped owner with cluster-scoped dependents.

Garbage collector should NOT work for the other two cases: (c) namespaced owner with cluster-scoped dependents. (d) owner and dependents that are in different namespaces. Today, GC sometimes work in these two cases. It's a bug for two reasons:

  • This weakens our security guarantees. Users might exploit this bug to grant other users delete permissions.
  • Users might rely on the unsupported behavior.

We can add extra checks in the GC controller to make it never work for case (c) and (d).

cc @lavalamp @liggitt @deads2k

@caesarxuchao caesarxuchao added kind/bug Categorizes issue or PR as related to a bug. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. labels Jun 18, 2018
@tpepper
Copy link
Member

tpepper commented Jun 20, 2018

The discussion in #63386 is unclear to me. While that is 1.11 milestone material, is the content of this issue here a lower priority and deferred to the next milestone and perhaps later cherry-picking? Given the delay, I'd like to assume it is not critical-urgent, but rather than assume...

@kubernetes/sig-api-machinery-bugs can folks comment?

@liggitt
Copy link
Member

liggitt commented Jun 21, 2018

This is longstanding and not a 1.11 blocker.

@wenjiaswe
Copy link
Contributor

/cc @janetkuo @roycaihw

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Sep 23, 2018
@caesarxuchao
Copy link
Member Author

/remove-lifecycle stale
/lifecycle frozen

@k8s-ci-robot k8s-ci-robot added lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Sep 24, 2018
@liggitt liggitt added the priority/important-longterm Important over the long term, but may not be staffed and/or may need multiple releases to complete. label Jun 12, 2019
@roytman
Copy link

roytman commented Sep 5, 2019

I work with K8s 1.13 and observed that GC works when

(d) owner and dependents that are in different namespaces

If required, I can provide a simple test example.

@liggitt
Copy link
Member

liggitt commented Sep 5, 2019

I work with K8s 1.13 and observed that GC works when

(d) owner and dependents that are in different namespaces

It does not work reliably. If you set up a relationship like that, then restart the controller manager, the dependent will usually be deleted (because the uid-indexed owner cache is not populated yet)

@roytman
Copy link

roytman commented Sep 5, 2019

I mean that in my case the dependent is deleted without restart the controller manager. It is quite reproducible.

@liggitt
Copy link
Member

liggitt commented Sep 5, 2019

I mean that in my case the dependent is deleted without restart the controller manager. It is quite reproducible.

That is the expected/desired behavior, but is racy, so sometimes the cross-namespace relationship does not result in deletion until restart. Because it is racy, environmental factors like load and performance (both of the API server and controller manager) can affect results.

@roytman
Copy link

roytman commented Sep 5, 2019

I see, thanks

@liggitt
Copy link
Member

liggitt commented Oct 17, 2019

xref #72192

@liggitt liggitt changed the title Garbage collector needs extra check to prevent cross-namespace cascading deletion Garbage collector behavior on ownerReferences for existing uids across namespaces and across kinds is non-deterministic Oct 17, 2019
@liggitt liggitt added priority/critical-urgent Highest priority. Must be actively worked on as someone's top priority right now. and removed priority/important-longterm Important over the long term, but may not be staffed and/or may need multiple releases to complete. labels Oct 17, 2019
@liggitt liggitt self-assigned this Oct 17, 2019
@liggitt liggitt changed the title Garbage collector behavior on ownerReferences for existing uids across namespaces and across kinds is non-deterministic Garbage collector behavior on invalid ownerReferences for existing uids across namespaces and across kinds is non-deterministic Oct 17, 2019
@tedyu
Copy link
Contributor

tedyu commented Oct 18, 2019

In GarbageCollector#attemptToDeleteItem :

		for _, dep := range deps {
			if dep.isDeletingDependents() {
...
				if _, err := gc.patch(item, patch, gc.unblockOwnerReferencesJSONMergePatch); err != nil {
					return err
				}
				break

I think we should continue with other dependents performing the unblocking (instead of breaking out of the loop).

@k8s-ci-robot k8s-ci-robot added this to the v1.20 milestone Jul 15, 2020
@liggitt
Copy link
Member

liggitt commented Aug 5, 2020

I'm working on a fix for this for the 1.20 timeframe

@sayanchowdhury
Copy link
Member

👋🏽 Hey @liggitt ! I'm from the Bug Triage team. This issue has not been updated for a while, so I'd like to check on the status. The code freeze is starting November 12th (about 3 weeks from now) and while there is still plenty of time, we want to ensure that each PR has a chance to be merged on time.

As the issue is tagged for 1.20, is it still planned for this release?

@liggitt
Copy link
Member

liggitt commented Oct 26, 2020

Yes, work on this is in progress for 1.20

@liggitt
Copy link
Member

liggitt commented Nov 17, 2020

Fixed in 1.20 by #92743

sebgl added a commit to sebgl/cloud-on-k8s that referenced this issue Nov 30, 2020
A k8s bug (kubernetes/kubernetes#65200) may cause the
k8s garbage collection to delete undesired resources in case users manually
copy an operator-managed secret to another namespace.

To avoid that situation, this commit ensures no ownerRef is set on a subset of
managed secrets users are susceptible to copy around:
- the elastic user password secret
- elasticsearch public transport certs
- elasticsearch, kibana, enterprise search, apm server public http certs

Existing ownerReferences set with earlier ECK versions will be removed when
reconciled.

Since they do not have an ownerRef anymore, those secrets are not automatically
deleted when the Elasticsearch resource is deleted. To work around that situation,
the secret reconciliation logic adds an additional set of labels to the reconciled
secrets that don't have an ownerRef specified. These labels reference the "soft"
owner ("soft" as in handled through some custom code and not through k8s builtin
garbage collection logic).
Once a controller receives a deletion event for the resource it manages, it will
automatically remove the soft-owned secrets.
This is done as best-effort. Secrets will remain orphan if:
- the operator is not running when the owner is deleted
- an error happens while deleting the soft-owned secrets
sebgl added a commit to elastic/cloud-on-k8s that referenced this issue Dec 4, 2020
…#3992)

* Don't set an ownerRef on secrets users are susceptible to copy around

A k8s bug (kubernetes/kubernetes#65200) may cause the
k8s garbage collection to delete undesired resources in case users manually
copy an operator-managed secret to another namespace.

To avoid that situation, this commit ensures no ownerRef is set on a subset of
managed secrets users are susceptible to copy around:
- the elastic user password secret
- elasticsearch public transport certs
- elasticsearch, kibana, enterprise search, apm server public http certs

Existing ownerReferences set with earlier ECK versions will be removed when
reconciled.

Since they do not have an ownerRef anymore, those secrets are not automatically
deleted when the Elasticsearch resource is deleted. To work around that situation,
the secret reconciliation logic adds an additional set of labels to the reconciled
secrets that don't have an ownerRef specified. These labels reference the "soft"
owner ("soft" as in handled through some custom code and not through k8s builtin
garbage collection logic).
Once a controller receives a deletion event for the resource it manages, it will
automatically remove the soft-owned secrets.
This is done as best-effort. Secrets will remain orphan if:
- the operator is not running when the owner is deleted
- an error happens while deleting the soft-owned secrets

* Error out the reconciliation on garbage collection errors

* Improvements from PR review

* Label soft-owned secrets with the owner Kind

* Reuse Kind constants instead of hardcoded string

* Fix existing unit tests

* Garbage collect orphan soft-owned secrets on operator startup

* Fix linter warnings

* Add unit tests

* Cover soft owned secrets gc in e2e tests

* Fix linter warning (typo)

* Improvements from PR review

* Trigger reconciliations on soft-owned secrets events

* Fix linter stuff
sebgl added a commit to sebgl/cloud-on-k8s that referenced this issue Dec 4, 2020
…elastic#3992)

* Don't set an ownerRef on secrets users are susceptible to copy around

A k8s bug (kubernetes/kubernetes#65200) may cause the
k8s garbage collection to delete undesired resources in case users manually
copy an operator-managed secret to another namespace.

To avoid that situation, this commit ensures no ownerRef is set on a subset of
managed secrets users are susceptible to copy around:
- the elastic user password secret
- elasticsearch public transport certs
- elasticsearch, kibana, enterprise search, apm server public http certs

Existing ownerReferences set with earlier ECK versions will be removed when
reconciled.

Since they do not have an ownerRef anymore, those secrets are not automatically
deleted when the Elasticsearch resource is deleted. To work around that situation,
the secret reconciliation logic adds an additional set of labels to the reconciled
secrets that don't have an ownerRef specified. These labels reference the "soft"
owner ("soft" as in handled through some custom code and not through k8s builtin
garbage collection logic).
Once a controller receives a deletion event for the resource it manages, it will
automatically remove the soft-owned secrets.
This is done as best-effort. Secrets will remain orphan if:
- the operator is not running when the owner is deleted
- an error happens while deleting the soft-owned secrets

* Error out the reconciliation on garbage collection errors

* Improvements from PR review

* Label soft-owned secrets with the owner Kind

* Reuse Kind constants instead of hardcoded string

* Fix existing unit tests

* Garbage collect orphan soft-owned secrets on operator startup

* Fix linter warnings

* Add unit tests

* Cover soft owned secrets gc in e2e tests

* Fix linter warning (typo)

* Improvements from PR review

* Trigger reconciliations on soft-owned secrets events

* Fix linter stuff
sebgl added a commit to elastic/cloud-on-k8s that referenced this issue Dec 4, 2020
…#3992) (#4008)

* Don't set an ownerRef on secrets users are susceptible to copy around

A k8s bug (kubernetes/kubernetes#65200) may cause the
k8s garbage collection to delete undesired resources in case users manually
copy an operator-managed secret to another namespace.

To avoid that situation, this commit ensures no ownerRef is set on a subset of
managed secrets users are susceptible to copy around:
- the elastic user password secret
- elasticsearch public transport certs
- elasticsearch, kibana, enterprise search, apm server public http certs

Existing ownerReferences set with earlier ECK versions will be removed when
reconciled.

Since they do not have an ownerRef anymore, those secrets are not automatically
deleted when the Elasticsearch resource is deleted. To work around that situation,
the secret reconciliation logic adds an additional set of labels to the reconciled
secrets that don't have an ownerRef specified. These labels reference the "soft"
owner ("soft" as in handled through some custom code and not through k8s builtin
garbage collection logic).
Once a controller receives a deletion event for the resource it manages, it will
automatically remove the soft-owned secrets.
This is done as best-effort. Secrets will remain orphan if:
- the operator is not running when the owner is deleted
- an error happens while deleting the soft-owned secrets

* Error out the reconciliation on garbage collection errors

* Improvements from PR review

* Label soft-owned secrets with the owner Kind

* Reuse Kind constants instead of hardcoded string

* Fix existing unit tests

* Garbage collect orphan soft-owned secrets on operator startup

* Fix linter warnings

* Add unit tests

* Cover soft owned secrets gc in e2e tests

* Fix linter warning (typo)

* Improvements from PR review

* Trigger reconciliations on soft-owned secrets events

* Fix linter stuff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug. lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. priority/critical-urgent Highest priority. Must be actively worked on as someone's top priority right now. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery.
Projects
None yet
Development

Successfully merging a pull request may close this issue.