天天看點

容器化dns服務容器化dns服務

之前将一個小應用使用docker compose部署之後,遇到一個問題,修改域名解析的ip。之前在虛拟機上可以直接修改hosts檔案,

在docker容器中修改就比較麻煩,修改主機hosts檔案也沒有效果。

為了解決這個問題,引入了dnsmasq作為dns伺服器。由于主機上本身已經有docker環境,是以也打算把dnsmasq放到容器中去運作。

首先是選擇容器,在docker hub上下載下傳量最多的是 andyshinn/dnsmasq 鏡像。這個鏡像的最大優勢就是簡單,整個鏡像隻有6m多。

對于無法通路外網的docker主機來說,部署比較友善。當然,這個鏡像最大的劣勢也是簡單,沒有提供配置檔案,也無法可視化配置,使用時需要對dnsmasq有一定的了解。本文後面會介紹到剛開始使用遇到的不友善的地方。

由于真正部署這個鏡像的伺服器無法通路外網,是以不能直接拉去docker鏡像,暫時在一台可以通路外網的機器上拉取,然後導出,最後在機器上重新加載的方式來進行安裝。也就是

<code>docker pull andyshinn/dnsmasq</code>

<code>docker save andyshinn/dnsmasq &gt; dnsmasq.tar</code>

<code>scp dnsmasq.tar admin@xxx:.</code>

<code>docker load &lt; dnsmasq.tar</code>

這樣鏡像就算是安裝完成了。

啟動鏡像前,參考了該鏡像文檔中的啟動指令:

同時,看了下這個鏡像的dockerfile:

可以發現,這個鏡像真是簡單至極。預設就是運作了dnsmasq -k,即強制讓dnsmasq運作在前端。然後dnsmasq沒有任何特殊的配置,都需要啟動過的時候手工指定。

而示例中的啟動指令,有這幾個含義:

将容器的53端口(tcp和udp)映射到主機上,這是dns的标準端口

增加net_admin參數,使得容器中的程序可以修改網絡配置

給dnsmasq傳遞參數,針對.consul字尾的域名,使用10.17.0.2這個上遊dns伺服器進行解析

這樣的啟動方式,當然是無法滿足需求的。dnsmasq指令的參數,可以在這個文檔中進行查詢。如果僅僅是解析一個域名,可以通過–address參數指定,域名和ip格式和上面類似:

這樣容器啟動之後,就可以解析api.test.com這個域名到127.0.0.1。

啟動容器還是比較友善,然後就是将這個dns服務提供給其他docker容器使用。docker在啟動參數中支援通過–dns指定dns伺服器位址(指定後,會修改啟動容器的/etc/resolv.conf檔案)。如果在docker-compose中使用,可以在yml檔案中增加dns項。

這樣,容器啟動之後,就可以使用自己搭建的dns服務了。然而,并沒有~

首先遇到的問題,是容器中的服務仍然無法解析域名。使用docker exec指令進入容器,ping了域名還是提示無法解析。排查dnsmasq的日志沒有輸出。

由于dnsmasq解析日志不太好排查,查詢了手冊之後發現,可以通過–log-facility參數指定日志輸出,将容器啟動參數改成:

這樣可以将dnsmasq的日志輸出到标準錯誤,也就能夠在目前指令行中檢視到。(如果在docker run的時候使用了-d參數放到了背景執行,可以直接通過docker logs來檢視輸出)

再次到應用容器中ping域名,會發現dnsmasq實際上已經完成了域名解析,但是域名解析的來源ip都是docker0裝置的ip。如果将應用容器的dns伺服器位址,修改成dnsmasq容器的内網位址,則解析正常。是以判斷這個解析錯誤,可能和兩個容器都運作在nat模式中有關。

将dns容器改成host模式:

在将應用容器的dns伺服器位址修改成主機的ip,可以發現能夠正常解析域名。

按照上面方式啟動dns容器,可以正常工作。但是如果要增加解析記錄,需要重新啟動這個容器。文檔裡面有提到dnsmasq可以通過向程序發送sighup信号,重新加載檔案:

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-hostsdir, –dhcp-optsfile, –dhcp-optsdir, –addn-hosts or –hostsdir. 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.

也就是說,如果通過–addn-hosts或者–hostsdir參數指定的檔案(夾),可以通過信号來觸發dnsmasq重新加載。為了友善區分,最終采用了後者,既–hostsdir指定hosts檔案夾。

首先,在主機上建立一個檔案夾和一個檔案,寫入需要解析的域名:

然後啟動容器的時候,設定挂載卷,将這個目錄共享給容器,同時指定這個目錄未hostsdir:

這樣,如果需要新增解析記錄,需要兩步:

在主機hosts目錄中,新增一條記錄:<code>echo 'b.test.com' &gt;&gt; hosts/common</code>

向dns容器發送信号,使其重新加載檔案:<code>docker kill -s hup 2beb1d9f3554</code>

這樣雖然還需要手工操作,但是無須再重新運作dns容器。

轉載自:https://coolex.info/blog/511.html