新聞中心
前言
DNS 這個東西,可大可小,可簡單可復(fù)雜。對于以園區(qū)網(wǎng)為主的傳統(tǒng)企業(yè)/單位而言,要考慮多出口的鏈路優(yōu)化,智能解析,私有域名的解析 ,監(jiān)控,管理等一系列問題,還是需要有一個好的設(shè)計優(yōu)化的。

創(chuàng)新互聯(lián)主營景谷網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,APP應(yīng)用開發(fā),景谷h5小程序開發(fā)搭建,景谷網(wǎng)站營銷推廣歡迎景谷等地區(qū)企業(yè)咨詢
我們前陣子剛完成了 DNS 架構(gòu)的升級,在這里整理一下做個分享。
需求分析
在討論 DNS 的架構(gòu)之前我們先分析一下我們的需求:
多鏈路優(yōu)化
通常一個園區(qū)網(wǎng)都會有多個出口。我們需要通過路由策略來決定用戶的請求最終落入那個出口上。在網(wǎng)絡(luò)層上,BGP 自然不必多說了,靜態(tài)路由的話,我們也可以設(shè)法去弄到各個運營商的地址表(萬能的淘寶)然后寫入路由,從而讓用戶的請求落入最合理的出口鏈路上。
“讓用戶的請求落入最合理的出口鏈路上”,靠路由表就夠了嗎?非也,因為還有 CDN。很自然的,由于有 CDN ,大部分網(wǎng)站的所提供的解析,都會根據(jù)用戶的 DNS 請求來源,而智能解析到對應(yīng)運營商區(qū)域內(nèi)的 CDN 上。也就是說,實際上我們 DNS 遞歸時的網(wǎng)絡(luò)路由策略,基本決定了用戶訪問網(wǎng)站的實際路由。例如我們的 DNS 通過電信的鏈路去遞歸解析,那么用戶解析到的網(wǎng)站地址多半也會落在該網(wǎng)站的電信 CDN 上,因此最終的請求也將被路由至電信鏈路上。
現(xiàn)在的問題在于,不同網(wǎng)站,在不同鏈路的 CDN 上的訪問體驗是不一致的!舉個例子,QQ 郵箱(mail.qq.com),如果他落在教科網(wǎng)的 CDN 上,附件經(jīng)常就傳不上去。12306 在電信的 CDN 上訪問很快,而在教科網(wǎng)的 CDN 上就經(jīng)??ǖ娘w起。。。說到底這其實就是不同鏈路之間的質(zhì)量差異,畢竟價格也要差好多呢。
把默認路由全都給質(zhì)量最好的鏈路就行了唄? 理想很豐滿,但是小錢錢很骨干吶!實際上我們擁有的鏈路帶寬大小通常也與鏈路質(zhì)量成反比。因此我們需要在用戶的訪問體驗和鏈路的帶寬利用率上尋找一個平衡。
智能解析
如同 CDN 一般。我們自己也有多條出口,因此我們自己的服務(wù)在提供 DNS 解析的時候,也得根據(jù)用戶解析的請求地址,來進行智能的解析,來提高我們網(wǎng)站的外部訪問速率。
私有域名
在我們的數(shù)據(jù)中心里,我們會需要一些私有的域名分配給服務(wù)器。這樣會方便管理,也可以利用 DNS 做一些服務(wù)注冊的工作。所以我們要有私有的域名,但是需要限制在數(shù)據(jù)中心之內(nèi),避免園區(qū)內(nèi)的普通用戶能夠直接解析到。
API
剛才我們提到了服務(wù)注冊。實際上無論是從運維自動化來考慮還是流程自動化來考慮,我們都需要 DNS 對應(yīng)的 API 接口,能夠讓我們自動化的注冊,修改,刪除域名。
服務(wù)狀態(tài)監(jiān)控
如同我們所有的服務(wù)一樣,DNS 我們也需要有對應(yīng)的服務(wù)監(jiān)控。這需要我們的 DNS 本身能夠暴露出相應(yīng)的狀態(tài)接口,提供服務(wù)狀態(tài)的查詢方法。我們通過腳本等去采集狀態(tài)信息推送給監(jiān)控系統(tǒng)(Open-Falcon)。
管理
我們需要一個方便易用的前端來做 DNS 的域名管理。需要能夠進行權(quán)限的控制,給不同的域分配不同的管理員。能夠記錄每次變更的操作記錄。徹底結(jié)束 SSH 到服務(wù)器上改 ZONE 文件的歷史。 同時后端數(shù)據(jù)最好落到數(shù)據(jù)庫里,這樣做一些查詢的時候會方便很多。比如我要查所有解析的 IP 落在外部而非校內(nèi) IP 的域名,數(shù)據(jù)庫里只要一條 SQL 就搞定了,而 ZONE 文件的話就得寫腳本了。
傳統(tǒng)架構(gòu)
大家可能看過前陣子《GitHub 的 DNS 基礎(chǔ)設(shè)施》 這篇文章。這里面 GitHub 說他們以前的 DNS 架構(gòu)就是兩臺服務(wù)器,包含了緩存,遞歸和權(quán)威服務(wù)。文章里沒說用的是啥軟件,不過 8 成是 Bind 吧。 我們學(xué)校之前的 DNS 架構(gòu)也是如此,兩臺 Bind 做完所有的事情。我所了解的許多學(xué)校 DNS 架構(gòu)亦是如此。很多地方的 DNS 架構(gòu)都是這樣子,簡單,穩(wěn)定。
然而對應(yīng)我們剛才的需求 :
- 多鏈路優(yōu)化——搞不了
- 智能解析——這個可以用 bind views 來做
- 私有域名——不好控制園區(qū)普通用戶的訪問
- API——木有
- 服務(wù)狀態(tài)監(jiān)控——只能通過分析日志,有限
- 管理——Bind 都有對應(yīng)的第三方解決辦法,但是都相對比較麻煩
新架構(gòu)
技術(shù)選型
GitHub 在《GitHub 的 DNS 基礎(chǔ)設(shè)施》里面提到,他們使用了 Unbound 作為緩存,NSD 作為邊緣節(jié)點,PowerDNS 作為權(quán)威服務(wù)。
我們則選擇了使用 PowerDNS 全家。即 PowerDNS-Authoritative 作為權(quán)威服務(wù),PowerDNS-Recursor 作為遞歸服務(wù),dnsdist 作為邊緣節(jié)點來提供智能解析。 并且使用 PowerDNS-Admin 進行權(quán)威服務(wù)的管理。
架構(gòu)
先看總體架構(gòu):
遞歸服務(wù)
我們將兩臺主遞歸服務(wù)器默認通過鏈路質(zhì)量稍差一點,但帶寬比較充裕的 ISP 進行遞歸。同時,在鏈路質(zhì)量較好的 ISP 上再放兩臺遞歸服務(wù)器,將部分域名 Forward 給他去遞歸,從而在基本不降低用戶訪問體驗的情況下,充分利用兩條鏈路的帶寬。
當然我們會把自身的域名直接 Forward 給我們的權(quán)威服務(wù),避免了無謂的外部遞歸。
權(quán)威服務(wù)
我們根據(jù)兩條不同的鏈路做了兩套權(quán)威服務(wù),一套解析 ISP-1 的地址,另一臺則解析為 ISP-2 的地址。然后在這兩套權(quán)威服務(wù)之前,放了兩臺 dnsdist 作為邊緣節(jié)點。
dnsdist 根據(jù)請求的 IP 地址,將請求轉(zhuǎn)發(fā)給對應(yīng)的后端權(quán)威服務(wù),實現(xiàn)智能解析。
私有域名
在數(shù)據(jù)中心內(nèi),我們需要一些私有的內(nèi)部域名來做點服務(wù)注冊之類的活。這些域名我們希望只能被我們數(shù)據(jù)中心內(nèi)的服務(wù)器們請求到,普通的園區(qū)用戶無法請求。 類似的,我們在私有的權(quán)威服務(wù)之前,使用 dnsdist 進行 ACL 過濾。這兩臺 dnsdist 就作為數(shù)據(jù)中心的 DNS 服務(wù)提供給服務(wù)器使用。僅匹配數(shù)據(jù)中心網(wǎng)段的服務(wù)器允許解析,并轉(zhuǎn)發(fā)私有的域名請求給權(quán)威服務(wù)器,其他請求則轉(zhuǎn)發(fā)給園區(qū)的主遞歸服務(wù)。普通用戶的請求則無法匹配 ACL 將被拒絕。
API
Powerdns 提供了簡單易用的 API 調(diào)用。像這樣:
# curl -v -X PATCH -H 'X-API-Key: d37757d0adfa0d3dc26a11119134f92' --data '{"rrsets":[{"name":"testtesttest.ecnu.edu.cn.","type":"A","ttl":3600,"changetype":"REPLACE","records":[{"content":"192.168.0.1","disabled":false,"set-ptr":false}]}]}' "http://127.0.0.1:8081/api/v1/servers/localhost/zones/ecnu.edu.cn"
* About to connect() to 127.0.0.1 port 8081 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8081 (#0)
> PATCH /api/v1/servers/localhost/zones/ecnu.edu.cn HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8081
> Accept: */*
> X-API-Key: ecnu3081
> Content-Length: 165
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 165 out of 165 bytes
< HTTP/1.1 204 No Content
< Access-Control-Allow-Origin: *
< Connection: close
< Content-Length: 0
< Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
< Server: PowerDNS/4.1.0-rc1
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Permitted-Cross-Domain-Policies: none
< X-Xss-Protection: 1; mode=block
<
* Closing connection 0
所以我們可以很容易的將他和流程系統(tǒng),運維系統(tǒng)進行對接。實現(xiàn)域名注冊的自動化。
監(jiān)控
與 Bind 最大的區(qū)別就在監(jiān)控上了。Powerdns 內(nèi)置了大量的性能指標項,我們可以非常容易的去采集這些指標,然后推送給我們的監(jiān)控系統(tǒng)。詳細的指標可以參看官網(wǎng)說明: recursor 、authoritative。
我們使用 open-falcon 作為監(jiān)控系統(tǒng),效果如下:
實際上我們可以看出來,對于規(guī)模不是很大的 DNS 而言,是不需要 DNS 的負載均衡的。因為在達到單機的性能瓶頸之前,cache 的命中率才是決定請求平均延遲的主要因素。我們做雙機的唯一目的只是冗余而已。
Powerdns 的單機性能,根據(jù) 官網(wǎng)介紹,大概能 HOLD 住億級的請求量,所以通常不會有什么壓力的~
It is known to power the resolving needs of over 150 million internet connections.
管理
Powerdns 由于提供了豐富的 API 接口,因此社區(qū)內(nèi)有很多適配的 WEB 前端可以選擇。
我們選擇了 PowerDNS-Admin 作為管理前端。
它可以實現(xiàn) DNS 的分級權(quán)限管理,同時記錄每次變更的記錄。
完整的變更記錄在 mysql 內(nèi):
MariaDB [powerdnsadmin]> select * from history order by created_on desc limit 1 \G;
這樣如果發(fā)生手抖事件誤操作了,也抵賴不了啦,該背鍋背鍋。
數(shù)據(jù)存儲
Powerdns 支持多種數(shù)據(jù)后端,也包含 BIND 的 Zone 文件模式。
| Name | Native | Master | Slave | Super slave | Auto serial | DNSSEC | Launch |
|---|---|---|---|---|---|---|---|
| BIND | Yes | Yes | Yes | Experimental | No | Yes | bind |
| Generic Mysql | Yes | Yes | Yes | Yes | Yes | Yes | gmysql |
| Generic ODBC | Yes | Yes | Yes | Yes | Yes | Yes | godbc |
| Generic Oracle | Yes | Yes | Yes | Yes | Yes | Yes | goracle |
| Generic Postgresql | Yes | Yes | Yes | Yes | Yes | Yes | gpgsql |
| GeoIP | Yes | No | No | No | No | Yes | geoip |
| LDAP | Yes | No | No | No | No | No | ldap |
| MyDNS | Yes | No | No | No | No | No | mydns |
| OpenDBX | Yes | Yes | Yes | Yes | No | No | opendbx |
| Oracle | Yes | Yes | Yes | Yes | Yes | Yes | oracle |
| Pipe | Yes | No | No | No | No | Partial | pipe |
| Random | Yes | No | No | No | No | Partial | random |
| Remote | Yes | Yes* | Yes* | Yes* | Yes* | Yes* | remote |
| TinyDNS | Yes | Yes | No | No | No | Parti | pipe |
我們?yōu)榱藢淼墓芾矸奖?,選擇將數(shù)據(jù)遷移到 MySQL 中作為 Backend。Powerdns 自帶遷移工具 zone2sql,可以很方便的把 zone 文件轉(zhuǎn)換成 sql 語句然后導(dǎo)入 mysql 中:
# zone2sql --help
syntax:
--filter-duplicate-soa | --filter-duplicate-soa=yes | --filter-duplicate-soa=no
Filter second SOA in zone
--gmysql | --gmysql=yes | --gmysql=no
Output in format suitable for default gmysqlbackend
--goracle | --goracle=yes | --goracle=no
Output in format suitable for the goraclebackend
--gpgsql | --gpgsql=yes | --gpgsql=no
Output in format suitable for default gpgsqlbackend
--gsqlite | --gsqlite=yes | --gsqlite=no
Output in format suitable for default gsqlitebackend
--help
Provide a helpful message
--json-comments | --json-comments=yes | --json-comments=no
Parse json={} field for disabled & comments
--mydns | --mydns=yes | --mydns=no
Output in format suitable for default mydnsbackend
--named-conf=...
Bind 8/9 named.conf to parse
--on-error-resume-next | --on-error-resume-next=yes | --on-error-resume-next=no
Continue after errors
--oracle | --oracle=yes | --oracle=no
Output in format suitable for the oraclebackend
--slave | --slave=yes | --slave=no
Keep BIND slaves as slaves. Only works with named-conf.
--soa-expire-default=...
Do not change
--soa-minimum-ttl=...
Do not change
--soa-refresh-default=...
Do not change
--soa-retry-default=...
Do not change
--transactions | --transactions=yes | --transactions=no
If target SQL supports it, use transactions
--verbose | --verbose=yes | --verbose=no
Verbose comments on operation
--version
Print the version
--zone=...
Zonefile to parse
--zone-name=...
Specify an $ORIGIN in case it is not present
主從同步
傳統(tǒng)的 DNS 主從同步是通過 AXFR 來同步。在 Powerdns 中,我們將主/從的 權(quán)威 DNS 分別設(shè)置為 Master 和 Slave 就可以實現(xiàn)。
然而既然我們的后端已經(jīng)是 MySQL 了~~所以完全可以用 MySQL 同步來做嘛。因此我們把 Powerdns 的類型設(shè)置為 Native,并且配置了兩臺權(quán)威服務(wù)器的 MySQL 進行主從同步。MySQL 的主從同步很可靠,同時 binlog 也能夠方便的進行回退。
復(fù)雜查詢
由于我們把數(shù)據(jù)放到了 MySQL 里,因此現(xiàn)在做一些復(fù)雜的記錄查詢變的非常容易了。例如我們需要查一下某個網(wǎng)段內(nèi)的所有 A 記錄解析。換以前可能得對著 Zone 文本寫腳本了。現(xiàn)在只要一條 SQL 語句就搞定了
MariaDB [powerdns]> select * from records where type="A" and content>="192.168.80.1" and content<="192.168.80.255";
數(shù)據(jù)備份
同樣,由于現(xiàn)在數(shù)據(jù)在 MySQL 內(nèi),數(shù)據(jù)備份也變得非常容易了。我們可以使用 MySQL 的 binlog 機制,很容易的實現(xiàn)數(shù)據(jù)的增量備份。再輔以每天一次全量的備份,數(shù)據(jù)的備份機制也比過去來的更完善了
總結(jié)
新的架構(gòu)上線之后,通過管理權(quán)限的下放和自動化的 API 調(diào)用,管理負擔降低了,管理透明度提升了。整個結(jié)構(gòu)清晰,易于維護。通過多鏈路的優(yōu)化,我們在基本不降低用戶的網(wǎng)絡(luò)訪問質(zhì)量的同時,盡可能的利用了每一條 ISP 鏈路。
解放我們的雙手,去做更多有意義的事情。
參考文檔
- PowerDNS-Authoritative
- PowerDNS-Recursor dnsdist
- PowerDNS-Admin
- GitHub 的 DNS 基礎(chǔ)設(shè)施
新聞標題:園區(qū)網(wǎng)為主的DNS架構(gòu)設(shè)計
當前URL:http://www.dlmjj.cn/article/dpsdecg.html


咨詢
建站咨詢
