kube-dns在kubernetes中负责域名解析,其中真正在提供dns服务的是dnsmasq容器。我们为了能让kubernetes上的容器也能根据主机名来访问宿主机,将宿主机的/etc/hosts文件以configmap volume的形式挂载到了dnsmasq容器中,让dnsmasq读取改hosts文件,从而提供宿主机的域名解析。

[root@m1 ~]# kubectl exec -it kube-dns-75qmb sh -n kube-system -c dnsmasq
/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:01 /usr/sbin/dnsmasq --keep-in-foreground --cache-size=1000 --no-resolv --addn-hosts=/dns/hosts --server=127.0.0.1#10053
    6 root       0:00 sh
   10 root       0:00 ps aux

但在k8s集群扩容时,需要将新增node也更新到dnsmasq容器的的hosts。configmap可以通过kubectl patch来更新,但dnsmasq怎么更新呢?

dnsmasq并不会watch这个file的更新,但可以让dnsmasq重启以重新加载hosts文件。

直接想到的做法是,由于kube-dns是一个deployment,可以走一波rolling-update,这样kube-dns的升级是平稳的,能保证总有dns服务可用;但问题是这里只是想重启dnsmasq容器,并没有配置的更新,rolling-update不合适。

那走kubectl scale?可以先kubectl scale --replicas=0 deploymen/kube-dns -n kube-system先缩为0,然后在kubectl scale --replicas=3 deploymen/kube-dns -n kube-system扩为3,这样可以起到dnsmasq重启重新加载hosts文件的目的;但问题是这样集群会有一段时间内kube-dns服务不可用。

有没有更好的做法呢?

仔细读一下dnsmasq的man page,会发现其实是有的。dnsmasq虽然不能根据hosts自动更新cache,但可以通过向dnsmasq进程发SIGHUP信号,通知dnsmasq进程清除缓存并重新加载hosts文件。

“When it receives a SIGHUP, dnsmasq clears its cache and then re-loads /etc/hosts and /etc/ethers and any file given by –dhcp-hostsfile, –dhcp-optsfile or –addn-hosts. The dhcp lease change script is called for all existing DHCP leases. If –no-poll is set SIGHUP also re-reads /etc/resolv.conf. SIGHUP does NOT re-read the configuration file.”

所以可以在扩容的时候,找到kube-dns的所有dnsmasq容器,依次、温柔的向它们发送SIGHUP信号(kill -1 {pid})。由于dnsmasq是容器的第一个进程,所以容器里dnsmasq 的pid为1,这样在外面kubectl exec的时候会比较方便。

注意,dnsmasq虽然不支持针对某一个hosts自动更新缓存,但可以针对某一个目录自动更新缓存(WTF)。

       --hostsdir=<path>
              Read  all  the hosts files contained in the directory. New or changed files are read automatically.

但这在我这里行不通。hostdir是要跟踪目录下文件的变化,但由于我的hosts文件其实是一个configmap volume的链接的链接,当configmap更新的时候,在dnsmasq容器里更新的是链接(..data)和具体的文件(..9989_12_09_19_35_45.006981446),而hosts链接并不变化,dnsmasq也就无从得知是否有变化了。

/ # ls -l /dns/ -a
total 12
drwxrwxrwx    3 root     root          4096 Sep 12 11:35 .
drwxr-xr-x   19 root     root          4096 Sep 12 11:35 ..
drwxr-xr-x    2 root     root          4096 Sep 12 11:35 ..9989_12_09_19_35_45.006981446
lrwxrwxrwx    1 root     root            31 Sep 12 11:35 ..data -> ..9989_12_09_19_35_45.006981446
lrwxrwxrwx    1 root     root            12 Sep 12 11:35 hosts -> ..data/hosts

通过向dnsmasq容器发送SIGHUP信号,可以达到更新缓存的目的。