Skip to content

Commit

Permalink
Added iface-regex option
Browse files Browse the repository at this point in the history
Allows for more flexibility when selecting the network interface that
flannel should be using.

Addresses kubernetes#620
  • Loading branch information
mgleung committed Jun 22, 2017
1 parent e0706ca commit 2c62df2
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
1 change: 1 addition & 0 deletions Documentation/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The following configuration illustrates the use of most options with `udp` backe
--etcd-cafile="": SSL Certificate Authority file used to secure etcd communication.
--kube-subnet-mgr: Contact the Kubernetes API for subnet assignment instead of etcd.
--iface="": interface to use (IP or name) for inter-host communication. Defaults to the interface for the default route on the machine.
--iface-regex="": regex expression to match the first interface to use (IP or name) for inter-host communication. If unspecified, will default to the interface for the default route on the machine. This option is superseded by the iface option and will not be used if the iface option is also specified.
--subnet-file=/run/flannel/subnet.env: filename where env variables (subnet and MTU values) will be written to.
--subnet-lease-renew-margin=60: subnet lease renewal margin, in minutes.
--ip-masq=false: setup IP masquerade for traffic destined for outside the flannel network. Flannel assumes that the default policy is ACCEPT in the NAT POSTROUTING chain.
Expand Down
50 changes: 48 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"os"
"os/signal"
"path/filepath"
"regexp"
"strconv"
"strings"
"syscall"
Expand Down Expand Up @@ -65,6 +66,7 @@ type CmdLineOpts struct {
version bool
kubeSubnetMgr bool
iface string
ifaceRegex string
ipMasq bool
subnetFile string
subnetDir string
Expand All @@ -89,6 +91,7 @@ func init() {
flag.StringVar(&opts.etcdUsername, "etcd-username", "", "Username for BasicAuth to etcd")
flag.StringVar(&opts.etcdPassword, "etcd-password", "", "Password for BasicAuth to etcd")
flag.StringVar(&opts.iface, "iface", "", "interface to use (IP or name) for inter-host communication")
flag.StringVar(&opts.ifaceRegex, "iface-regex", "", "regex expression to match the first interface to use (IP or name) for inter-host communication. Skipped if the iface option is also specified")
flag.StringVar(&opts.subnetFile, "subnet-file", "/run/flannel/subnet.env", "filename where env variables (subnet, MTU, ... ) will be written to")
flag.StringVar(&opts.publicIP, "public-ip", "", "IP accessible by other nodes for inter-host communication")
flag.IntVar(&opts.subnetLeaseRenewMargin, "subnet-lease-renew-margin", 60, "Subnet lease renewal margin, in minutes.")
Expand Down Expand Up @@ -140,7 +143,7 @@ func main() {
flagutil.SetFlagsFromEnv(flag.CommandLine, "FLANNELD")

// Work out which interface to use
extIface, err := LookupExtIface(opts.iface)
extIface, err := LookupExtIface(opts.iface, opts.ifaceRegex)
if err != nil {
log.Error("Failed to find interface to use: ", err)
os.Exit(1)
Expand Down Expand Up @@ -306,7 +309,7 @@ func MonitorLease(ctx context.Context, sm subnet.Manager, bn backend.Network) er
}
}

func LookupExtIface(ifname string) (*backend.ExternalInterface, error) {
func LookupExtIface(ifname string, ifregex string) (*backend.ExternalInterface, error) {
var iface *net.Interface
var ifaceAddr net.IP
var err error
Expand All @@ -324,6 +327,49 @@ func LookupExtIface(ifname string) (*backend.ExternalInterface, error) {
return nil, fmt.Errorf("error looking up interface %s: %s", ifname, err)
}
}
} else if len(ifregex) > 0 {
// Use the regex if specified and the iface option for matching a specific ip or name is not used
ifaces, err := net.Interfaces()
if err != nil {
return nil, fmt.Errorf("error listing all interfaces: %s", err)
}

// Check IP
for _, ifaceToMatch := range ifaces {
ifaceIP, err := ip.GetIfaceIP4Addr(&ifaceToMatch)
if err != nil {
// Skip if there is no IPv4 address
continue
}

matched, err := regexp.MatchString(ifregex, ifaceIP.String())
if err != nil {
return nil, fmt.Errorf("regex error matching pattern %s to %s", ifregex, ifaceIP.String())
}

if matched {
ifaceAddr = ifaceIP
iface = &ifaceToMatch
break
}
}

// Check Name
if iface == nil && ifaceAddr == nil {
for _, ifaceToMatch := range ifaces {
matched, err := regexp.MatchString(ifregex, ifaceToMatch.Name)
if err != nil {
return nil, fmt.Errorf("regex error matching pattern %s to %s", ifregex, ifaceToMatch.Name)
}

if matched {
iface = &ifaceToMatch
break
}
}
}

return nil, fmt.Errorf("Could not match pattern %s to any of the available network interfaces", ifregex)
} else {
log.Info("Determining IP address of default interface")
if iface, err = ip.GetDefaultGatewayIface(); err != nil {
Expand Down

0 comments on commit 2c62df2

Please sign in to comment.