-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
datapath: Create sysctl
rp_filter
overwrite config on agent init
SystemD versions greater than 245 will create sysctl config which sets the `rp_filter` value for all network interfaces to 1. This conflicts with cilium which requires `rp_filter` to be 0 on interfaces it uses. This commit adds a small utility/tool: `sysctlfix` which will insert a config file into the `/etc/sysctl.d` dir with the highest priority containing directives to disable `rp_filter` and perhaps to contain other sysctl config in future. This utility is called as an init container before the cilium agent starts. Because the sysctl config is in place before the agent starts, all interfaces created by the agent and matching the patten in the config file will have `rp_filter` disabled, even when SystemD >=245 is installed. Fixes: #10645 Fixes: #19909 Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
- Loading branch information
1 parent
3f822c2
commit cabc658
Showing
60 changed files
with
8,704 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
cilium-sysctlfix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright Authors of Cilium | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
include ../../Makefile.defs | ||
|
||
TARGET := cilium-sysctlfix | ||
|
||
.PHONY: all $(TARGET) $(SUBDIRS) clean install | ||
|
||
all: $(TARGET) | ||
|
||
$(TARGET): | ||
@$(ECHO_GO) | ||
$(QUIET)$(GO_BUILD) -o $@ | ||
|
||
clean: | ||
@$(ECHO_CLEAN) | ||
-$(QUIET)rm -f $(TARGET) | ||
$(QUIET)$(GO_CLEAN) | ||
|
||
install: | ||
$(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) | ||
$(QUIET)$(INSTALL) -m 0755 $(TARGET) $(DESTDIR)$(BINDIR) | ||
|
||
install-binary: install | ||
|
||
install-bash-completion: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Authors of Cilium | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"os" | ||
"path" | ||
"time" | ||
|
||
"github.com/coreos/go-systemd/v22/dbus" | ||
"github.com/spf13/pflag" | ||
) | ||
|
||
// This tool attempts to write a sysctl config file to the sysctl config directory with the highest precedence so | ||
// we can overwrite any other config and ensure correct sysctl options for Cilium to function. | ||
|
||
var ( | ||
flagSet = pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError) | ||
|
||
sysctlD = flagSet.String("sysctl-conf-dir", "/etc/sysctl.d/", "Path to the sysctl config directory") | ||
// The 99-zzz prefix ensures our config file gets precedence over most if not all other files. | ||
ciliumOverwrites = flagSet.String( | ||
"sysctl-config-file", | ||
"99-zzz-override_cilium.conf", | ||
"Filename of the cilium sysctl overwrites config file", | ||
) | ||
// Name of the systemd-sysctl unit to restart after making changes | ||
sysctlUnit = flagSet.String( | ||
"systemd-sysctl-unit", | ||
"systemd-sysctl.service", | ||
"Name of the systemd sysctl unit to reload", | ||
) | ||
) | ||
|
||
var sysctlConfig = ` | ||
# Disable rp_filter on Cilium interfaces since it may cause mangled packets to be dropped | ||
net.ipv4.conf.lxc*.rp_filter = 0 | ||
net.ipv4.conf.cilium_*.rp_filter = 0 | ||
# The kernel uses max(conf.all, conf.{dev}) as its value, so we need to set .all. to 0 as well. | ||
# Otherwise it will overrule the device specific settings. | ||
net.ipv4.conf.all.rp_filter = 0 | ||
` | ||
|
||
// This program is executed by an init container so we purposely don't | ||
// exit with any error codes. In case of errors, the function will print warnings, | ||
// but we don't block cilium agent pod from running. | ||
func main() { | ||
err := flagSet.Parse(os.Args[1:]) | ||
if err != nil { | ||
fmt.Printf("parse flags: %s\n", err) | ||
return | ||
} | ||
|
||
info, err := os.Stat(*sysctlD) | ||
if err != nil { | ||
fmt.Printf("can't stat sysctl.d dir '%s': %s\n", *sysctlD, err) | ||
return | ||
} | ||
|
||
if !info.IsDir() { | ||
fmt.Printf("'%s' is not a directory\n", *sysctlD) | ||
return | ||
} | ||
|
||
overwritesPath := path.Join(*sysctlD, *ciliumOverwrites) | ||
f, err := os.OpenFile(overwritesPath, os.O_RDWR|os.O_CREATE, 0644) | ||
if err != nil { | ||
fmt.Printf("unable to create cilium sysctl overwrites config: %s\n", err) | ||
return | ||
} | ||
defer f.Close() | ||
|
||
currentContents, err := io.ReadAll(f) | ||
if err != nil { | ||
fmt.Printf("read config: %s\n", err) | ||
return | ||
} | ||
|
||
if string(currentContents) == sysctlConfig { | ||
fmt.Println("sysctl config up-to-date, nothing to do") | ||
return | ||
} | ||
|
||
_, err = f.Seek(0, io.SeekStart) | ||
if err != nil { | ||
fmt.Printf("error while seeking to start of sysctl config: %s\n", err) | ||
return | ||
} | ||
|
||
// Truncate the whole file | ||
err = f.Truncate(0) | ||
if err != nil { | ||
fmt.Printf("error while truncating sysctl config: %s\n", err) | ||
return | ||
} | ||
|
||
_, err = fmt.Fprint(f, sysctlConfig) | ||
if err != nil { | ||
fmt.Printf("error while writing to sysctl config: %s\n", err) | ||
return | ||
} | ||
|
||
fmt.Println("sysctl config created/updated") | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) | ||
defer cancel() | ||
|
||
conn, err := dbus.NewSystemdConnectionContext(ctx) | ||
if err != nil { | ||
fmt.Printf("error while creating SystemD D-Bus connection: %s\n", err) | ||
return | ||
} | ||
|
||
_, err = conn.GetUnitPropertiesContext(ctx, *sysctlUnit) | ||
if err != nil { | ||
fmt.Printf("can't verify unit '%s' exists: %s\n", *sysctlUnit, err) | ||
return | ||
} | ||
|
||
// https://www.freedesktop.org/wiki/Software/systemd/dbus/ | ||
// "The mode needs to be one of replace, fail, isolate, ignore-dependencies, ignore-requirements. | ||
// If "replace" the call will start the unit and its dependencies, possibly replacing already queued jobs that | ||
// conflict with this." | ||
const mode = "replace" | ||
|
||
// Restart the systemd-sysctl unit, this will trigger SystemD to apply the new config to all existing interfaces | ||
// which is required for host-interfaces and reloads on existing cilium deployments. | ||
_, err = conn.RestartUnitContext(ctx, *sysctlUnit, mode, nil) | ||
if err != nil { | ||
fmt.Printf("error while restarting unit '%s': %s\n", *sysctlUnit, err) | ||
return | ||
} | ||
|
||
fmt.Printf("systemd unit '%s' restarted\n", *sysctlUnit) | ||
} |
Oops, something went wrong.