-
Notifications
You must be signed in to change notification settings - Fork 211
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
fix(capture): ignore known copy failure and fix iptables issue #903
base: main
Are you sure you want to change the base?
Changes from 2 commits
b95d2e4
f8cfb2d
fac1200
6ef95a3
b173ff7
e028a85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -188,15 +188,16 @@ func (ncp *NetworkCaptureProvider) CaptureNetworkPacket(filter string, duration, | |
} | ||
|
||
type command struct { | ||
name string | ||
args []string | ||
description string | ||
name string | ||
args []string | ||
description string | ||
ignoreFailure bool | ||
} | ||
|
||
func (ncp *NetworkCaptureProvider) CollectMetadata() error { | ||
ncp.l.Info("Start to collect network metadata") | ||
|
||
iptablesMode := obtainIptablesMode() | ||
iptablesMode := obtainIptablesMode(ncp.l) | ||
ncp.l.Info(fmt.Sprintf("Iptables mode %s is used", iptablesMode)) | ||
iptablesSaveCmdName := fmt.Sprintf("iptables-%s-save", iptablesMode) | ||
iptablesCmdName := fmt.Sprintf("iptables-%s", iptablesMode) | ||
|
@@ -282,9 +283,10 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { | |
description: "networking stats", | ||
}, | ||
{ | ||
name: "cp", | ||
args: []string{"-r", "/proc/sys/net", filepath.Join(ncp.TmpCaptureDir, "proc-sys-net")}, | ||
description: "kernel networking configuration", | ||
name: "cp", | ||
args: []string{"-r", "/proc/sys/net", filepath.Join(ncp.TmpCaptureDir, "proc-sys-net")}, | ||
description: "kernel networking configuration", | ||
ignoreFailure: true, | ||
}, | ||
}, | ||
}, | ||
|
@@ -320,14 +322,15 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { | |
} | ||
|
||
// Write command stdout and stderr to output file | ||
for _, cmd := range cmds { | ||
for _, command := range metadata.commands { | ||
cmd := exec.Command(command.name, command.args...) | ||
if _, err := outfile.WriteString(fmt.Sprintf("%s\n\n", cmd.String())); err != nil { | ||
ncp.l.Error("Failed to write string to file", zap.String("file", outfile.Name()), zap.Error(err)) | ||
} | ||
|
||
cmd.Stdout = outfile | ||
cmd.Stderr = outfile | ||
if err := cmd.Run(); err != nil { | ||
if err := cmd.Run(); err != nil && !command.ignoreFailure { | ||
// Don't return for error to continue capturing following network metadata. | ||
ncp.l.Error("Failed to execute command", zap.String("command", cmd.String()), zap.Error(err)) | ||
// Log the error in output file because this error does not stop capture job pod from finishing, | ||
|
@@ -342,7 +345,7 @@ func (ncp *NetworkCaptureProvider) CollectMetadata() error { | |
cmd := exec.Command(command.name, command.args...) | ||
// Errors will when copying kernel networking configuration for not all files under /proc/sys/net are | ||
// readable, like '/proc/sys/net/ipv4/route/flush', which doesn't implement the read function. | ||
if output, err := cmd.CombinedOutput(); err != nil { | ||
if output, err := cmd.CombinedOutput(); err != nil && !command.ignoreFailure { | ||
// Don't return for error to continue capturing following network metadata. | ||
ncp.l.Error("Failed to execute command", zap.String("command", cmd.String()), zap.String("output", string(output)), zap.Error(err)) | ||
} | ||
|
@@ -361,16 +364,44 @@ func (ncp *NetworkCaptureProvider) Cleanup() error { | |
return nil | ||
} | ||
|
||
func obtainIptablesMode() string { | ||
type iptablesMode string | ||
|
||
const ( | ||
legacyIptablesMode iptablesMode = "legacy" | ||
nftIptablesMode iptablesMode = "nft" | ||
) | ||
|
||
func obtainIptablesMode(l *log.ZapLogger) iptablesMode { | ||
// Since iptables v1.8, nf_tables are introduced as an improvement of legacy iptables, but provides the same user | ||
// interface as legacy iptables through iptables-nft command. | ||
// based on: https://github.com/kubernetes-sigs/iptables-wrappers/blob/97b01f43a8e8db07840fc4b95e833a37c0d36b12/iptables-wrapper-installer.sh | ||
legacySaveOut, _ := exec.Command("iptables-legacy-save").CombinedOutput() | ||
|
||
// when both iptables modes available, we choose the one with more rules. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the thinking behind this? Can you not list all the rules using either one of the modes? Given one is named legacy, shouldn't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When both modes available, we should use the one list more rules, and the one list less rules normally just return empty rules. I am referring to https://github.com/kubernetes-sigs/iptables-wrappers/blob/97b01f43a8e8db07840fc4b95e833a37c0d36b12/iptables-wrapper-installer.sh, which is also mentioned in L377 |
||
nftIptablesModeAvaiable := true | ||
legacyIptablesModeAvaiable := true | ||
legacySaveOut, err := exec.Command("iptables-legacy-save").CombinedOutput() | ||
if err != nil && strings.Contains(err.Error(), "command not found") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about errors with running the command? How should we handle them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I treat all command errors as unavailability of that mode and log the error for us to investigate.
timraymond marked this conversation as resolved.
Show resolved
Hide resolved
|
||
legacyIptablesModeAvaiable = false | ||
} | ||
|
||
legacySaveLineNum := len(strings.Split(string(legacySaveOut), "\n")) | ||
nftSaveOut, _ := exec.Command("iptables-nft-save").CombinedOutput() | ||
nftSaveLineNum := len(strings.Split(string(nftSaveOut), "\n")) | ||
if legacySaveLineNum > nftSaveLineNum { | ||
return "legacy" | ||
nftSaveOut, err := exec.Command("iptables-nft-save").CombinedOutput() | ||
if err != nil && strings.Contains(err.Error(), "command not found") { | ||
nftIptablesModeAvaiable = false | ||
} | ||
|
||
if nftIptablesModeAvaiable && legacyIptablesModeAvaiable { | ||
nftSaveLineNum := len(strings.Split(string(nftSaveOut), "\n")) | ||
if legacySaveLineNum > nftSaveLineNum { | ||
return legacyIptablesMode | ||
} | ||
return "nft" | ||
mainred marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// when only one iptables mode available, we choose the available one when the other one is not available. | ||
// when both iptables modes are not available, we choose the nft mode and let the iptables command fail. | ||
if !nftIptablesModeAvaiable { | ||
return legacyIptablesMode | ||
} | ||
return "nft" | ||
return nftIptablesMode | ||
} |
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 think you should return unhandled errors along with mode.
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.
The ideas in my mind is the failed iptables rules does not break the whole capture.