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

unified function to set sysctl values #580

Merged
merged 9 commits into from
Nov 22, 2018
Merged
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
69 changes: 31 additions & 38 deletions pkg/controllers/proxy/network_services_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,28 +275,46 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
if err != nil {
return errors.New("Failed to do add masquerad rule in POSTROUTING chain of nat table due to: %s" + err.Error())
}

// https://www.kernel.org/doc/Documentation/networking/ipvs-sysctl.txt
// enable ipvs connection tracking
err = ensureIpvsConntrack()
if err != nil {
return errors.New("Failed to do sysctl net.ipv4.vs.conntrack=1 due to: %s" + err.Error())
sysctlErr := utils.SetSysctl("net/ipv4/vs/conntrack", 1)
if sysctlErr != nil {
return errors.New(sysctlErr.Error())
}

// LVS failover not working with UDP packets https://access.redhat.com/solutions/58653
err = ensureIpvsExpireNodestConn()
if err != nil {
return errors.New("Failed to do sysctl net.ipv4.vs.expire_nodest_conn=1 due to: %s" + err.Error())
sysctlErr = utils.SetSysctl("net/ipv4/vs/expire_nodest_conn", 1)
if sysctlErr != nil {
return errors.New(sysctlErr.Error())
}

// LVS failover not working with UDP packets https://access.redhat.com/solutions/58653
err = ensureIpvsQuiescentTemplate()
if err != nil {
return errors.New("Failed to do sysctl net.ipv4.vs.expire_quiescent_template=1 due to: %s" + err.Error())
sysctlErr = utils.SetSysctl("net/ipv4/vs/expire_quiescent_template", 1)
if sysctlErr != nil {
return errors.New(sysctlErr.Error())
}

err = ensureIpvsConnReuseMode()
if err != nil {
return fmt.Errorf("failed to set net.ipv4.vs.conn_reuse_mode=0: %s", err)
// https://github.com/kubernetes/kubernetes/pull/71114
sysctlErr = utils.SetSysctl("net/ipv4/vs/conn_reuse_mode", 0)
if sysctlErr != nil {
// Check if the error is fatal, on older kernels this option does not exist and the same behaviour is default
// if option is not found just log it
if sysctlErr.IsFatal() {
return errors.New(sysctlErr.Error())
}
glog.Info(sysctlErr.Error())
}

// https://github.com/kubernetes/kubernetes/pull/70530/files
sysctlErr = utils.SetSysctl("net/ipv4/conf/all/arp_ignore", 1)
if sysctlErr != nil {
return errors.New(sysctlErr.Error())
}

// https://github.com/kubernetes/kubernetes/pull/70530/files
sysctlErr = utils.SetSysctl("net/ipv4/conf/all/arp_announce", 2)
if sysctlErr != nil {
return errors.New(sysctlErr.Error())
}

// loop forever unitl notified to stop on stopCh
Expand Down Expand Up @@ -1405,31 +1423,6 @@ func deleteHairpinIptablesRules() error {
return nil
}

func ensureIpvsConntrack() error {
return ioutil.WriteFile("/proc/sys/net/ipv4/vs/conntrack", []byte(strconv.Itoa(1)), 0640)
}

func ensureIpvsConnReuseMode() error {
sysctlPath := "/proc/sys/net/ipv4/vs/conn_reuse_mode"
if _, err := os.Stat(sysctlPath); err != nil {
if os.IsNotExist(err) {
glog.Infof("%s not found, skipping setting net.ipv4.vs.conn_reuse_mode=0 (non fatal error, feature introduced into kernel in 4.1)", sysctlPath)
return nil
}
glog.Errorf("skipping setting net.ipv4.vs.conn_reuse_mode=0, error stating: %s : %s", sysctlPath, err.Error())
return nil
}
return ioutil.WriteFile(sysctlPath, []byte(strconv.Itoa(0)), 0640)
}

func ensureIpvsExpireNodestConn() error {
return ioutil.WriteFile("/proc/sys/net/ipv4/vs/expire_nodest_conn", []byte(strconv.Itoa(1)), 0640)
}

func ensureIpvsQuiescentTemplate() error {
return ioutil.WriteFile("/proc/sys/net/ipv4/vs/expire_quiescent_template", []byte(strconv.Itoa(1)), 0640)
}

func deleteMasqueradeIptablesRule() error {
iptablesCmdHandler, err := iptables.New()
if err != nil {
Expand Down
41 changes: 41 additions & 0 deletions pkg/utils/sysctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package utils

import (
"fmt"
"io/ioutil"
"os"
"strconv"
)

type SysctlError struct {
err string
option string
value int
fatal bool
}

// Error return the error as string
func (e *SysctlError) Error() string {
return fmt.Sprintf("Sysctl %s=%d : %s", e.option, e.value, e.err)
}

roffe marked this conversation as resolved.
Show resolved Hide resolved
// IsFatal was the error fatal and reason to exit kube-router
func (e *SysctlError) IsFatal() bool {
return e.fatal
}

// SetSysctl sets a sysctl value
func SetSysctl(path string, value int) *SysctlError {
sysctlPath := fmt.Sprintf("/proc/sys/%s", path)
if _, err := os.Stat(sysctlPath); err != nil {
if os.IsNotExist(err) {
return &SysctlError{"option not found, Does your kernel version support this feature?", path, value, false}
}
return &SysctlError{"stat error: " + err.Error(), path, value, true}
}
err := ioutil.WriteFile(sysctlPath, []byte(strconv.Itoa(value)), 0640)
if err != nil {
return &SysctlError{"could not set due to: " + err.Error(), path, value, true}
}
return nil
}