一、Docker 网络配置

docker提供了许多网络模式来提供容器间的相互通信以及跨主机的通信,常用的有五种网络模式:

  • host模式,使用- -net=host指定。
  • container模式,使用- -net=container:NAME_or_ID指定。
  • none模式,使用- -net=none指定。
  • bridge模式,使用- -net=bridge指定,这个是默认模式。
  • network模式

1、host模式

如果启动容器的时候使用host模式,name这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
演示

$ docker run -itd --net=host --name centos_test1 centos /bin/bash
$ docker run -itd --net=host --name centos_test2 centos /bin/bash

$ docker exec -it centos_test1 bash
$ docker exec -it centos_test2 bash
ifconfig查看eth0 的地址 是一样的,并且和宿主机上的ip是一样的。注意,但是这个只在Linux上使用,其他都不适

2、container模式

这个模式指定新创建的容器和已经存在的容器共享一个Network Namespace,而不是个宿主机共享。新创建的容器不会创建自己的网卡,配置自己的ip,而是和一个指定的容器共享ip、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的、两个容器的进程可以沟通过lo网卡设备通信。
演示:

$ docker run -itd --net=container:reverent_allen --name docker-con nginx

$ docker exec -it reverent_allen  bash
$ docker exec -it docker-con bash
ifconfig 查看IP地址还是一样的

3、none模式

使用none模式,docker容器拥有自己的Network Namespace,但是,并不为docker容器进行任何网络配置,也就是说,这个docker网络模式需要自己配置网卡、iP、路由等配置。

4、bridge模式

当docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过docker0连接在了一个二层网络中。

从docker0子网中分配一个IP给容器使用,并设置docker0的ip地址为容器的默认网关。在主机上创建一堆虚拟网卡veth pair设备,docker将veth pair设备的一端放在心创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

bridge模式是docker的默认网络模式,不写- -net参数,就是bridge模式、使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
演示:

$ docker run -tid --net=bridge --name docker_bri1 centos
$ docker run -tid --net=bridge --name docker_bri2 centos

$ docker exec -it docker_bri1 bash
$ docker exec -it docker_bri2 bash
ifconfig 查看eth0的IP地址,会发现地址是同一个网段的,并且网关是指向宿主机的docker0的

5、network方式

使用自定义网络,可以使用docker network create创建,并且默认支持多种网络驱动,用户可以自由创建桥接网络或者overlay网络。

二、跨主机通信

Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信,二不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信,这种端口映射方式对很多集群应用来说极不方便。如果能让docker容器之间使用值得ip地址进行通信,会解决很多问题。按实现原理可分为直接路由方式、桥接模式(如pipework)、Overlay隧道模式(如flannel、ovs+gre)等。
本文对overlay方式的flannel网路模式 做一示例

flannel是CoreOS研究的一种覆盖网络(overlay network)网络工具,目的是帮助每一个host主机有一个完整的子网。让集群中不同节点的主机创建对的容器都有一个唯一的虚拟IP。

其原理是讲TCP数据包装在另一种网络包里进行路由转发和通信,目前已经支持UDP,Vxlan,AWS,APC和GRE等路由转发的模式。默认节点间通信通过UDP转发。

flannel网络使用etcd存储配置数据和子网分配信息。flannel启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。etcd也存储每个主机对应的ip。flannel使用etcd的watch机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据它来维护一个路由表。

flannel网络不会创建新的bridge,而事用默认的docker0,但创建flannel网络会在主机上创建一个虚拟网卡,挂在docker0上,用于跨主机通信。

带有telnet的docker 镜像 docker netty_docker


图解:

  • 数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。
  • flannel通过ectd服务维护了一张节点间的路由表。
  • 援助的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flannel服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一下的有docker0路由到达目标容器。

1、安装配置etcd

etcd功能:与consul的功能差不多,为主主机间的路由表,flannel的配置信息全部存放在etcd里面,主要负责给各个主机分配subnet。

etcd集群搭建

三台主机

etcd实例名称

IP地址

Hostname

etcd1

192.168.1.101

node1.etcd.com

etcd2

192.168.1.102

node2.etcd.com

etcd3

192.168.1.103

node3.etcd.com

在三个节点上下载etcd
https://github.com/etcd-io/etcd/releases/download/v3.3.11/etcd-v3.3.11-linux-amd64.tar.gz tar xvf etcd-v3.3.11-linux-amd64.tar.gz
cd etcd-v3.3.11-linux-amd64
cp etcd etcdctl /usr/local/bin/
在三个节点上设置启动脚本,也即systemd服务文件

vim /usr/lib/systemd/system/etcd.service
内容如下:
[Unit]
Description=Etcd Server
After=network.target


[Service]
Type=simple
WorkingDirectory=/var/lib/etcd/   
EnvironmentFile=-/etc/etcd/etcd.conf #配置文件路径
ExecStart=/usr/bin/etcd
Type=notify
[Install]
WantedBy=multi-user.target

编写/etc/etcd/etcd.conf文件

node1

vim /etc/etcd/etcd.conf

# [member]
ETCD_NAME=etcd1                 #etcd实例名称
ETCD_DATA_DIR="/var/lib/etcd"         #etcd数据保存目录
ETCD_LISTEN_CLIENT_URLS="http://192.168.1.101:2379,http://127.0.0.1:2379"       #供外部客户端使用的url
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.101:2379,http://127.0.0.1:2379"    #广播给外部客户端使用的url

#[cluster]
ETCD_LISTEN_PEER_URLS="http://192.168.1.101:2380"   #集群内部通信使用的URL
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.101:2380"    #广播给集群内其他成员访问的URL
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.1.101:2380,etcd2=http://192.168.1.102:2380,etcd3=http://192.168.1.103:2380"       #初始集群成员列表
ETCD_INITIAL_CLUSTER_STATE="new"               #初始集群状态,new为新建集群
ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"  #集群的名称
node2
# [member]
ETCD_NAME=etcd2
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_CLIENT_URLS="http://192.168.1.102:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.102:2379,http://127.0.0.1:2379"

#[cluster]
ETCD_LISTEN_PEER_URLS="http://192.168.1.102:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.102:2380"
         ETCD_INITIAL_CLUSTER="etcd1=http://192.168.1.101:2380,etcd2=http://192.168.1.102:2380,etcd3=http://192.168.1.103:2380"
ETCD_INITIAL_CLUSTER_STATE="exist"
ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
node3
# [member]
ETCD_NAME=etcd3
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_CLIENT_URLS="http://192.168.1.103:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.103:2379,http://127.0.0.1:2379"

#[cluster]
ETCD_LISTEN_PEER_URLS="http://192.168.1.103:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.103:2380"
            ETCD_INITIAL_CLUSTER="etcd1=http://192.168.1.101:2380,etcd2=http://192.168.1.102:2380,etcd3=http://192.168.1.103:2380"
ETCD_INITIAL_CLUSTER_STATE="exist"         
ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
启动并检查

启动etcd1上的服务 然后启动etcd2和etcd3上的服务

  • 查看集群中的节点
    etcdctl cluster-healthy
  • 查看集群列表
    etcdctl member list

创建flannel需要的网络段
etcdctl set /coreos.com/network/config ‘{ “Network”: “172.17.0.0/16”}’

2、安装配置flanneld

https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz tar xvf flannel-v0.10.0-linux-amd64.tar.gz
mkdir -p /opt/flanneld/{bin,cfg}
mv flanneld mk-docker-opts.sh /opt/flanneld/bin/

vim /opt/kubernetes/cfg/flanneld
FLANNEL_OPTIONS="–etcd-endpoints=https://192.168.1.101:2379,https://192.168.1.102:2379,https://192.168.1.103:2379"

vim /usr/lib/systemd/system/flanneld.service

[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service

[Service]
Type=notify
EnvironmentFile=/opt/kubernetes/cfg/flanneld
ExecStart=/opt/kubernetes/bin/flanneld --ip-masq $FLANNEL_OPTIONSExecStartPost=/opt/flanneld/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure

[Install]
WantedBy=multi-user.target

vim /usr/lib/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=/run/flannel/subnet.env
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONSExecReload=/bin/kill -s HUP $MAINPIDLimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0Delegate=yesKillMode=process
Restart=on-failure
StartLimitBurst=3StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

systemctl daemon-reload
systemctl start flanneld
systemctl enable flanneld
systemctl restart docker