Skip to content

Commit

Permalink
feat: enable ip_forward, disable arp_ignore arp_filter (#1484)
Browse files Browse the repository at this point in the history
* feat: enable ip_forward, disable arp_ignore arp_filter

we are now enabling ip_forward on the node, this is required for the
embedded-cluster to work properly. we are also disabling arp_ignore
and arp_filter to make sure the system is prepared for calico.

* chore: do not fail if unable to config sysctl

* feat: does not fail if unable to write sysctl config

we only fail if the sysctl binary is not present on the system as we
know that preflights depend on it. if we fail to configure sysctl we
just move on as the preflights are expected to fail later on.

* feat: config sysctl on 'run-prelights' command

we need to configure sysctl before running the preflights.

* chore: add unit tests for the new functions

added unit tests around the sysctl configuation functions.
  • Loading branch information
ricardomaraschini authored Nov 13, 2024
1 parent 3f4d8bd commit d44af2b
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pkg/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,12 @@ func installCommand() *cli.Command {
}

metrics.ReportApplyStarted(c)

logrus.Debugf("configuring sysctl")
if err := configutils.ConfigureSysctl(provider); err != nil {
return fmt.Errorf("unable to configure sysctl: %w", err)
}

logrus.Debugf("configuring network manager")
if err := configureNetworkManager(c, provider); err != nil {
return fmt.Errorf("unable to configure network manager: %w", err)
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmd/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,11 @@ var joinCommand = &cli.Command{
return err
}

logrus.Debugf("configuring sysctl")
if err := configutils.ConfigureSysctl(provider); err != nil {
return fmt.Errorf("unable to configure sysctl: %w", err)
}

// jcmd.InstallationSpec.MetricsBaseURL is the replicated.app endpoint url
replicatedAPIURL := jcmd.InstallationSpec.MetricsBaseURL
proxyRegistryURL := fmt.Sprintf("https://%s", defaults.ProxyRegistryAddress)
Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/preflights.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
"github.com/replicatedhq/embedded-cluster/pkg/configutils"
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
"github.com/replicatedhq/embedded-cluster/pkg/versions"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -79,6 +80,10 @@ func installRunPreflightsCommand() *cli.Command {
return err
}

if err := configutils.ConfigureSysctl(provider); err != nil {
return err
}

applier, err := getAddonsApplier(c, runtimeConfig, "", proxy)
if err != nil {
return err
Expand Down Expand Up @@ -170,6 +175,10 @@ var joinRunPreflightsCommand = &cli.Command{
return err
}

if err := configutils.ConfigureSysctl(provider); err != nil {
return err
}

applier, err := getAddonsApplier(c, jcmd.InstallationSpec.RuntimeConfig, "", jcmd.InstallationSpec.Proxy)
if err != nil {
return err
Expand Down
4 changes: 4 additions & 0 deletions pkg/cmd/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,10 @@ func resetCommand() *cli.Command {
return fmt.Errorf("failed to remove embedded cluster data config: %w", err)
}

if err := helpers.RemoveAll("/etc/sysctl.d/99-embedded-cluster.conf"); err != nil {
return fmt.Errorf("failed to remove embedded cluster sysctl config: %w", err)
}

if _, err := helpers.RunCommand("reboot"); err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmd/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,11 @@ func restoreCommand() *cli.Command {
}
}

logrus.Debugf("configuring sysctl")
if err := configutils.ConfigureSysctl(provider); err != nil {
return fmt.Errorf("unable to configure sysctl: %w", err)
}

proxy, err := getProxySpecFromFlags(c)
if err != nil {
return fmt.Errorf("unable to get proxy spec from flags: %w", err)
Expand Down
29 changes: 29 additions & 0 deletions pkg/configutils/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@ package configutils
import (
"fmt"
"os"
"os/exec"
"path/filepath"

"github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
"github.com/replicatedhq/embedded-cluster/pkg/goods"
"github.com/replicatedhq/embedded-cluster/pkg/helpers"
"github.com/sirupsen/logrus"
"sigs.k8s.io/yaml"
)

// sysctlConfigPath is the path to the sysctl config file that is used to configure
// the embedded cluster. This could have been a constant but we want to be able to
// override it for testing purposes.
var sysctlConfigPath = "/etc/sysctl.d/99-embedded-cluster.conf"

func WriteRuntimeConfig(spec *v1beta1.RuntimeConfigSpec) error {
if spec == nil {
return nil
Expand Down Expand Up @@ -57,3 +65,24 @@ func ReadRuntimeConfig() (*v1beta1.RuntimeConfigSpec, error) {

return &spec, nil
}

// ConfigureSysctl writes the sysctl config file for the embedded cluster and
// reloads the sysctl configuration. This function has a distinct behavior: if
// the sysctl binary does not exist it returns an error but if it fails to lay
// down the sysctl config on disk it simply returns nil.
func ConfigureSysctl(provider *defaults.Provider) error {
if _, err := exec.LookPath("sysctl"); err != nil {
return fmt.Errorf("unable to find sysctl binary: %w", err)
}

materializer := goods.NewMaterializer(provider)
if err := materializer.SysctlConfig(sysctlConfigPath); err != nil {
logrus.Debugf("unable to materialize sysctl config: %v", err)
return nil
}

if _, err := helpers.RunCommand("sysctl", "--system"); err != nil {
logrus.Debugf("unable to configure sysctl: %v", err)
}
return nil
}
41 changes: 41 additions & 0 deletions pkg/configutils/runtime_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package configutils

import (
"os"
"path/filepath"
"testing"

"github.com/replicatedhq/embedded-cluster/pkg/defaults"
"github.com/stretchr/testify/assert"
)

func TestConfigureSysctl(t *testing.T) {
basedir, err := os.MkdirTemp("", "embedded-cluster-test-base-dir")
assert.NoError(t, err)
defer os.RemoveAll(basedir)

orig := sysctlConfigPath
defer func() {
sysctlConfigPath = orig
}()

provider := defaults.NewProvider(basedir)

// happy path.
dstdir, err := os.MkdirTemp("", "embedded-cluster-test")
assert.NoError(t, err)
defer os.RemoveAll(dstdir)

sysctlConfigPath = filepath.Join(dstdir, "sysctl.conf")
err = ConfigureSysctl(provider)
assert.NoError(t, err)

// check that the file exists.
_, err = os.Stat(sysctlConfigPath)
assert.NoError(t, err)

// now use a non-existing directory.
sysctlConfigPath = filepath.Join(dstdir, "non-existing-dir", "sysctl.conf")
// we do not expect an error here.
assert.NoError(t, err)
}
2 changes: 2 additions & 0 deletions pkg/goods/goods.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var (
systemdfs embed.FS
//go:embed internal/bins/*
internalBinfs embed.FS
//go:embed static/*
staticfs embed.FS
)

// K0sBinarySHA256 returns the SHA256 checksum of the embedded k0s binary.
Expand Down
12 changes: 12 additions & 0 deletions pkg/goods/materializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ func (m *Materializer) CalicoNetworkManagerConfig() error {
return nil
}

// SysctlConfig writes the embedded sysctl config to the /etc/sysctl.d directory.
func (m *Materializer) SysctlConfig(dstpath string) error {
content, err := staticfs.ReadFile("static/99-embedded-cluster.conf")
if err != nil {
return fmt.Errorf("unable to open embedded sysctl config file: %w", err)
}
if err := os.WriteFile(dstpath, content, 0644); err != nil {
return fmt.Errorf("unable to write file: %w", err)
}
return nil
}

// Materialize writes to disk all embedded assets.
func (m *Materializer) Materialize() error {
if err := m.Binaries(); err != nil {
Expand Down
34 changes: 34 additions & 0 deletions pkg/goods/materializer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package goods

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

func TestMaterializer_SysctlConfig(t *testing.T) {
m := NewMaterializer(nil)

// happy path.
dstdir, err := os.MkdirTemp("", "embedded-cluster-test")
assert.NoError(t, err)
defer os.RemoveAll(dstdir)

dstpath := filepath.Join(dstdir, "sysctl.conf")
err = m.SysctlConfig(dstpath)
assert.NoError(t, err)

expected, err := os.ReadFile(dstpath)
assert.NoError(t, err)

content, err := staticfs.ReadFile("static/99-embedded-cluster.conf")
assert.NoError(t, err)
assert.Equal(t, string(expected), string(content))

// write to a non-existent directory.
dstpath = filepath.Join(dstdir, "dir-does-not-exist", "sysctl.conf")
err = m.SysctlConfig(dstpath)
assert.Contains(t, err.Error(), "no such file or directory")
}
11 changes: 11 additions & 0 deletions pkg/goods/static/99-embedded-cluster.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# this entry enables ip forwarding. this feature is necessary as embedded
# cluster creates virtual network interfaces and need the traffic among them to
# be forwarded.
net.ipv4.ip_forward = 1

# arp filter and ignore need to be disabled otherwise we can't have arp
# resolving across the calico network interfaces.
net.ipv4.conf.default.arp_filter = 0
net.ipv4.conf.default.arp_ignore = 0
net.ipv4.conf.all.arp_filter = 0
net.ipv4.conf.all.arp_ignore = 0

0 comments on commit d44af2b

Please sign in to comment.