Merge branch 'master' of https://github.com/zettio/weave
This commit is contained in:
commit
707041c7d0
7 files changed
+138
-26
No files matched your search
@@ -188,6 +188,35 @@ each other but not the containers of our first application...
|
||||
This isolation-through-subnets scheme is an example of carrying over a
|
||||
well-known technique from the 'on metal' days to containers.
|
||||
|
||||
### Dynamic network attachment
|
||||
|
||||
In some scenarios containers are started independently, e.g. via some
|
||||
existing tool chain, or require more complex startup sequences than
|
||||
provided by `weave run`. And sometimes the decision which application
|
||||
network a container should be part of is made post startup. For these
|
||||
situations, weave allows an existing, running container to be attached
|
||||
to the weave network. To illustrate, we can achieve the same effect as
|
||||
the first example with
|
||||
|
||||
host1# C=$(docker run -d -t -i ubuntu)
|
||||
host1# weave attach 10.0.1.1/24 $C
|
||||
|
||||
There is a matching `weave detach` command:
|
||||
|
||||
host1# weave detach 10.0.1.1/24 $C
|
||||
|
||||
You can detach a container from one application network and attach it
|
||||
to another:
|
||||
|
||||
host1# weave detach 10.0.1.1/24 $C
|
||||
host1# weave attach 10.0.2.1/24 $C
|
||||
|
||||
or attach a container to multiple application networks, effectively
|
||||
sharing it between applications:
|
||||
|
||||
host1# weave attach 10.0.1.1/24 $C
|
||||
host1# weave attach 10.0.2.1/24 $C
|
||||
|
||||
### Security
|
||||
|
||||
In order to connect containers across untrusted networks, weave peers
|
||||
@@ -435,6 +464,21 @@ Any running application containers will permanently lose connectivity
|
||||
with the weave network and have to be restarted in order to
|
||||
re-connect.
|
||||
|
||||
### Reboots
|
||||
|
||||
When a host reboots, docker's default behaviour is to restart any
|
||||
containers that were running. Since weave relies on special network
|
||||
configuration outside of the containers, the weave network will not
|
||||
function in this state.
|
||||
|
||||
To remedy this, stop and re-launch the weave container, and re-attach
|
||||
the application containers with `weave attach`.
|
||||
|
||||
For a more permanent solution,
|
||||
[disable Docker's auto-restart feature](https://docs.docker.com/articles/host_integration/)
|
||||
and create appropriate startup scripts to launch weave and run
|
||||
application containers from your favourite process manager.
|
||||
|
||||
## Installation with Boot2Docker
|
||||
|
||||
If you are running Docker inside the Boot2Docker VM, e.g. because you
|
||||
|
||||
+2
-3
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"time"
|
||||
@@ -59,7 +58,7 @@ func (cm *ConnectionMaker) String() string {
|
||||
}
|
||||
|
||||
func (cm *ConnectionMaker) queryLoop(queryChan <-chan *ConnectionMakerInteraction) {
|
||||
timer := time.NewTimer(math.MaxInt64)
|
||||
timer := time.NewTimer(MaxDuration)
|
||||
run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) }
|
||||
for {
|
||||
select {
|
||||
@@ -131,7 +130,7 @@ func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
|
||||
})
|
||||
|
||||
now := time.Now() // make sure we catch items just added
|
||||
after := time.Duration(math.MaxInt64)
|
||||
after := MaxDuration
|
||||
for address, target := range cm.targets {
|
||||
if our_connected_targets[address] {
|
||||
delete(cm.targets, address)
|
||||
|
||||
@@ -2,6 +2,7 @@ package weave
|
||||
|
||||
import (
|
||||
"time"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -23,6 +24,7 @@ const (
|
||||
FragTestInterval = 5 * time.Minute
|
||||
PMTUVerifyAttempts = 8
|
||||
PMTUVerifyTimeout = 10 * time.Millisecond // gets doubled with every attempt
|
||||
MaxDuration = time.Duration(math.MaxInt64)
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -40,7 +40,7 @@ func newPcapIO(ifName string, promisc bool, snaplen int, bufSz int) (handle *Pca
|
||||
if err = inactive.SetSnapLen(snaplen); err != nil {
|
||||
return
|
||||
}
|
||||
if err = inactive.SetTimeout(-1); err != nil {
|
||||
if err = inactive.SetTimeout(MaxDuration); err != nil {
|
||||
return
|
||||
}
|
||||
if err = inactive.SetImmediateMode(true); err != nil {
|
||||
@@ -60,7 +60,12 @@ func newPcapIO(ifName string, promisc bool, snaplen int, bufSz int) (handle *Pca
|
||||
}
|
||||
|
||||
func (pi *PcapIO) ReadPacket() (data []byte, err error) {
|
||||
data, _, err = pi.handle.ZeroCopyReadPacketData()
|
||||
for {
|
||||
data, _, err = pi.handle.ZeroCopyReadPacketData()
|
||||
if err == nil || err != pcap.NextErrorTimeoutExpired {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ MAINTAINER Zettio weave@zett.io
|
||||
WORKDIR /home/weave
|
||||
ADD ./weaver /home/weave/
|
||||
CMD []
|
||||
ENTRYPOINT ["/home/weave/weaver", "-iface", "ethwe", "-wait"]
|
||||
ENTRYPOINT ["/home/weave/weaver", "-iface", "ethwe", "-wait", "5"]
|
||||
+9
-6
@@ -18,17 +18,19 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func ensureInterface(ifaceName string, wait bool) (iface *net.Interface, err error) {
|
||||
func ensureInterface(ifaceName string, wait int) (iface *net.Interface, err error) {
|
||||
iface, err = findInterface(ifaceName)
|
||||
if err == nil || !wait {
|
||||
if err == nil || wait == 0 {
|
||||
return
|
||||
}
|
||||
log.Println("Waiting for interface", ifaceName, "to come up")
|
||||
for err != nil {
|
||||
for ; err != nil && wait > 0; wait -= 1 {
|
||||
time.Sleep(1 * time.Second)
|
||||
iface, err = findInterface(ifaceName)
|
||||
}
|
||||
log.Println("Interface", ifaceName, "is up")
|
||||
if err == nil {
|
||||
log.Println("Interface", ifaceName, "is up")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -47,6 +49,7 @@ func main() {
|
||||
|
||||
log.SetPrefix(weave.Protocol + " ")
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
|
||||
log.Println(os.Args)
|
||||
|
||||
procs := runtime.NumCPU()
|
||||
// packet sniffing can block an OS thread, so we need one thread
|
||||
@@ -60,7 +63,7 @@ func main() {
|
||||
ifaceName string
|
||||
routerName string
|
||||
password string
|
||||
wait bool
|
||||
wait int
|
||||
debug bool
|
||||
prof string
|
||||
peers []string
|
||||
@@ -71,7 +74,7 @@ func main() {
|
||||
flag.StringVar(&ifaceName, "iface", "", "name of interface to read from")
|
||||
flag.StringVar(&routerName, "name", "", "name of router (defaults to MAC)")
|
||||
flag.StringVar(&password, "password", "", "network password")
|
||||
flag.BoolVar(&wait, "wait", false, "wait for interface to be created and come up")
|
||||
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up (defaults to 0, i.e. don't wait)")
|
||||
flag.BoolVar(&debug, "debug", false, "enable debug logging")
|
||||
flag.StringVar(&prof, "profile", "", "enable profiling and write profiles to given path")
|
||||
flag.IntVar(&connLimit, "connlimit", 10, "connection limit (defaults to 10, set to 0 for unlimited)")
|
||||
|
||||
+73
-14
@@ -3,8 +3,10 @@ set -e
|
||||
|
||||
usage() {
|
||||
echo "Usage:"
|
||||
echo "weave launch <ipaddr>/<subnet> [-passwd <passwd>] <peer_host> ..."
|
||||
echo "weave launch <ipaddr>/<subnet> [-password <password>] <peer_host> ..."
|
||||
echo "weave run <ipaddr>/<subnet> <docker run args> ..."
|
||||
echo "weave attach <ipaddr>/<subnet> <container_id>"
|
||||
echo "weave detach <ipaddr>/<subnet> <container_id>"
|
||||
echo "weave expose <ipaddr>/<subnet>"
|
||||
echo "weave hide <ipaddr>/<subnet>"
|
||||
echo "weave status"
|
||||
@@ -101,7 +103,7 @@ stop_masquerading() {
|
||||
}
|
||||
|
||||
# the following borrows from https://github.com/jpetazzo/pipework
|
||||
configure_container_networking() {
|
||||
container_netns_preamble() {
|
||||
DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' $1)
|
||||
[ "$DOCKERPID" = 0 ] && {
|
||||
echo "Container $1 not running." >&2
|
||||
@@ -122,7 +124,41 @@ configure_container_networking() {
|
||||
GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}"
|
||||
IP_TMPFILE=/tmp/weave_ip_output_$$
|
||||
rm -f $IP_TMPFILE
|
||||
if ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU >$IP_TMPFILE 2>&1 ; then
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
container_netns_postamble() {
|
||||
if [ "$EXITCODE" -ne 0 ] ; then
|
||||
if ! ps -p $DOCKERPID >/dev/null 2>&1 ; then
|
||||
echo "Container $1 died" >&2
|
||||
else
|
||||
echo "Failure during network configuration for container $1:" >&2
|
||||
cat $IP_TMPFILE >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f $IP_TMPFILE
|
||||
rm -f /var/run/netns/$NSPID
|
||||
}
|
||||
|
||||
# Attach Container-ID $1 to the weave network at CIDR address $2,
|
||||
# creating a virtual ethernet device if necessary.
|
||||
# Also turn off tx offload on device $3 inside the namespace.
|
||||
attach() {
|
||||
container_netns_preamble $1
|
||||
|
||||
# If veth name already exists then assume we set it up already;
|
||||
# just add the IP address, if it's not already there
|
||||
if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then
|
||||
if ! (ip netns exec $NSPID ip addr list dev $CONTAINER_IFNAME | grep -qF $2) 2>$IP_TMPFILE ; then
|
||||
if ip netns exec $NSPID ip addr add $2 dev $CONTAINER_IFNAME 2>$IP_TMPFILE ; then
|
||||
EXITCODE=0 # succeeded in adding the address
|
||||
fi
|
||||
else
|
||||
EXITCODE=0 # address was there already
|
||||
fi
|
||||
elif ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU >$IP_TMPFILE 2>&1 ; then
|
||||
if (ip link set $LOCAL_IFNAME master $BRIDGE &&
|
||||
ip link set $LOCAL_IFNAME up &&
|
||||
ip link set $GUEST_IFNAME netns $NSPID) >$IP_TMPFILE 2>&1
|
||||
@@ -138,18 +174,32 @@ configure_container_networking() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$EXITCODE" -ne 0 ] ; then
|
||||
if ! ps -p $DOCKERPID >/dev/null 2>&1 ; then
|
||||
echo "Container $1 died" >&2
|
||||
else
|
||||
echo "Failure during network configuration for container $1:" >&2
|
||||
cat $IP_TMPFILE >&2
|
||||
container_netns_postamble $1
|
||||
|
||||
return $EXITCODE
|
||||
}
|
||||
|
||||
# Detach Container-ID $1 at CIDR address $2 from the weave network
|
||||
# removing the virtual ethernet device if there are no more addresses
|
||||
detach() {
|
||||
container_netns_preamble $1
|
||||
|
||||
if (ip netns exec $NSPID ip addr list dev $CONTAINER_IFNAME | grep -qF $2) 2>$IP_TMPFILE ; then
|
||||
if ip netns exec $NSPID ip addr del $2 dev $CONTAINER_IFNAME 2>$IP_TMPFILE ; then
|
||||
# if no inet addresses remain then delete the veth
|
||||
if [ -z "$(ip netns exec $NSPID ip -f inet addr list dev ethwe 2>$IP_TMPFILE)" ] ; then
|
||||
if ip link del $LOCAL_IFNAME type veth 2>$IP_TMPFILE ; then
|
||||
EXITCODE=0
|
||||
fi
|
||||
else
|
||||
EXITCODE=0
|
||||
fi
|
||||
fi
|
||||
else
|
||||
EXITCODE=0
|
||||
fi
|
||||
|
||||
rm -f $IP_TMPFILE
|
||||
rm -f /var/run/netns/$NSPID
|
||||
|
||||
container_netns_postamble $1
|
||||
return $EXITCODE
|
||||
}
|
||||
|
||||
@@ -186,7 +236,7 @@ case "$COMMAND" in
|
||||
# restarts.
|
||||
MACADDR=`cat /sys/class/net/$BRIDGE/address`
|
||||
CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS zettio/weave -name $MACADDR "$@")
|
||||
configure_container_networking $CONTAINER $IPADDR eth0
|
||||
attach $CONTAINER $IPADDR eth0
|
||||
echo $CONTAINER
|
||||
;;
|
||||
status)
|
||||
@@ -223,9 +273,18 @@ case "$COMMAND" in
|
||||
shift 1
|
||||
create_bridge
|
||||
CONTAINER=$(docker run -d "$@")
|
||||
configure_container_networking $CONTAINER $IPADDR $CONTAINER_IFNAME
|
||||
attach $CONTAINER $IPADDR $CONTAINER_IFNAME
|
||||
echo $CONTAINER
|
||||
;;
|
||||
attach)
|
||||
[ $# -gt 1 ] || usage
|
||||
create_bridge
|
||||
attach $2 $1 $CONTAINER_IFNAME
|
||||
;;
|
||||
detach)
|
||||
[ $# -gt 1 ] || usage
|
||||
detach $2 $1
|
||||
;;
|
||||
expose)
|
||||
[ $# -gt 0 ] || usage
|
||||
IPADDR=$1
|
||||
|
||||
Reference in new issue
Block a user