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

ebpf: delete existing pinned map if incompatible with the spec #15832

Merged
merged 4 commits into from May 4, 2021

Conversation

jibi
Copy link
Member

@jibi jibi commented Apr 22, 2021

This PR updates the OpenOrCreate() method of the ebpf package to
gracefully handle the case of a pinned map that is incompatible with the
map's spec passed to the method.

Rather than just returning the error returned by NewMapWithOptions(), we
now log a warning and try to delete and recreate the pinned map.

This mimics the behaviour of the old OpenOrCreate() method of the bpf
package.

Fixes: #15629

@maintainer-s-little-helper maintainer-s-little-helper bot added the dont-merge/needs-release-note-label The author needs to describe the release impact of these changes. label Apr 22, 2021
@maintainer-s-little-helper maintainer-s-little-helper bot added this to In progress in 1.10.0 Apr 22, 2021
@jibi jibi added the release-note/misc This PR makes changes that have no direct user impact. label Apr 22, 2021
@maintainer-s-little-helper maintainer-s-little-helper bot removed the dont-merge/needs-release-note-label The author needs to describe the release impact of these changes. label Apr 22, 2021
@jibi jibi added sig/datapath Impacts bpf/ or low-level forwarding details, including map management and monitor messages. release-blocker/1.10 labels Apr 22, 2021
@jibi jibi changed the title bpf: delete existing pinned map if incompatible with the spec ebpf: delete existing pinned map if incompatible with the spec Apr 22, 2021
@jibi
Copy link
Member Author

jibi commented Apr 22, 2021

test-me-please

@jibi jibi requested a review from aanm April 23, 2021 10:35
@jibi jibi requested a review from christarazi April 23, 2021 10:35
@jibi jibi marked this pull request as ready for review April 23, 2021 10:35
@jibi jibi requested a review from a team April 23, 2021 10:35
@jibi jibi requested a review from a team as a code owner April 23, 2021 10:35
@jibi jibi requested a review from borkmann April 23, 2021 10:35
@jibi
Copy link
Member Author

jibi commented Apr 23, 2021

retest-net-next

Comment on lines +82 to +100
// There already exists a pinned map but it has a different
// configuration (e.g different type, k/v size or flags).
// Try to delete and recreate it.
Copy link
Member

Choose a reason for hiding this comment

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

Is it safe to do this for all maps? I also assume this can't be done "atomically"?

Copy link
Member Author

@jibi jibi Apr 26, 2021

Choose a reason for hiding this comment

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

Is it safe to do this for all maps?

That's what we are already doing with all the other maps that are opened using the bpf.OpenOrCreate() method:

cilium/pkg/bpf/map_linux.go

Lines 503 to 505 in 648f4f0

// the Map. If the existing map's attributes such as map type, key/value size,
// capacity, etc. do not match the Map's attributes, then the map will be
// deleted and reopened without any attempt to retain its previous contents.

I'm not saying that this is necessarily the best approach, but since the aim of the ebpf package is to (at least initially) mimic the bpf package (to avoid introducing another dimension of complexity while we migrate to that) I think we should stick with this approach for now

edit: I just found that the bpf package has also an Open() method (in addition to the OpenOrCreate()) which will return an error in case the map's spec is incompatible with the existing map

I also assume this can't be done "atomically"?

That's my understanding, yes

Copy link
Member

@christarazi christarazi left a comment

Choose a reason for hiding this comment

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

I haven't looked deeply at the code yet, but I glanced quickly and couldn't tell if the PR addresses this comment: #15629 (comment)

@jibi
Copy link
Member Author

jibi commented Apr 26, 2021

I haven't looked deeply at the code yet, but I glanced quickly and couldn't tell if the PR addresses this comment: #15629 (comment)

See my previous comment #15832 (comment)

In case the existing map is incompatible with the provided spec and we want to error on that, I believe we should use the bpf.Open() method (which has not been re implemented yet in the ebpf package as we haven't ported any map that requires that)

@aanm
Copy link
Member

aanm commented Apr 28, 2021

@joestringer will provide a look at this PR to understand the implications of it.

@jibi
Copy link
Member Author

jibi commented Apr 28, 2021

@joestringer will provide a look at this PR to understand the implications of it.

Thanks, I'll quickly recap all the context around this change as I fear it might be scattered around at this point:

  • before the switch to cilium/ebpf, the cilium_metrics map was being opened/created with the bpf.OpenOrCreate() method
  • according to the documentation, this method would delete and recreate the map if it was incompatible with the provided spec:

    cilium/pkg/bpf/map_linux.go

    Lines 503 to 505 in 648f4f0

    // the Map. If the existing map's attributes such as map type, key/value size,
    // capacity, etc. do not match the Map's attributes, then the map will be
    // deleted and reopened without any attempt to retain its previous contents.
  • when switching the cilium_metrics map to the cilium/ebpf library I rewrote this method under the ebpf package, missing the fact that the old bpf.OpenOrCreate() method would delete and recreate the map in case it was incompatible with the provided spec
  • this led to the failure documented in Add more user-friendly log messages on map creation #15629
  • this PR addresses this by updating ebpf.OpenOrCreate() to mimic the old bpf.OpenOrCreate() so I don't think I'm introducing anything new, but I'm rather just fixing the new method to be alligned with the behavior of old one
  • (moreover, in case we need to actually handle the case of a mismatch between the map's spec and the pinned map, we should use the bpf.Open() method, which has not been ported yet to the ebpf package as we haven't ported yet any map that requires this)

Copy link
Member

@christarazi christarazi left a comment

Choose a reason for hiding this comment

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

LGTM, one minor nit

pkg/ebpf/map.go Outdated Show resolved Hide resolved
@jibi
Copy link
Member Author

jibi commented Apr 28, 2021

test-me-please

Copy link
Member

@joestringer joestringer left a comment

Choose a reason for hiding this comment

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

Thanks for the recap, that was useful framing to consider these changes.

I went through the call stack for both cases and noticed a couple of remaining minor differences which I've highlighted below.

pkg/ebpf/map.go Outdated Show resolved Hide resolved
pkg/ebpf/map.go Outdated Show resolved Hide resolved
@@ -70,13 +71,42 @@ func (m *Map) OpenOrCreate() error {
mapType := bpf.GetMapType(bpf.MapType(m.spec.Type))
m.spec.Flags = m.spec.Flags | bpf.GetPreAllocateMapFlags(mapType)

path := bpf.MapPath(m.spec.Name)
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 we're still missing one other difference between the implementations: pkg/bpf/bpf_linux.go:OpenOrCreateMap() will attempt to create the parent directory here before pinning; from a brief search through the ebpf library I didn't see the same logic.

Might not be too relevant for this PR depending on the order of map creation but we'll want to fix this up at some point before we fully switch libraries over.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, I initially ignored it as cilium_metrics is not the first pinned map opened by the agent, but since we are on it I just added the logic to ebpf.OpenOrCreate()

@aanm aanm removed their assignment Apr 29, 2021
jibi added 2 commits May 3, 2021 09:57
Signed-off-by: Gilberto Bertin <gilberto@isovalent.com>
Signed-off-by: Gilberto Bertin <gilberto@isovalent.com>
@jibi
Copy link
Member Author

jibi commented May 3, 2021

test-me-please

Copy link
Member

@joestringer joestringer left a comment

Choose a reason for hiding this comment

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

Thanks, just one remaining nit (with a few occurrences; we used to lint this out of the codebase but it seems we lost that linter somewhere along the way). Once that's addressed, LGTM.

pkg/ebpf/map.go Outdated
Comment on lines 102 to 103
log.WithField("map", m.spec.Name).
Warnf("Removing map to allow for property upgrade (expect map data loss): %v", errors.Unwrap(err))
Copy link
Member

Choose a reason for hiding this comment

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

Usually we use .WithError() to include an individual error, so that if a log shows up multiple times with different parameters, it is possible to correlate the common pieces in structured logging systems (eg the message is the same across all, but the error itself may vary). This can also help with grepping for an error as we can always tell that the msg= part is static text:

Suggested change
log.WithField("map", m.spec.Name).
Warnf("Removing map to allow for property upgrade (expect map data loss): %v", errors.Unwrap(err))
log.WithField("map", m.spec.Name).
WithError(err).Warn("Removing map to allow for property upgrade (expect map data loss)")

ref. #14156

jibi added 2 commits May 4, 2021 09:31
This commit updates the OpenOrCreate() method of the ebpf package to
gracefully handle the case of a pinned map that is incompatible with the
map's spec passed to the method.

Rather than just returning the error returned by NewMapWithOptions(), we
now log a warning and try to delete and recreate the pinned map.

This mimics the behaviour of the old OpenOrCreate() method of the bpf
package.

Fixes: #15629

Signed-off-by: Gilberto Bertin <gilberto@isovalent.com>
When dealing with a pinned map in the ebpf.OpenOrCreate method, make
sure the map's parent directory does exist (and try to create it in case
it doesn't).

Signed-off-by: Gilberto Bertin <gilberto@isovalent.com>
@jibi
Copy link
Member Author

jibi commented May 4, 2021

test-me-please

@jibi jibi added the ready-to-merge This PR has passed all tests and received consensus from code owners to merge. label May 4, 2021
@maintainer-s-little-helper maintainer-s-little-helper bot added this to Needs backport from master in 1.10.0-rc2 May 4, 2021
@maintainer-s-little-helper maintainer-s-little-helper bot removed the ready-to-merge This PR has passed all tests and received consensus from code owners to merge. label May 4, 2021
@ti-mo ti-mo merged commit 238d6b5 into master May 4, 2021
@ti-mo ti-mo deleted the pr/jibi/maps-logs-msgs branch May 4, 2021 12:26
1.10.0 automation moved this from In progress to Done May 4, 2021
@brb brb mentioned this pull request May 7, 2021
@maintainer-s-little-helper maintainer-s-little-helper bot moved this from Needs backport from master to Backport pending to v1.10 in 1.10.0-rc2 May 7, 2021
@maintainer-s-little-helper maintainer-s-little-helper bot moved this from Backport pending to v1.10 to Backport done to v1.10 in 1.10.0-rc2 May 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note/misc This PR makes changes that have no direct user impact. sig/datapath Impacts bpf/ or low-level forwarding details, including map management and monitor messages.
Projects
No open projects
1.10.0-rc2
Backport done to v1.10
Development

Successfully merging this pull request may close these issues.

Add more user-friendly log messages on map creation
7 participants