How does the flannel work?


Recently, I am studying kubernetis. During studying, I have known about the flannel. There is some instruction to reproduct simply. I will follow this instruction.


1. Pre-requisite


There are some preparation. Docker and Etcd should be installed before. Here is instruction for installation of Docker. I will install community engine on 2 nodes running "ubuntu 16.04".


sudo apt-get remove docker docker-engine docker.io

sudo apt-get update

sudo apt-get install \

    apt-transport-https \

    ca-certificates \

    curl \

    software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo apt-key fingerprint 0EBFCD88

sudo add-apt-repository \

   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \

   $(lsb_release -cs) \

   stable"

sudo apt-get update

sudo apt-get install docker-ce  


And then, I will install Etcd. I have already written how to install and use Etcd in this post. However, it is more simple in this instruction. In my case, I will run the command in "root directory"


wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz

tar zxvf etcd-v3.0.12-linux-amd64.tar.gz

cd etcd-v3.0.12-linux-amd64


After installation, I will edit the "/etc/hosts" file before running this Etcd. Please note that host name has only single IP address on this file.


vi /etc/hosts

147.75.65.69    node1

147.75.65.63    node2


Each nodes can communicate with each other with these IP addresses.


# At node 1

nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://node1:2380 \

--listen-peer-urls http://node1:2380 \

--listen-client-urls http://node1:2379,http://localhost:2379 \

--advertise-client-urls http://node1:2379 \

--initial-cluster-token etcd-cluster \

--initial-cluster docker-node1=http://node1:2380,docker-node2=http://node2:2380 \

--initial-cluster-state new&


# At node 2

nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://node2:2380 \

--listen-peer-urls http://node2:2380 \

--listen-client-urls http://node2:2379,http://localhost:2379 \

--advertise-client-urls http://node2:2379 \

--initial-cluster-token etcd-cluster \

--initial-cluster docker-node1=http://node1:2380,docker-node2=http://node2:2380 \

--initial-cluster-state new&


Now, I am ready to start the flannel configuration.


cd etcd-v3.0.12-linux-amd64

./etcdctl cluster-health

member 43bb846a7344a01f is healthy: got healthy result from http://node2:2379

member a9aee06e6a14d468 is healthy: got healthy result from http://node1:2379

cluster is healthy


2. Flannel installation.


Download and install the flannel command on each nodes. In my case, I will run the command in "root directory"


wget https://github.com/coreos/flannel/releases/download/v0.6.2/flanneld-amd64 -O flanneld && chmod 755 flanneld


I will make configuration file to create the network topology.


vi flannel-network-config.json

{

    "Network": "172.16.0.0/12",

    "SubnetLen": 24,

    "SubnetMin": "172.16.16.0",

    "SubnetMax": "172.31.247.0",

    "Backend": {

        "Type": "vxlan",

        "VNI": 172,

        "Port": 8889

    }

}


In this documentation, there are the meaning of the above parameters. Especially, "SubnetLen" is IP address range allocated in each host. Flannel use the configuration from Etcd, /coreos.com/network/config. I will set the configuration on Node 1


# At node 1

cd etcd-v3.0.12-linux-amd64/

~/etcd-v3.0.12-linux-amd64$ ./etcdctl set /coreos.com/network/config < ../flannel-network-config.json


I can check if the configuration is set or not on Node 2.


# At node 2

cd etcd-v3.0.12-linux-amd64/

~/etcd-v3.0.12-linux-amd64$ ./etcdctl get /coreos.com/network/config | jq .

{

  "Network": "172.16.0.0/12",

  "SubnetLen": 24,

  "SubnetMin": "172.16.16.0",

  "SubnetMax": "172.31.247.0",

  "Backend": {

    "Type": "vxlan",

    "VNI": 172,

    "Port": 8889

  }

}


Now, I am ready to start the flannel. Before start flannel, I have to look at my network interface status.


# At node 1

nohup sudo ./flanneld -iface=bond0 &


# At node 2

nohup sudo ./flanneld -iface=bond0 &


After start flannel, I can see new interface which is named with "flannel.VNI". In this case, It should be flannel.172.


flannel.172 Link encap:Ethernet  HWaddr 82:41:de:d4:77:d3

          inet addr:172.16.75.0  Bcast:0.0.0.0  Mask:255.240.0.0

          inet6 addr: fe80::8041:deff:fed4:77d3/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1

          RX packets:0 errors:0 dropped:0 overruns:0 frame:0

          TX packets:0 errors:0 dropped:8 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


Also, I can get some information from Etcd.


cd etcd-v3.0.12-linux-amd64/

~/etcd-v3.0.12-linux-amd64# ./etcdctl ls /coreos.com/network/subnets

/coreos.com/network/subnets/172.16.68.0-24

/coreos.com/network/subnets/172.16.75.0-24


This mean that each host has these subnets each. I can see more detail. 


cd etcd-v3.0.12-linux-amd64/

~/etcd-v3.0.12-linux-amd64# ./etcdctl get /coreos.com/network/subnets/172.16.68.0-24 | jq .

{

  "PublicIP": "147.75.65.63",

  "BackendType": "vxlan",

  "BackendData": {

    "VtepMAC": "7a:ac:15:15:2b:61"

  }

}


This is configuration for the flannel. I can also see the what flannel network is assigned with "/var/run/flannel/subnet.env". Please note that this file will be used for next step, docker daemon configuration.


cat /var/run/flannel/subnet.env

FLANNEL_NETWORK=172.16.0.0/12

FLANNEL_SUBNET=172.16.68.1/24

FLANNEL_MTU=1450

FLANNEL_IPMASQ=false


3. Docker daemon configuration.


Docker does not use flannel default. It has swarm mode to make overlay network. Therefore, it is necessary to change to use this flannel as default network module. At first, I have to stop the Docker daemon on each hosts, node1 and node2.


# Node 1 and Node 2

sudo service docker stop


I will restart Docker daemon with this flannel configuration.


# Node 1 and Node 2

source /run/flannel/subnet.env
sudo ifconfig docker0 ${FLANNEL_SUBNET}
sudo dockerd --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} &


Before restart Docker daemon, there is "docker0" interface default which has "172.17.0.1" IP address. It will be changed with the network what I defined.


# Before restart with flannel configuration

ifconfig docker0

docker0   Link encap:Ethernet  HWaddr 02:42:f6:10:ac:49

          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0

          UP BROADCAST MULTICAST  MTU:1500  Metric:1

          RX packets:0 errors:0 dropped:0 overruns:0 frame:0

          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


# After restart with flannel configuration

ifconfig docker0
docker0   Link encap:Ethernet  HWaddr 02:42:f6:10:ac:49
          inet addr:172.16.75.1  Bcast:172.16.75.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


4. Create the Test container and Start it.


Now, I will create 2 container for the test. 


# At the node 1

sudo docker run -d --name test1  busybox sh -c "while true; do sleep 3600; done"


# At the node 2

ssudo docker run -d --name test2  busybox sh -c "while true; do sleep 3600; done"


Depends on the container properties, the container can be stopped after exit. "sh -c "while true; do sleep 3600; done" make this container keep alive for 1 hour. It is enough for the test.


5. Analysis container networks.


In this post, I will explain how to work in docker swarm mode. It is good to analysis the network topology of docker. At first, go to "/var/run/docker", there is the "netns" directory. There is the network configuration of the container.


# At node 1 and node 2 

cd /var/run/

ln -s docker/netns/ netns


After this symbolic link, I can see the network namespace list like below. "ip netns list" show the namespace ID.


ip netns list

faf9928b897f (id: 0)


I can see more detail information with this ID. "ip netns exec" show the same result with "docker exec". Thus I can see the same result with "docker exec test1 ip -d addr show"


# At the Node 1

ip netns exec b5380e6b336a ip -d addr show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0

    inet 127.0.0.1/8 scope host lo

       valid_lft forever preferred_lft forever

11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default

    link/ether 02:42:ac:10:4b:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0

    veth

    inet 172.16.75.2/24 brd 172.16.75.255 scope global eth0

       valid_lft forever preferred_lft forever


# At the Node 2

ip netns exec faf9928b897f ip -d addr show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0

    inet 127.0.0.1/8 scope host lo

       valid_lft forever preferred_lft forever

15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default

    link/ether 02:42:ac:10:44:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0

    veth

    inet 172.16.68.2/24 brd 172.16.68.255 scope global eth0

       valid_lft forever preferred_lft forever


6. Test and Troubleshooting


Now, I have know that "172.16.75.2" is container IP address on Node 1 and "172.16.68.2" is container IP address on Node 2. Flannel offers the overlay network between hosts. So, I will send ICMP (ping) from node1 to node2


ip netns exec b5380e6b336a ping 172.16.68.2

PING 172.16.68.2 (172.16.68.2) 56(84) bytes of data.

^C

--- 172.16.68.2 ping statistics ---

6 packets transmitted, 0 received, 100% packet loss, time 5040ms


Hmm. It does not work. From Docker 1.13 default iptables policy for FORWARDING is DROP,


# At Node 1 and Node 2

sudo iptables -P FORWARD ACCEPT


Wow, I can send ICMP each other.


ip netns exec b5380e6b336a ping 172.16.68.2

ip netns exec b5380e6b336a ping 172.16.68.2 -c 4

PING 172.16.68.2 (172.16.68.2) 56(84) bytes of data.

64 bytes from 172.16.68.2: icmp_seq=1 ttl=62 time=0.364 ms

64 bytes from 172.16.68.2: icmp_seq=2 ttl=62 time=0.310 ms

64 bytes from 172.16.68.2: icmp_seq=3 ttl=62 time=0.319 ms

64 bytes from 172.16.68.2: icmp_seq=4 ttl=62 time=0.308 ms


--- 172.16.68.2 ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 2998ms

rtt min/avg/max/mdev = 0.308/0.325/0.364/0.026 ms


This is the flannel.


Reference


[ 1 ] https://docs.docker.com/install/linux/docker-ce/ubuntu/

[ 2 ] https://docker-k8s-lab.readthedocs.io/en/latest/docker/docker-etcd.html

[ 3 ] https://docker-k8s-lab.readthedocs.io/en/latest/docker/docker-flannel.html

[ 4 ] https://github.com/coreos/flannel/blob/master/Documentation/configuration.md

+ Recent posts