基于etcd服务发现的overlay跨多宿主机容器网络

环境限制

  • 必须安装key-value存储服务用于服务发现,如etcd
  • 宿主机已经安装docker engine
  • 宿主机的hostname必须不同
  • 内核大于3.16
  • 各宿主机的时间需要同步

最简单的时间同步方式,在各个宿主机上执行sudo ntpdate cn.pool.ntp.org 这通常是临时方案.终极方案是搭建时间同步的ntp服务.

环境准备及角色分配

  • 三台ubuntu14.04的server
    由于etcd采用Raft算法, 因此在做决策时需要多数节点的投票, 所以一般部署为奇数节点: 3, 5, 7
    |主机名|ip|内核|启动docker容器名称|docker engine版本|
    |-|-|-|-|-|-|
    |DC-server1|192.168.1.158|4.2.0-27-generic|server1(centOS7)|1.10.3|
    |DC-server2|192.168.1.60|4.2.0-27-generic|server2(centOS7)|1.10.3|
    |DC-server3|192.168.1.24|4.2.0-27-generic||1.10.3|

  • 实验目标:两个CentOS7容器server1,server2网络互通

下载分布式发现服务协调软件:etcd

下载cetcd软件并解压,实际就是将其二进制文件放到$PATH下面即可


aixin@DC-server1$ curl -L  https://github.com/coreos/etcd/releases/download/v2.2.1/etcd-v2.2.1-linux-amd64.tar.gz -o etcd-v2.2.1-linux-amd64.tar.gz
aixin@DC-server1$ tar xzvf etcd-v2.2.1-linux-amd64.tar.gz

aixin@DC-server1$ sudo mv etcd etcdctl /bin

将以上的命令在三台机器上都执行一遍,或者使用scp将以上文件分发到另外两个主机

文件解压之后有如下几个文件:

Documentation  etcd  etcdctl
  • Documents是文档
  • etcd是服务的主执行文件
  • etcdctl是用户客户端命令

启动etcd服务


aixin@DC-server1$ etcd -name node1 
  -initial-advertise-peer-urls http://192.168.1.158:2380 
  -listen-peer-urls http://192.168.1.158:2380 
  -listen-client-urls http://192.168.1.158:2379,http://127.0.0.1:2379 
  -advertise-client-urls http://192.168.1.158:2379 
  -initial-cluster-token etcd-cluster 
  -initial-cluster node1=http://${CLUSTER_IPS[0]}:2380,node2=http://${CLUSTER_IPS[1]}:2380,node3=http://${CLUSTER_IPS[2]}:2380 
  -initial-cluster-state new 
  -data-dir $ETCD_DATADIR  &

aixin@DC-server2$ etcd -name node2 
  -initial-advertise-peer-urls http://192.168.1.60:2380 
  -listen-peer-urls http://192.168.1.60:2380 
  -listen-client-urls http://192.168.1.60:2379,http://127.0.0.1:2379 
  -advertise-client-urls http://192.168.1.60:2379 
  -initial-cluster-token etcd-cluster 
  -initial-cluster node1=http://${CLUSTER_IPS[0]}:2380,node2=http://${CLUSTER_IPS[1]}:2380,node3=http://${CLUSTER_IPS[2]}:2380 
  -initial-cluster-state new 
  -data-dir $ETCD_DATADIR  &
  
aixin@DC-server3$ etcd -name node3 
  -initial-advertise-peer-urls http://192.168.1.24:2380 
  -listen-peer-urls http://192.168.1.24:2380 
  -listen-client-urls http://192.168.1.24:2379,http://127.0.0.1:2379 
  -advertise-client-urls http://192.168.1.24:2379 
  -initial-cluster-token etcd-cluster 
  -initial-cluster node1=http://${CLUSTER_IPS[0]}:2380,node2=http://${CLUSTER_IPS[1]}:2380,node3=http://${CLUSTER_IPS[2]}:2380 
  -initial-cluster-state new 
  -data-dir $ETCD_DATADIR  &

在三台机器上分别启动etcd服务.`CLUSTER_IPS=(192.168.1.158 192.168.1.60 192.168.1.24)`这是一个ip数组.

配置解析

  • listen-peer-urls
    用于节点与节点之间数据交换, 因此需要监听在其他节点可以访问的IP地址上
    默认端口为: 2380 & 7001 (7001不推荐使用, 已基本废弃, 主要用于兼容老服务)
  • listen-client-urls
    用户客户机访问etcd数据, 一般监听在本地, 如果需要集中管理, 可以监听在管理服务器可以访问的IP地址上
    默认端口为: 2379 & 4001 (4001不推荐使用, 已基本废弃, 主要用于兼容老服务)
  • initial-advertise-peer-urls
    该参数表示节点监听其他节点同步信号的地址
    默认端口为: 2380 & 7001 (7001不推荐使用, 已基本废弃, 主要用于兼容老服务)
  • advertise-client-urls
    在加入proxy节点后, 会使用该广播地址, 因此需要监听在一个proxy节点可以访问的IP地址上
    默认端口为: 2379 & 4001 (7001不推荐使用, 已基本废弃, 主要用于兼容老服务)

检查集群的启动是否正确

aixin@DC-server2$ etcdctl cluster-health
member 5a2567911e869c1 is healthy: got healthy result from http://192.168.1.158:2379
member 5a125ed3c29f1acb is healthy: got healthy result from http://192.168.1.24:2379
member 70622961dfd72d05 is healthy: got healthy result from http://192.168.1.60:2379
cluster is healthy

配置Docker并重启

  • 在每一台docker宿主机上做如下配置,并重启docker
sudo vi /etc/default/docker

DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store etcd://<三个IP任选其一>:2379 --cluster-advertise eth0:2375"

sudo service docker restart

  • 集群配置

--cluster-store= 参数指向docker daemon所使用key value service的地址(本例中即etcd的服务地址)
--cluster-advertise= 参数决定了所使用网卡以及docker daemon端口信息

  • 宿主机配置

上面的-H 的参数分别指定了docker demon服务的地址和协议

自动启动shell脚本(优化启动过程)

#!/bin/bash
source ~/workspace/conf/project.cfg
source ./etcd.conf

if [ $# != 1 ] ; then
    echo "USAGE: $0 <SUDO_PASSWD>"
    echo " e.g.: $0 aixin"
    exit 1;
fi 

SUDO_PASSWD=$1
NODE_IP=$(hostname --all-ip-addresses | awk "{print $1}")
ETCD_NODENAME=""

for ((i=1; i<=${#CLUSTER_IPS[*]}; i++))
do
	if [  $1 == ${CLUSTER_IPS[i-1]} ];then
		ETCD_NODENAME="node"${i}
	fi
done

if [ -z $ETCD_NODENAME ];then
	echo "you must enter an ip in CLUSTER_IPS list. conf file is etcd.conf"
	exit 0;
fi

ETCD_DATADIR=${DATA_DIR}/etcd/${ETCD_NODENAME}
if [ ! -d $ETCD_DATADIR ];then
        echo ${SUDO_PASSWD}|sudo -S mkdir -p $ETCD_DATADIR
fi

echo ${SUDO_PASSWD}|sudo -S ./etcd/etcd -name ${ETCD_NODENAME} 
  -initial-advertise-peer-urls http://${NODE_IP}:2380 
  -listen-peer-urls http://${NODE_IP}:2380 
  -listen-client-urls http://${NODE_IP}:2379,http://127.0.0.1:2379 
  -advertise-client-urls http://${NODE_IP}:2379 
  -initial-cluster-token etcd-cluster 
  -initial-cluster node1=http://${CLUSTER_IPS[0]}:2380,node2=http://${CLUSTER_IPS[1]}:2380,node3=http://${CLUSTER_IPS[2]}:2380 
  -initial-cluster-state new 
  -data-dir $ETCD_DATADIR  &

创建overlay网络,并进行容器联通测试

与consul的实现方式对比

consul: 服务发现/全局的分布式key-value存储。自带DNS查询服务,可以跨数据中心。提供节点的健康检查,可以实现动态的consul节点增减.docker官方的用例推荐!
etcd: 服务发现/全局的分布式key-value存储.静态的服务发现,如果实现动态的新增etcd节点,需要依赖第三方组件。

参考

http://my.oschina.net/funwun/blog/689861

http://chunqi.li/2015/11/09/docker-multi-host-networking/

文章导航