Winse Blog

走走停停都是风景, 熙熙攘攘都向最好, 忙忙碌碌都为明朝, 何畏之.

Dnsmasq解决docker集群节点互通问题

上个星期学习了一下docker,写了一个伪分布式的Dockerfile

通过--link的方式master能访问slaver,毕竟slaver的相关信息已经被写入到master的hosts文件里面去了嘛!理所当然认为,直接把master的hosts文件全部复制一份到所有slaver节点问题就解决了。

等真正操作的时刻,发现不是那么回事,docker容器不给修改hosts文件!!(2016-1-7 14:18:11 注: Docker 1.6.2已经可以修改/etc/hosts了!重启后hosts的变更也没了,囧)

错误实现

首先,看下不当的操作:

1
2
3
4
5
6
7
8
9
10
# 注意:没有填写image,会去找Dockerfile
[root@docker hadoop]# docker run -d --name slaver1 -h slaver1 hadoop
[root@docker hadoop]# docker run -d --name slaver2 -h slaver2 hadoop
[root@docker hadoop]# docker run -d --name master -h master --link slaver1:slaver1 --link slaver2:slaver2 hadoop

[root@docker ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
dafc82678811        hadoop:latest       /bin/sh -c '/usr/sbi   40 seconds ago      Up 40 seconds       22/tcp              master
86d2da5209c5        hadoop:latest       /bin/sh -c '/usr/sbi   49 seconds ago      Up 48 seconds       22/tcp              master/slaver2,slaver2
7b9761fb05a8        hadoop:latest       /bin/sh -c '/usr/sbi   56 seconds ago      Up 55 seconds       22/tcp              master/slaver1,slaver1

此时,通过--link连接方式,master的hosts中已经包括了slaver1和slaver2,按照正常的路子,登录master拷贝其hosts到slaver节点,一切就妥妥的了。现实是残酷的:

1
2
-bash-4.1# scp /etc/hosts slaver1:/etc/
scp: /etc//hosts: Read-only file system

DNS完美解决问题

首先需要在宿主机器上安装dns服务器,bind不多说比较麻烦。这里参考网上人家解决方式,使用dnsmasq来搭建DNS服务器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@docker ~]# yum install dnsmasq -y

[root@docker ~]# cp /etc/resolv.conf /etc/resolv.dnsmasq.conf 
[root@docker ~]# touch /etc/dnsmasq.hosts

[root@docker ~]# vi /etc/resolv.conf
[root@docker ~]# cat /etc/resolv.conf
; generated by /sbin/dhclient-script
nameserver 127.0.0.1 

[root@docker ~]# vi /etc/dnsmasq.conf
[root@docker ~]# cat /etc/dnsmasq.conf
...
resolv-file=/etc/resolv.dnsmasq.conf
...
addn-hosts=/etc/dnsmasq.hosts

[root@docker ~]# service dnsmasq restart

[root@docker ~]# dig www.baidu.com
...
;; SERVER: 127.0.0.1#53(127.0.0.1)
...

通过dig可以查看当前的DNS服务器你已经修改为localhost了。然后启动docker容器来搭建环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 注意:没有填写image,会去找Dockerfile

[root@docker hadoop]# docker run -d  --dns 172.17.42.1 --name slaver1 -h slaver1 hadoop
[root@docker hadoop]# docker run -d  --dns 172.17.42.1 --name slaver2 -h slaver2 hadoop
[root@docker hadoop]# docker run -d  --dns 172.17.42.1 --name master -h master hadoop

[root@docker ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
f6e63b311e60        hadoop:latest       /bin/sh -c '/usr/sbi   6 seconds ago       Up 5 seconds        22/tcp              master
454ae2c3e435        hadoop:latest       /bin/sh -c '/usr/sbi   13 seconds ago      Up 12 seconds       22/tcp              slaver2
7698230a03fb        hadoop:latest       /bin/sh -c '/usr/sbi   21 seconds ago      Up 20 seconds       22/tcp              slaver1

[root@docker ~]# docker ps | grep hadoop | awk '{print $1}' | xargs -I{} docker inspect -f '{{.NetworkSettings.IPAddress}} {{.Config.Hostname}}' {} > /etc/dnsmasq.hosts
[root@docker ~]# service dnsmasq restart

[root@docker ~]# ssh hadoop@master
hadoop@master's password: 
[hadoop@master ~]$ ping slaver1
PING slaver1 (172.17.0.9) 56(84) bytes of data.
64 bytes from slaver1 (172.17.0.9): icmp_seq=1 ttl=64 time=1.79 ms
...
[hadoop@master ~]$ ping slaver2
PING slaver2 (172.17.0.10) 56(84) bytes of data.
64 bytes from slaver2 (172.17.0.10): icmp_seq=1 ttl=64 time=1.96 ms
...

节点互通后,后面的步骤都类似了,ssh无密钥通信,格式化namenode,启动等等。

遇到的问题

  • 一开始我把配置文件放在/root目录下,dnsmasq总是不起作用。最后放到/etc目录就可以,不知道啥子问题。
  • 配置dns启动docker容器后,如果不起作用看下/etc/resolv.conf。如果互ping不同,去掉resolv的search localhost再试下。

DNS可以正常工作的配置:

1
2
3
4
5
6
7
8
9
10
-bash-4.1# ping slaver
PING slaver (172.17.0.7) 56(84) bytes of data.
64 bytes from slaver (172.17.0.7): icmp_seq=1 ttl=64 time=0.095 ms

-bash-4.1# cat /etc/resolv.conf 
nameserver 172.17.42.1
search localdomain

-bash-4.1# cat /etc/resolv.conf 
nameserver 172.17.42.1

如果还是不行的话,关掉防火墙然后重启下docker服务: service iptables stop; service docker restart

如果要访问外网,也可以条件其他的DNS服务解析:

1
2
3
-bash-4.1# vi /etc/resolv.conf 
nameserver 172.17.42.1
nameserver 8.8.8.8

常用命令

1
2
3
~]# docker run -d --dns 172.17.42.1 --name puppet -h puppet winse/hadoop:2.6.0 /usr/sbin/sshd -D
~]# docker inspect `docker ps -a | grep centos | awk '{print $1}'` | grep IPAddress
~]# docker stop `docker ps -a | grep centos | awk '{print $1}'`

参考

–END

Comments