Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/config/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ const (

DefaultPersistentPercentageNum = 0.3
PersistentSizeMinGiB = 150

SysctlDisableIPv6All = "net.ipv6.conf.all.disable_ipv6"
SysctlDisableIPv6Default = "net.ipv6.conf.default.disable_ipv6"
SysctlDisableIPv6Lo = "net.ipv6.conf.lo.disable_ipv6"
)
22 changes: 22 additions & 0 deletions pkg/config/cos.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,28 @@ func ConvertToCOS(config *HarvesterConfig) (*yipSchema.YipConfig, error) {
// disable multipath for longhorn
disableLonghornMultipathing(&initramfs)

// write a persistent sysctl drop-in and apply at runtime; persists after reboot

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there an installer option to indicate if ipv6 is required (dual mode or ipv6 only mode) ? thanks.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is the groundwork PR, on subsequent PR (the sub task 1.2 of the installer) we can add that feature along with conditional dual stack cidr and conditional network interface configuration based on installer option / panel

initramfs.Directories = append(initramfs.Directories, yipSchema.Directory{
Path: "/etc/sysctl.d",
Permissions: 0755,
Owner: 0,
Group: 0,
})
initramfs.Files = append(initramfs.Files, yipSchema.File{
Path: "/etc/sysctl.d/zz-harvester-enable-ipv6.conf",
Content: fmt.Sprintf("# Written by harvester-installer: overrides /etc/sysctl.d/ipv6.conf\n%s = 0\n%s = 0\n%s = 0\n",
SysctlDisableIPv6All, SysctlDisableIPv6Default, SysctlDisableIPv6Lo),
Permissions: 0644,
Owner: 0,
Group: 0,
})
if initramfs.Sysctl == nil {
initramfs.Sysctl = make(map[string]string)
}
initramfs.Sysctl[SysctlDisableIPv6All] = "0"
initramfs.Sysctl[SysctlDisableIPv6Default] = "0"
initramfs.Sysctl[SysctlDisableIPv6Lo] = "0"

// TOP
if cfg.Install.Mode != ModeInstall {
if err := initRancherdStage(config, &initramfs); err != nil {
Expand Down
75 changes: 75 additions & 0 deletions pkg/config/cos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,78 @@ func containsFile(files []yipSchema.File, fileName string) bool {
}
return false
}

func containsDirectory(dirs []yipSchema.Directory, path string) bool {
for _, d := range dirs {
if d.Path == path {
return true
}
}
return false
}

func TestConvertToCOS_EnableIPv6(t *testing.T) {
testCases := []struct {
name string
check func(t *testing.T, initramfs yipSchema.Stage)
}{
{
name: "sysctl directory present",
check: func(t *testing.T, initramfs yipSchema.Stage) {
assert.True(t, containsDirectory(initramfs.Directories, "/etc/sysctl.d"),
"initramfs.Directories should contain /etc/sysctl.d")
},
},
{
name: "drop-in file present",
check: func(t *testing.T, initramfs yipSchema.Stage) {
assert.True(t, containsFile(initramfs.Files, "/etc/sysctl.d/zz-harvester-enable-ipv6.conf"),
"initramfs.Files should contain /etc/sysctl.d/zz-harvester-enable-ipv6.conf")
},
},
{
name: "drop-in file content",
check: func(t *testing.T, initramfs yipSchema.Stage) {
for _, f := range initramfs.Files {
if f.Path == "/etc/sysctl.d/zz-harvester-enable-ipv6.conf" {
assert.Contains(t, f.Content, SysctlDisableIPv6All+" = 0")
assert.Contains(t, f.Content, SysctlDisableIPv6Default+" = 0")
assert.Contains(t, f.Content, SysctlDisableIPv6Lo+" = 0")
assert.Equal(t, uint32(0644), f.Permissions)
return
}
}
t.Error("drop-in file not found")
},
},
{
name: "sysctl map not nil",
check: func(t *testing.T, initramfs yipSchema.Stage) {
assert.NotNil(t, initramfs.Sysctl)
},
},
{
name: "sysctl map keys",
check: func(t *testing.T, initramfs yipSchema.Stage) {
assert.Equal(t, "0", initramfs.Sysctl[SysctlDisableIPv6All])
assert.Equal(t, "0", initramfs.Sysctl[SysctlDisableIPv6Default])
assert.Equal(t, "0", initramfs.Sysctl[SysctlDisableIPv6Lo])
},
},
}

conf, err := LoadHarvesterConfig(util.LoadFixture(t, "harvester-config.yaml"))
assert.NoError(t, err)
conf.Mode = ModeInstall

yipConfig, err := ConvertToCOS(conf)
assert.NoError(t, err)

initramfs := yipConfig.Stages["initramfs"][0]

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tc.check(t, initramfs)
})
}
}
11 changes: 11 additions & 0 deletions pkg/console/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ func applyNetworks(network config.Network, hostname string) error {
}
}

// enable IPv6 before applying NetworkManager profiles
for _, param := range []string{
config.SysctlDisableIPv6All,
config.SysctlDisableIPv6Default,
config.SysctlDisableIPv6Lo,
} {
if out, execErr := exec.Command("sysctl", "-w", fmt.Sprintf("%s=0", param)).CombinedOutput(); execErr != nil {
logrus.Warnf("Failed to enable IPv6 sysctl %s: %v (%s)", param, execErr, string(out))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this only a warning and why is an error silently ignored?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for the review Volker, good question!

As of today we can't say whether we are in dual stack or ipv4 only mode. This is warning as in case it fails it's not critical for harvester - we don't expect ipv6 to work in IPv4 scenario and we don't expect our installations to fail with ipv6 related errors as of today.

Once we have way to say - ok we are in dual stack mode, then the error here becomes critical for the work of the current configuration and it becomes distinguishable. We can either assign err = execErr or skip evaluation altogether. This is close to what Jian said above.

But merging the change as is today won't break anything in case we decide to release tomorrow with this change in.

This is good catch also it is not clear that's why I added as first point in the feature itself to make this a toggle:

harvester/harvester#10796

Make sure IPv6 is enabled at Kernel level: When we are in dual stack scenario make sure we error out in case we are in dual stack scenario. Currently in applyNetworks we only log warning as we support IPv4 before this feature. Concerns were raised #1298 (comment) and #1298 (comment). So stating it clearly as first point.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Again thanks for the question, will leave the discussion open for others to take a look in case they wonder as well

}
}

err = config.UpdateManagementInterfaceConfig(network, []string{}, config.NMConnectionPath, true)
if err != nil {
return err
Expand Down
Loading