一、DOCKER 容器之间进行互相通信
容器之间互通
新建两个容器
docker run -d —name box1 busybox /bin/sh -c “while true;do sleep 3600;done”
docker run -d —name box2 busybox /bin/sh -c “while true;do sleep 3600;done”
进入box1 ping box2
docker exec -it ac1aa7242949 /bin/sh
ping 172.17.0.3
表明新建的两个容器之间是可以互通的,他们之间通过bridge docker0进行通信,docker0为他们分别组了一对
为新建的容器指定bridge网络
创建新的bridge网络
docker network ls 查看现在的网络
docker network create -d bridge mybridge 创建自己的bridge
创建容器并且指定bridge
docker run -d —name box5 —network mybridge busybox /bin/sh -c “while true;do sleep 3600;done”
docker run -d —name box6 —network mybridge busybox /bin/sh -c “while true;do sleep 3600;done”
运用自己的创建的bridge两个容器之间会自动link
docker exec -it ac1aa7242949 /bin/sh
ping box5
一张bridge network的图,表明容器之间可以互通,还可以链接互联网
二、Docker容器跨主机通信之:直接路由方式
概述
就目前Docker自身默认的网络来说,单台主机上的不同Docker容器可以借助docker0网桥直接通信,这没毛病,而不同主机上的Docker容器之间只能通过在主机上用映射端口的方法来进行通信,有时这种方式会很不方便,甚至达不到我们的要求,因此位于不同物理机上的Docker容器之间直接使用本身的IP地址进行通信很有必要。再者说,如果将Docker容器起在不同的物理主机上,我们不可避免的会遭遇到Docker容器的跨主机通信问题。本文就来尝试一下。
**
情景构造
如下图所示,我们有两个物理主机1和主机2,我们在各自宿主机上启动一个centos容器,启动成功之后,两个容器分别运行在两个宿主机之上,默认的IP地址分配如图所示,这也是Docker自身默认的网络。
两台主机上的容器如何通信?
此时两台主机上的Docker容器如何直接通过IP地址进行通信?
一种直接想到的方案便是通过分别在各自主机中 添加路由 来实现两个centos容器之间的直接通信。我们来试试吧
方案原理分析
由于使用容器的IP进行路由,就需要避免不同主机上的容器使用了相同的IP,为此我们应该为不同的主机分配不同的子网来保证。于是我们构造一下两个容器之间通信的路由方案,如下图所示。
容器间通信
各项配置如下:
- 主机1的IP地址为:192.168.145.128
- 主机2的IP地址为:192.168.145.129
- 为主机1上的Docker容器分配的子网:172.17.1.0/24
- 为主机2上的Docker容器分配的子网:172.17.2.0/24
这样配置之后,两个主机上的Docker容器就肯定不会使用相同的IP地址从而避免了IP冲突。
我们接下来 定义两条路由规则 即可:
- 所有目的地址为172.17.1.0/24的包都被转发到主机1上
- 所有目的地址为172.17.2.0/24的包都被转发到主机2上
综上所述,数据包在两个容器间的传递过程如下:
- 从container1 发往 container2 的数据包,首先发往container1的“网关”docker0,然后通过查找主机1的路由得知需要将数据包发给主机2,数据包到达主机2后再转发给主机2的docker0,最后由其将数据包转到container2中;反向原理相同,不再赘述。
我们心里方案想的是这样,接下来实践一下看看是否可行。
实际试验
- 0x01. 分别对主机1和主机2上的docker0进行配置
编辑主机1上的 /etc/docker/daemon.json
文件,添加内容:"bip" : "ip/netmask"
{ "bip", "172.17.1.252/24" }
编辑主机2上的 /etc/docker/daemon.json
文件,添加内容:"bip" : "ip/netmask"
{ "bip", "172.17.2.252/24" }
- 0x02. 重启docker服务
主机1和主机2上均执行如下命令重启docker服务以使修改后的docker0网段生效
systemctl restart docker
- 0x03. 添加路由规则
主机1上添加路由规则如下:
route add -net 172.17.2.0 netmask 255.255.255.0 gw 192.168.145.129
主机2上添加路由规则如下:
route add -net 172.17.1.0 netmask 255.255.255.0 gw 192.168.145.128
- 0x04. 配置iptables规则
主机1上添加如下规则:
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.1.0/24 ! -d 172.17.0.0/16 -j MASQUERADE
主机2上添加如下规则:
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.2.0/24 ! -d 172.17.0.0/16 -j MASQUERADE
- 0x05. 启动容器
主机1上启动centos容器:
docker run -it --name container1 centos /bin/bash
主机2上启动centos容器:
docker run -it --name container2 centos /bin/bash
- 0x06. 容器间直接通信
好了,现在两容器可以互ping了
container1 ping container2
container2 ping container1
三、Docker容器跨主机通信之:Calico插件方式
注意:Calico v3以上版本已经不支持Docker进行通信,并且针对ARM架构3.0版本之前的需要自己编译相关可执行文件进行使用.
一、环境配置
操作系统都是ubuntu16.04
host:10.180.149.36 x86
host1:10.180.149.73 Arm
host2:10.180.149.74 Arm
二、安装Etcd
从Github上下载etcd安装包,并将etcd保存在/usr/local/bin文件中
命令行示例:
https://github.com/etcd-io/etcd/releases
建议直接下载安装包,然后复制到相关文件中
完成后启动端口监听
etcd -listen-client-urls http://10.180.149.36:2379 -advertise-client-urls http://10.180.149.36:2379
别注意一个细节:
上面的命令执行后会一直在前台执行中,不能关闭当前终端窗口,关闭当前窗口后,上面启动的etcd集群程序就会关闭!!
正确的做法是将其切到后台执行,在上面etcd集群程序启动后,依次:
1)按键ctrl+z 将其程序挂起,会出现一个序列号,一般为1
2)执行命令:bg 1 1就是上面挂起后出现的序列号
3)执行命令disown -a 这样就将这个程序切到后台运行了
启动程序后:
修改在host1与host2中的配置文件 /etc/systemd/system/docker.service
Docker.service 示例如下:
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376 --containerd=/run/containerd/containerd.sock --cluster-store=consul://10.180.149.36:8500 --cluster-advertise=eth0:2376 --cluster-store=etcd://10.180.149.36:2379
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
[Install]
WantedBy=multi-user.target
重启Docker.service服务
systemctl daemon-reload && systemctl restart docker.service
三、部署Calico
在host1和host2中部署calico网络,注意此处要安装Calico 3.0以下版本
curl -O -L https://github.com/projectcalico/calicoctl/releases/download/v2.6.0/calicoctl
chmod +x calicoctl
mv calicoctl /usr/local/bin/
一、配置文件:
配置calicoctl以访问您的数据存储,配置文件默认情况下,calicoctl
将在上查找配置文件/etc/calico/calicoctl.cfg
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
datastoreType: etcdv3
etcdEndpoints: "https://127.0.0.1:2379"
etcdCACert: |
-----BEGIN CERTIFICATE-----
MIICKzCCAZSgAwIBAgIBAzANBgkqhkiG9w0BAQQFADA3MQswCQYDVQQGEwJVUzER
MA8GA1UEChMITmV0c2NhcGUxFTATBgNVBAsTDFN1cHJpeWEncyBDQTAeFw05NzEw
MTgwMTM2MjVaFw05OTEwMTgwMTM2MjVaMEgxCzAJBgNVBAYTAlVTMREwDwYDVQQK
EwhOZXRzY2FwZTENMAsGA1UECxMEUHViczEXMBUGA==
-----END CERTIFICATE-----
etcdCert: |
-----BEGIN CERTIFICATE-----
gI6iLXgMsp2EOlD56I6FA1jrCtNb01XQvX3eyFuA6g5T1jWGYBDtvQb0WRVkdUy9
L/uK+sHQwtloCSuakcQAsWV9bajCQtHX8XGu25Yz56kpJ/OJjcishxT6pc/sthum
A5PX739JsNUi/p5aG+H/6eNx+ukJP7QaM646YCfS5i8S9DJUvim+/BSlKi2ZiOCd
0MYH4Xb7lmAOTNmTvSYpKo9J2fZ9erw0MYSBTyjh6F7PRbHBiivgUnJfGQ==
-----END CERTIFICATE-----
etcdKey: |
-----BEGIN RSA PRIVATE KEY-----
k0dWj16h9P6TvfcNl2iwT4VIwx0uy2faWBED1DrCJcuQCy5nPrts2ZIaAWPi1t3t
VbDKQvs+KXBEeqh0qYcYkejUXqIF0uKUFLjiQmZssjpL5RHqqWuYKbO87n+Jod1L
TjGRHdbP0zF2U0LdjM17rc2hpJ3qrmgJ7pOLzbXMcOr+NP1ojRCArXhQ4iLs7D8T
eHw9QH4luJYtnmk7x03izLMQdLWcKnUbqh/xOVPyazgJHXwRxwNXpMsBVGY=
-----END RSA PRIVATE KEY-----
二、配置环境变量:
如果calicoctl
无法找到,读取或访问配置文件,它将检查一组特定的环境变量。
ETCD_ENDPOINTS=http://myhost1:2379 calicoctl get bgppeers
附:官方安装文档https://docs.projectcalico.org/getting-started/clis/calicoctl/install
三、下载相关Docker镜像文件:
docker pull calico/node
docker pull quay.io/calico/node
docker pull calico/node-libnetwork
四、运行calicoctl:
calicoctl node run --node-image=quay.io/calico/node:v2.0.6-c /etc/calico/calicoctl.cfg
启动过程如下:
① 设置主机网络,例如 enable IP forwarding。
② 下载并启动 calico-node 容器,calico 会以容器的形式运行(与 weave 类似)。
③ 连接 etcd。
④ calico 启动成功。
五、创建calico网络:
在host1和host2中运行以下命令创建网络:
docker network create --driver calico --ipam-driver calico-ipam ckl_calico
六、在calico网络中运行容器:
在host1中运行容器bbox1 并连接到cal_net1:
docker container run --net cali_net1 --name bbox1 -tid busybox
在host2中运行容器bbox2 ,也连接到cal_net1:
docker container run --net cali_net1 --name bbox2 -tid busybox
七、测试calico网络连通性:
验证测试bbox1与bbox2 的连通性如下:
docker exec bbox1 ping -c bbox2
四、部署常见问题及解决方式
- Calico node ‘calico01’ is already using the IPv4 address 172.16.91.205:imageimage
- 方法一:
如果calico数据不重要的话,可以根据图片中的操作步骤进行删除
etcdctl rm /calico —recusive - 方法二:
根据原因是因为:
多个calico服务,绑定在同一个IP上导致的,
因此,需要检查calico服务的配置文件,看看是不是ip绑定重复了。
- 方法一:
- calicoctl rm /calico —recursive
- calicoctl node status no IPv4 peers foundimage原因:
- 其他节点calico服务没有启动
- ip绑定错误,如下所示:
image
- Error response from daemon: Post http://%2Frun%2Fdocker%2Fplugins%2Fcalico-ipam.sock/IpamDriver.RequestPool: dial unix /run/docker/plugins/calico-ipam.sock: connect: connection refused
image - docker calico 环境,创建容器的容器不能ping通主机
现象一:
没有创建路由, 如下图所示:
image
主机和容器互相不能ping通。
也不报错。
原因是:配置文件
image
也不报错。 - docker network create —driver calico —ipam-driver calico-ipam net2 创建网络后,其他节点上没有同步网络信息?
image
image
原因之一:
其中两个节点上的docker,并没有从etcd里获取数据,因此并没有进行同步。
解决措施:
添加——cluster-store参数即可。
原因之二:
calico的libnetwork进程出问题
libenetwork进程
原因之三:
etcd出问题 - ERROR: Unable to access datastore to query node configuration
image - Idle BGP Error: Bad BGP identifier
现象如下图所示:
master节点
node1节点
node2节点
但是,这种情况,服务好像还可以使用 - Failed to create Calico API client: context deadline exceeded
Failed to create Calico API client: context deadline exceeded
原因是:
calicoctl 客户端读取配置文件/etc/calico/calicoctl.cfg里配置的etcdEndpoints跟etcd集群访问策略不匹配,
etcd集群是非安全访问方式,因此,只需要将etcdEndpoints里的https 改成 http即可了。
解决措施