本文由高永超在高可用架构群所做的分享整理,转载请注明高可用架构公众号ArchNotes。
高永超(flex)
宜信大数据创新中心云平台运维专家。
目前专注于 DevOps 和 PaaS 平台开发(基础设施方向)。
曾在豆瓣担任过 SA Team Leader。
《Pro Puppet》第一版中文译者。
PaaS 平台的网络需求
在使用 Docker 构建 PaaS 平台的过程中,我们首先遇到的问题是需要选择一个满足需求的网络模型:
让每个容器拥有自己的网络栈,特别是独立的 IP 地址
能够进行跨服务器的容器间通讯,同时不依赖特定的网络设备
有访问控制机制,不同应用之间互相隔离,有调用关系的能够通讯
调研了几个主流的网络模型:
Docker 原生的 Bridge 模型:NAT 机制导致无法使用容器 IP 进行跨服务器通讯(后来发现自定义网桥可以解决通讯问题,但是觉得方案比较复杂)
Docker 原生的 Host 模型:大家都使用和服务器相同的 IP,端口冲突问题很麻烦
Weave OVS 等基于隧道的模型:由于是基于隧道的技术,在用户态进行封包解包,性能折损比较大,同时出现问题时网络抓包调试会很蛋疼
在对上述模型都不怎么满意的情况下,发现了一个还不怎么被大家关注的新项目:Project Calico 。
Project Calico 是纯三层的 SDN 实现,它基于 BPG 协议和 Linux 自己的路由转发机制,不依赖特殊硬件,没有使用 NAT 或 Tunnel 等技术。能够方便的部署在物理服务器,虚拟机(如 OpenStack)或者容器环境下。同时它自带的基于 Iptables 的 ACL 管理组件非常灵活,能够满足比较复杂的安全隔离需求。
使用 Calico 来实现 Docker 的跨服务器通讯
环境准备
两个 Linux 环境 node1|2(物理机,VM 均可),假定 IP 为:192.168.78.21|22
为了简单,请将 node1|2 上的 Iptables INPUT 策略设为 ACCEPT,同时安装 Docker
一个可访问的 Etcd 集群(192.168.78.21:2379),Calico 使用其进行数据存放和节点发现
启动 Calico
在 node1|2 上面下载控制脚本:
# wget https://github.com/projectcalico/calico-docker/releases/download/v0.4.9/calicoctl
启动
# export ETCD_AUTHORITY=192.168.78.21:2379
# ./calicoctl node --ip=192.168.78.21|22
docker ps 能看到:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
74cc20b90b0f calico/node:v0.4.9 "/sbin/my_init" 24 seconds ago Up 23 seconds calico-node
部署测试实例
在 Calico 中,有一个 Profile 的概念(类似 AWS 的 Security Group),位于同一个 Profile 中的实例才能互相通讯,所以我们先创建一个名为 db 的 Profile:
在 node1 上执行:
[node1]# ./calicoctl profile add db
然后启动测试实例:
[node1]# export DOCKER_HOST=localhost:2377
[node1]# docker run -n container1 -e CALICO_IP=auto -e CALICO_PROFILE=db -td ubuntu
这里大家注意,我们注入了两个环境变量:CALICO_IP 和 CALICO_PROFILE 。
前者告诉 CALICO 自动进行 IP 分配,后者将此容器加入到 Profile db 中。
那么 Calico 是怎么做到在容器启动的时候分配 IP 的呢?
大家注意我们在 run 一个容器前,先执行了一个 export,这里其实就是将 Docker API 的入口劫持到了 Calico 那里。Calico 内部是一个 twistd 实现的 Python Daemon,转发所有 Docker 的 API 请求给真正的 Docker 服务,如果发现是 start 则插入自己的逻辑创建容器的网络栈。
容器启动后我们查看 container1 获取的 IP 地址:
[container1]# ip addr
...
8: eth1:
|