Merge branch '1.9'
This commit is contained in:
commit
37526728e0
7 files changed
+82
-14
No files matched your search
+6
-2
@@ -106,7 +106,7 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
|
|||||||
|
|
||||||
// NB: This function can be used only by a process that terminates immediately
|
// NB: This function can be used only by a process that terminates immediately
|
||||||
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
|
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
|
||||||
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error {
|
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
||||||
ns, err := netns.GetFromPath(netNSPath)
|
ns, err := netns.GetFromPath(netNSPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -124,7 +124,7 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
|||||||
id = id[:maxIDLen] // trim passed ID if too long
|
id = id[:maxIDLen] // trim passed ID if too long
|
||||||
}
|
}
|
||||||
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
|
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
|
||||||
_, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error {
|
veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, func(veth netlink.Link) error {
|
||||||
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
|
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
|
||||||
return fmt.Errorf("failed to move veth to container netns: %s", err)
|
return fmt.Errorf("failed to move veth to container netns: %s", err)
|
||||||
}
|
}
|
||||||
@@ -136,6 +136,10 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err = netlink.LinkSetHairpin(veth, hairpinMode); err != nil {
|
||||||
|
return fmt.Errorf("unable to set hairpin mode to %t for bridge side of veth %s: %s", hairpinMode, name, err)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
|
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
|
||||||
|
|||||||
+8
-6
@@ -34,7 +34,8 @@ func NewCNIPlugin(weave *weaveapi.Client) *CNIPlugin {
|
|||||||
|
|
||||||
func loadNetConf(bytes []byte) (*NetConf, error) {
|
func loadNetConf(bytes []byte) (*NetConf, error) {
|
||||||
n := &NetConf{
|
n := &NetConf{
|
||||||
BrName: weavenet.WeaveBridgeName,
|
BrName: weavenet.WeaveBridgeName,
|
||||||
|
HairpinMode: true,
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
if err := json.Unmarshal(bytes, n); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||||
@@ -128,7 +129,7 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
|
|||||||
id = fmt.Sprintf("%x", data)
|
id = fmt.Sprintf("%x", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false); err != nil {
|
if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&ip.Address}, false, conf.HairpinMode); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error {
|
if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error {
|
||||||
@@ -218,8 +219,9 @@ func logOnStderr(err error) {
|
|||||||
|
|
||||||
type NetConf struct {
|
type NetConf struct {
|
||||||
types.NetConf
|
types.NetConf
|
||||||
BrName string `json:"bridge"`
|
BrName string `json:"bridge"`
|
||||||
IsGW bool `json:"isGateway"`
|
IsGW bool `json:"isGateway"`
|
||||||
IPMasq bool `json:"ipMasq"`
|
IPMasq bool `json:"ipMasq"`
|
||||||
MTU int `json:"mtu"`
|
MTU int `json:"mtu"`
|
||||||
|
HairpinMode bool `json:"hairpinMode"`
|
||||||
}
|
}
|
||||||
@@ -17,11 +17,12 @@ import (
|
|||||||
|
|
||||||
func attach(args []string) error {
|
func attach(args []string) error {
|
||||||
if len(args) < 4 {
|
if len(args) < 4 {
|
||||||
cmdUsage("attach-container", "[--no-multicast-route] [--keep-tx-on] <container-id> <bridge-name> <mtu> <cidr>...")
|
cmdUsage("attach-container", "[--no-multicast-route] [--keep-tx-on] [--hairpin-mode=true|false] <container-id> <bridge-name> <mtu> <cidr>...")
|
||||||
}
|
}
|
||||||
|
|
||||||
keepTXOn := false
|
keepTXOn := false
|
||||||
withMulticastRoute := true
|
withMulticastRoute := true
|
||||||
|
hairpinMode := true
|
||||||
for i := 0; i < len(args); {
|
for i := 0; i < len(args); {
|
||||||
switch args[i] {
|
switch args[i] {
|
||||||
case "--no-multicast-route":
|
case "--no-multicast-route":
|
||||||
@@ -30,6 +31,9 @@ func attach(args []string) error {
|
|||||||
case "--keep-tx-on":
|
case "--keep-tx-on":
|
||||||
keepTXOn = true
|
keepTXOn = true
|
||||||
args = append(args[:i], args[i+1:]...)
|
args = append(args[:i], args[i+1:]...)
|
||||||
|
case "--hairpin-mode=false":
|
||||||
|
hairpinMode = false
|
||||||
|
args = append(args[:i], args[i+1:]...)
|
||||||
default:
|
default:
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@@ -58,7 +62,7 @@ func attach(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn)
|
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn, hairpinMode)
|
||||||
// If we detected an error but the container has died, tell the user that instead.
|
// If we detected an error but the container has died, tell the user that instead.
|
||||||
if err != nil && !processExists(pid) {
|
if err != nil && !processExists(pid) {
|
||||||
err = fmt.Errorf("Container %s died", args[0])
|
err = fmt.Errorf("Container %s died", args[0])
|
||||||
|
|||||||
+1
-1
@@ -515,7 +515,7 @@ func (proxy *Proxy) attach(containerID string) error {
|
|||||||
|
|
||||||
pid := container.State.Pid
|
pid := container.State.Pid
|
||||||
// Passing 0 for mtu means it will be taken from the bridge
|
// Passing 0 for mtu means it will be taken from the bridge
|
||||||
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn)
|
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,6 +221,10 @@ The list of variables you can set is:
|
|||||||
|
|
||||||
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
|
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
|
||||||
versions (default is blank, i.e. check is enabled)
|
versions (default is blank, i.e. check is enabled)
|
||||||
|
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
|
||||||
|
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
|
||||||
|
kernel is one of those that can panic if hairpin is enabled, then you can disable it
|
||||||
|
by setting `HAIRPIN_MODE=false`.
|
||||||
* `IPALLOC_RANGE` - the range of IP addresses used by Weave Net
|
* `IPALLOC_RANGE` - the range of IP addresses used by Weave Net
|
||||||
and the subnet they are placed in (CIDR format; default `10.32.0.0/12`)
|
and the subnet they are placed in (CIDR format; default `10.32.0.0/12`)
|
||||||
* `EXPECT_NPC` - set to 0 to disable Network Policy Controller (default is on)
|
* `EXPECT_NPC` - set to 0 to disable Network Policy Controller (default is on)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ cni_connect() {
|
|||||||
pid=$(container_pid $1 $2)
|
pid=$(container_pid $1 $2)
|
||||||
id=$(docker_on $1 inspect -f '{{.Id}}' $2)
|
id=$(docker_on $1 inspect -f '{{.Id}}' $2)
|
||||||
run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \
|
run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \
|
||||||
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
|
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
|
||||||
}
|
}
|
||||||
|
|
||||||
run_on $HOST1 sudo mkdir -p /opt/cni/bin
|
run_on $HOST1 sudo mkdir -p /opt/cni/bin
|
||||||
@@ -19,6 +19,11 @@ weave_on $HOST1 launch
|
|||||||
C0=$(docker_on $HOST1 run --net=none --name=c0 -dt $SMALL_IMAGE /bin/sh)
|
C0=$(docker_on $HOST1 run --net=none --name=c0 -dt $SMALL_IMAGE /bin/sh)
|
||||||
C1=$(docker_on $HOST1 run --net=none --privileged --name=c1 -dt $SMALL_IMAGE /bin/sh)
|
C1=$(docker_on $HOST1 run --net=none --privileged --name=c1 -dt $SMALL_IMAGE /bin/sh)
|
||||||
C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh)
|
C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh)
|
||||||
|
CH0=$(docker_on $HOST1 run --net=none --name=ch0 -dt $SMALL_IMAGE /bin/sh)
|
||||||
|
CH1=$(docker_on $HOST1 run --net=none --name=ch1 -dt $SMALL_IMAGE /bin/sh)
|
||||||
|
CH2=$(docker_on $HOST1 run --net=none --name=ch2 -dt $SMALL_IMAGE /bin/sh)
|
||||||
|
|
||||||
|
|
||||||
# Enable unsolicited ARPs so that ping after the address reuse does not time out
|
# Enable unsolicited ARPs so that ping after the address reuse does not time out
|
||||||
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1
|
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1
|
||||||
|
|
||||||
@@ -52,6 +57,29 @@ cni_connect $HOST1 c2 <<EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# examples to test hairpin
|
||||||
|
cni_connect $HOST1 ch0 <<EOF
|
||||||
|
{
|
||||||
|
"name": "weave",
|
||||||
|
"type": "weave-net",
|
||||||
|
"hairpinMode": true
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cni_connect $HOST1 ch1 <<EOF
|
||||||
|
{
|
||||||
|
"name": "weave",
|
||||||
|
"type": "weave-net",
|
||||||
|
"hairpinMode": false
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
cni_connect $HOST1 ch2 <<EOF
|
||||||
|
{
|
||||||
|
"name": "weave",
|
||||||
|
"type": "weave-net"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
C0IP=$(container_ip $HOST1 c0)
|
C0IP=$(container_ip $HOST1 c0)
|
||||||
C1IP=$(container_ip $HOST1 c1)
|
C1IP=$(container_ip $HOST1 c1)
|
||||||
C2IP=$(container_ip $HOST1 c2)
|
C2IP=$(container_ip $HOST1 c2)
|
||||||
@@ -85,6 +113,29 @@ assert_raises "[ $C2IP != $C3IP ]"
|
|||||||
assert_raises "[ $BRIP != $C3IP ]"
|
assert_raises "[ $BRIP != $C3IP ]"
|
||||||
assert_raises "exec_on $HOST1 c1 $PING $C3IP"
|
assert_raises "exec_on $HOST1 c1 $PING $C3IP"
|
||||||
|
|
||||||
|
#####
|
||||||
|
#
|
||||||
|
# Hairpin mode tests
|
||||||
|
#
|
||||||
|
# here we check that the bridge side of the veth is set to hairpin mode (true or false) correctly
|
||||||
|
# check for each of
|
||||||
|
# - ch0 explicitly true
|
||||||
|
# - ch1 explicitly false
|
||||||
|
# - ch2 unset, which should default to true
|
||||||
|
#
|
||||||
|
# we take advantage of the veth name being constructed from the container ID)
|
||||||
|
#
|
||||||
|
# should this reliance ever fail and we need to get it from the system, do the following for each:
|
||||||
|
# CH0_PEER_ID=$(exec_on $HOST1 ch0 cat /sys/class/net/eth0/iflink)
|
||||||
|
# CH0_PEER=$($SSH $HOST1 ip link show | awk "/^${CH0_PEER_ID}:/"' {print $2}' | sed 's/@.*$//g' )
|
||||||
|
# CH0_HAIRPIN=$($SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/$CH0_PEER/hairpin_mode)
|
||||||
|
# assert_raises "[ $CH0_HAIRPIN == 1 ]"
|
||||||
|
#
|
||||||
|
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH0:0:7}/hairpin_mode" "1"
|
||||||
|
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH1:0:7}/hairpin_mode" "0"
|
||||||
|
assert "$SSH $HOST1 cat /sys/devices/virtual/net/weave/brif/vethwepl${CH2:0:7}/hairpin_mode" "1"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548
|
# Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548
|
||||||
stop_weave_on $HOST1
|
stop_weave_on $HOST1
|
||||||
|
|||||||
@@ -745,17 +745,20 @@ create_cni_config() {
|
|||||||
cat >"$1" <<EOF
|
cat >"$1" <<EOF
|
||||||
{
|
{
|
||||||
"name": "weave",
|
"name": "weave",
|
||||||
"type": "weave-net"
|
"type": "weave-net",
|
||||||
|
"hairpinMode": $2
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_cni() {
|
setup_cni() {
|
||||||
|
# if env var HAIRPIN_MODE is not set, default it to true
|
||||||
|
HAIRPIN_MODE=${HAIRPIN_MODE:-true}
|
||||||
if install_cni_plugin $CNI_PLUGIN_DIR ; then
|
if install_cni_plugin $CNI_PLUGIN_DIR ; then
|
||||||
upgrade_cni_plugin $CNI_PLUGIN_DIR
|
upgrade_cni_plugin $CNI_PLUGIN_DIR
|
||||||
fi
|
fi
|
||||||
if [ -d $HOST_ROOT/etc/cni/net.d -a ! -f $HOST_ROOT/etc/cni/net.d/10-weave.conf ] ; then
|
if [ -d $HOST_ROOT/etc/cni/net.d -a ! -f $HOST_ROOT/etc/cni/net.d/10-weave.conf ] ; then
|
||||||
create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf
|
create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf $HAIRPIN_MODE
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user