Skip to content

Commit

Permalink
docker: Integrate docker containers with Open vSwitch.
Browse files Browse the repository at this point in the history
Open vSwitch does not have native integration with Docker.
INSTALL.Docker explains how Open vSwitch can be integrated
with docker non-natively.

ovs-docker is a helper script to add network interfaces to
docker containers and to attach them as ports to OVS bridge.
This script can be further enhanced as we understand different
use cases.

Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
  • Loading branch information
shettyg committed Oct 16, 2014
1 parent dcd92cf commit ec8f0f0
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 1 deletion.
82 changes: 82 additions & 0 deletions INSTALL.Docker
@@ -0,0 +1,82 @@
How to Use Open vSwitch with Docker
====================================

This document describes how to use Open vSwitch with Docker 1.2.0 or
later. This document assumes that you followed INSTALL or installed
Open vSwitch from distribution packaging such as a .deb or .rpm.
Consult www.docker.com for instructions on how to install Docker.

Limitations
-----------
Currently there is no native integration of Open vSwitch in Docker, i.e.,
one cannot use the Docker client to automatically add a container's
network interface to an Open vSwitch bridge during the creation of the
container. This document describes addition of new network interfaces to an
already created container and in turn attaching that interface as a port to an
Open vSwitch bridge.

Setup
-----
* Create your container, e.g.:

% docker run -d ubuntu:14.04 /bin/sh -c \
"while true; do echo hello world; sleep 1; done"

The above command creates a container with one network interface 'eth0'
and attaches it to a Linux bridge called 'docker0'. 'eth0' by default
gets an IP address in the 172.17.0.0/16 space. Docker sets up iptables
NAT rules to let this interface talk to the outside world. Also since
it is connected to 'docker0' bridge, it can talk to all other containers
connected to the same bridge. If you prefer that no network interface be
created by default, you can start your container with
the option '--net=none', e,g.:

% docker run -d --net=none ubuntu:14.04 /bin/sh -c \
"while true; do echo hello world; sleep 1; done"

The above commands will return a container id. You will need to pass this
value to the utility 'ovs-docker' to create network interfaces attached to an
Open vSwitch bridge as a port. This document will reference this value
as $CONTAINER_ID in the next steps.

* Add a new network interface to the container and attach it to an Open vSwitch
bridge. e.g.:

% ovs-docker add-port br-int eth1 $CONTAINER_ID

The above command will create a network interface 'eth1' inside the container
and then attaches it to the Open vSwitch bridge 'br-int'. This is done by
creating a veth pair. One end of the interface becomes 'eth1' inside the
container and the other end attaches to 'br-int'.

The script also lets one to add an IP address to the interface. e.g.:

% ovs-docker add-port br-int eth1 $CONTAINER_ID 192.168.1.1/24

* A previously added network interface can be deleted. e.g.:

% ovs-docker del-port br-int eth1 $CONTAINER_ID

All the previously added Open vSwitch interfaces inside a container can be
deleted. e.g.:

% ovs-docker del-ports br-int $CONTAINER_ID

It is important that the same $CONTAINER_ID be passed to both add-port
and del-port[s] commands.

* More network control.

Once a container interface is added to an Open vSwitch bridge, one can
set VLANs, create Tunnels, add OpenFlow rules etc for more network control.
Please read the man pages of ovs-vsctl, ovs-ofctl, ovs-vswitchd,
ovsdb-server ovs-vswitchd.conf.db etc for more details.

Docker networking is quite flexible and can be used in multiple ways. For more
information, please read:
https://docs.docker.com/articles/networking

Bug Reporting
-------------

Please report problems to bugs@openvswitch.org.
1 change: 1 addition & 0 deletions Makefile.am
Expand Up @@ -68,6 +68,7 @@ EXTRA_DIST = \
FAQ \
INSTALL \
INSTALL.Debian \
INSTALL.Docker \
INSTALL.DPDK \
INSTALL.Fedora \
INSTALL.KVM \
Expand Down
2 changes: 2 additions & 0 deletions NEWS
Expand Up @@ -39,6 +39,8 @@ Post-v2.3.0
still needed, so this should not be enabled on production environments.
- Stats are no longer updated on fake bond interface.
- Keep active bond slave selection across OVS restart.
- A simple wrapper script, 'ovs-docker', to integrate OVS with Docker
containers.


v2.3.0 - 14 Aug 2014
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -88,6 +88,8 @@ platform, please see one of these files:

To use Open vSwitch...

- ...with Docker on Linux, read INSTALL.Docker.

- ...with KVM on Linux, read INSTALL, read INSTALL.KVM.

- ...with Libvirt, read INSTALL.Libvirt.
Expand Down
1 change: 1 addition & 0 deletions debian/openvswitch-common.install
@@ -1,5 +1,6 @@
usr/bin/ovs-appctl
usr/bin/ovs-benchmark
usr/bin/ovs-docker
usr/bin/ovs-ofctl
usr/bin/ovs-parse-backtrace
usr/bin/ovs-pki
Expand Down
1 change: 1 addition & 0 deletions rhel/openvswitch-fedora.spec.in
Expand Up @@ -173,6 +173,7 @@ systemctl start openvswitch.service
/usr/sbin/ovs-vswitchd
/usr/sbin/ovsdb-server
/usr/bin/ovs-appctl
/usr/bin/ovs-docker
/usr/bin/ovs-dpctl
/usr/bin/ovs-dpctl-top
/usr/bin/ovs-ofctl
Expand Down
1 change: 1 addition & 0 deletions rhel/openvswitch.spec.in
Expand Up @@ -130,6 +130,7 @@ exit 0
/usr/bin/ovs-benchmark
/usr/bin/ovs-dpctl
/usr/bin/ovs-dpctl-top
/usr/bin/ovs-docker
/usr/bin/ovs-ofctl
/usr/bin/ovs-parse-backtrace
/usr/bin/ovs-pcap
Expand Down
4 changes: 3 additions & 1 deletion utilities/automake.mk
Expand Up @@ -4,7 +4,8 @@ bin_PROGRAMS += \
utilities/ovs-dpctl \
utilities/ovs-ofctl \
utilities/ovs-vsctl
bin_SCRIPTS += utilities/ovs-pki
bin_SCRIPTS += utilities/ovs-docker \
utilities/ovs-pki
if HAVE_PYTHON
bin_SCRIPTS += \
utilities/ovs-dpctl-top \
Expand All @@ -27,6 +28,7 @@ EXTRA_DIST += \
utilities/ovs-check-dead-ifs.in \
utilities/ovs-ctl.in \
utilities/ovs-dev.py \
utilities/ovs-docker \
utilities/ovs-dpctl-top.in \
utilities/ovs-l3ping.in \
utilities/ovs-lib.in \
Expand Down
201 changes: 201 additions & 0 deletions utilities/ovs-docker
@@ -0,0 +1,201 @@
#!/bin/bash
# Copyright (C) 2014 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

check_command_avail () {
while [ $# -ne 0 ]; do
if ("$1" --version) > /dev/null 2>&1; then :; else
echo >&2 "$UTIL: missing $1, cannot proceed"
exit 1
fi
shift
done
}

ovs_vsctl () {
ovs-vsctl --timeout=60 "$@"
}

create_netns_link () {
mkdir -p /var/run/netns
if [ ! -e /var/run/netns/"$PID" ]; then
ln -s /proc/"$PID"/ns/net /var/run/netns/"$PID"
trap 'delete_netns_link' 0
for signal in 1 2 3 13 14 15; do
trap 'delete_netns_link; trap - $signal; kill -$signal $$' $signal
done
fi
}

delete_netns_link () {
rm -f /var/run/netns/"$PID"
}

add_port () {
BRIDGE="$1"
INTERFACE="$2"
CONTAINER="$3"
ADDRESS="$4"

if [ "$#" -lt 3 ]; then
usage
exit 1
fi

if ovs_vsctl --may-exist add-br "$BRIDGE"; then :; else
echo >&2 "$UTIL: Failed to create bridge $BRIDGE"
exit 1
fi

if PID=`docker inspect -f '{{.State.Pid}}' "$CONTAINER"`; then :; else
echo >&2 "$UTIL: Failed to get the PID of the container"
exit 1
fi

create_netns_link

# Create a veth pair.
ID=`uuidgen | sed 's/-//g'`
PORTNAME="${ID:0:13}"
ip link add "${PORTNAME}_l" type veth peer name "${PORTNAME}_c"

# Add one end of veth to OVS bridge.
if ovs_vsctl --may-exist add-port "$BRIDGE" "${PORTNAME}_l" \
-- set interface "${PORTNAME}_l" \
external_ids:container_id="$CONTAINER" \
external_ids:container_iface="$INTERFACE"; then :; else
echo >&2 "$UTIL: Failed to add "${PORTNAME}_l" port to bridge $BRIDGE"
ip link delete "${PORTNAME}_l"
exit 1
fi

ip link set "${PORTNAME}_l" up

# Move "${PORTNAME}_c" inside the container and changes its name.
ip link set "${PORTNAME}_c" netns "$PID"
ip netns exec "$PID" ip link set dev "${PORTNAME}_c" name "$INTERFACE"
ip netns exec "$PID" ip link set "$INTERFACE" up

if [ -n "$ADDRESS" ]; then
ip netns exec "$PID" ip addr add "$ADDRESS" dev "$INTERFACE"
fi
}

del_port () {
BRIDGE="$1"
INTERFACE="$2"
CONTAINER="$3"

if [ "$#" -lt 3 ]; then
usage
exit 1
fi

PORT=`ovs_vsctl --data=bare --no-heading --columns=name find interface \
external_ids:container_id="$CONTAINER" \
external_ids:container_iface="$INTERFACE"`
if [ -z "$PORT" ]; then
echo >&2 "$UTIL: Failed to find any attached port in $BRIDGE" \
"for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE"
exit 1
fi

ovs_vsctl --if-exists del-port "$PORT"

ip link delete "$PORT"
}

del_ports () {
BRIDGE="$1"
CONTAINER="$2"
if [ "$#" -lt 2 ]; then
usage
exit 1
fi

PORTS=`ovs_vsctl --data=bare --no-heading --columns=name find interface \
external_ids:container_id="$CONTAINER"`
if [ -z "$PORTS" ]; then
exit 0
fi

for PORT in $PORTS; do
ovs_vsctl --if-exists del-port "$PORT"
ip link delete "$PORT"
done
}

usage() {
cat << EOF
${UTIL}: Performs integration of Open vSwitch with Docker.
usage: ${UTIL} COMMAND
Commands:
add-port BRIDGE INTERFACE CONTAINER [ADDRESS]
Adds INTERFACE inside CONTAINER and connects it as a port
in Open vSwitch BRIDGE. Optionally, sets ADDRESS on
INTERFACE. ADDRESS can include a '/' to represent network
prefix length. e.g.:
${UTIL} add-port br-int eth1 c474a0e2830e 192.168.1.2/24
del-port BRIDGE INTERFACE CONTAINER
Deletes INTERFACE inside CONTAINER and removes its
connection to Open vSwitch BRIDGE. e.g.:
${UTIL} del-port br-int eth1 c474a0e2830e
del-ports BRIDGE CONTAINER
Removes all Open vSwitch interfaces from CONTAINER. e.g.:
${UTIL} del-ports br-int c474a0e2830e
Options:
-h, --help display this help message.
EOF
}

UTIL=$(basename $0)
check_command_avail ovs-vsctl docker uuidgen

if (ip netns) > /dev/null 2>&1; then :; else
echo >&2 "$UTIL: ip utility not found (or it does not support netns),"\
"cannot proceed"
exit 1
fi

if [ $# -eq 0 ]; then
usage
exit 0
fi

case $1 in
"add-port")
shift
add_port "$@"
exit 0
;;
"del-port")
shift
del_port "$@"
exit 0
;;
"del-ports")
shift
del_ports "$@"
exit 0
;;
-h | --help)
usage
exit 0
;;
*)
echo >&2 "$UTIL: unknown command \"$1\" (use --help for help)"
exit 1
;;
esac

0 comments on commit ec8f0f0

Please sign in to comment.