嗶哩嗶哩內網 DNS 實踐
本期作者
衛智雄
基礎架構部高級運維工程師
01 引言
域名系統 (DNS) 就像是互聯網的地址簿,通過將一個或多個複雜難記的 IP 地址映射到容易識別和記憶的域名上,便於人們通過簡單的域名比如 bilibili.com 訪問互聯網資源。在此基礎上,DNS 還提供了負載均衡等重要服務。是極爲關鍵的互聯網基礎設施。
以 DNS 爲基礎的內網 DNS 服務則提供了一些額外的好處:
- 私有域名
-
方便內網服務互聯互通
-
外界無法感知和探測到,滿足了安全性和隱私方面的需求
- DNS 劫持
-
攔截特定公網域名到內網 ip,降低公網帶寬和訪問延遲。如某核心服務 A 早期只有公網域名,隨着業務發展,內部非常多其他服務調用 A 服務,此時內部調用產生的公網帶寬成本已非常高。而推動其他服務更換內網域名成本不低,DNS 劫持則能輕鬆幫我們解決問題。
-
攔截惡意公網域名,降低安全隱患
- 特定業務邏輯支持
-
內部調用 API,方便管理與運維
-
主機名管理和私有 ip 反向解析支持
-
支持特定域轉發
- 極低的解析延遲以及極高的吞吐量
因此本文將分享 B 站內網 DNS 服務建設相關實踐。
02 架構演進
考慮到基礎設施的穩定性,我們選擇了知名度最高、普及範圍最廣的 DNS 實現 BIND9 作爲 DNS Server。
在介紹架構之前,我們簡單瞭解一下內網 DNS Server 中最常用的兩種角色:
- 權威 Name Server
權威 Name Server 是實際持有並負責特定域資源記錄的服務器,通常是解析器查找 IP 地址過程中的最後一步,擁有這些域的最終解釋權。
權威 Name Server 在軟件層的實現又可以分爲主權威和從權威。對 DNS 查詢來說主從權威完成是對等的,但是它在軟件架構上提供了必要的故障災備和橫向擴容能力。
- 解析器(Caching Name Servers)
解析器通常是 DNS 查詢中的第一站,處理用戶的遞歸查詢,並提供完整的答案。當收到請求時,解析器向 DNS 層次結構發出一個或多個迭代查詢。在獲得一個完整的答案(或一個錯誤)後,解析器將答案傳遞給用戶,並將記錄放入其緩存。用戶對同一查詢的後續請求將從解析器的緩存中得到回答,直到緩存記錄的 TTL 過期,那時它將從緩存中被刷新;請求相同信息的下一個用戶查詢將導致對 DNS 層次結構的一系列新的查詢。
解析器在不同的使用場景下常被稱爲各種令人困惑的名字,如緩存名稱服務器、遞歸名稱服務器、轉發解析器、區域解析器和全面服務解析器等。
典型域名解析過程圖:
1. 第一代 DNS 架構
B 站內網 DNS 服務早期第一代架構相對比較簡單,核心關注高可用和穩定性,採用了主從模式,保障每個核心 IDC 有獨立的從權威集羣,通過 VIP 提供負載均衡,並通過 VIP 健康檢查機制自動踢掉故障節點。同時各 IDC 機房內網互通,互爲備份。
隨着業務的發展,在高 QPS 場景中,主從權威 Zone 配置同步時存在解析時長突增,響應時延不穩定的問題。其次從權威的可擴展性也相對較弱。因此我們衍生出第二代 DNS 架構。
2. 第二代 DNS 架構
第二代 DNS 架構主要引入了多級緩存。
首先是引入了 Caching Name Servers,可擴展性得到了非常大的提升。同時也避免了權威節點配置 / Zone 變更帶來的抖動。
其次是針對大數據、AI 等 QPS 極高的業務,引入 NSCD 作爲 Client 緩存服務。既降低了響應延遲也提高了整體服務吞吐。
在此基礎上,第二代架構還對 BIND9 Server 進行了升級和優化。BIND9 雖然支持多線程,但是在我們早期使用的 9.11 版本中,最高只能利用 400% 的 CPU,單實例 QPS 峯值在 10 萬左右,爲了提高服務器利用率,我們進行了單機多實例部署,但這也給運維帶來了複雜度。在新的版本中,因爲支持 reuseport、日誌寫緩存等新特性,對性能有非常大提升,單實例可以充分利用多核 CPU,在生產環境壓測中單機 QPS 超過 150 萬,因此我們也在線上進行了升級。
03 DNS 服務監控建設
DNS 服務監控告警主要分爲三個層面:
-
主機層
-
業務層
-
Client 端
1. 主機層
主機層通常都會有 CPU、內存、網絡、磁盤等資源的使用率、飽和度、錯誤監控告警。這裏主要強調兩點容易忽略或者對 DNS 服務比較重要的監控告警。
-
單核 CPU / 單網卡的使用率告警
現代 IT 服務架構中,從交換機到服務器網卡到服務器 CPU,各個路徑幾乎都是多 Pipeline 負載均衡,因爲錯誤配置或使用不當,可能會出現單核 CPU / 單網卡負載不均衡,引發服務異常的情況。
-
網絡層面
-
網卡收發包異常告警
-
TCP、UDP errors 告警
-
2. 業務層
-
BIND 內部指標採集
BIND 通過 statistics-channels 暴露了豐富的內部監控指標。早期我們通過 bind_exporter 採集,但是遇到兩個比較明顯的問題:一是 bind_exporter 默認會採集 /xml/v3/tasks 數據,這個路徑下的數據即無用,又會嚴重影響解析時延;二是部分比較重要的指標 bind_exporter 沒有采集。因此我們重新開發了採集程序。
-
Zone 記錄值變化率 / 變化量告警
監測每個 Zone 的記錄值變化量,防止內部 API 等異常變更導致大量記錄值被刪除。
-
BIND 錯誤日誌監控告警
錯誤日誌能更詳細的反應 BIND 內部的異常情況,幫助我們及時排障。
3. Client 端探測告警
服務內部的監控並不總能真實反映用戶到服務端的訪問質量,因此我們在各個機房部署多個探針,模擬真實用戶請求,多 Zone 多域名高頻率監測每個 Server 的可用性、內容正確性和響應時延。Client 探針多次幫助我們及時發現網絡設備小概率 BUG、網絡擁塞等業務方還感知不到的異常。
同時增加 Client 到 Server 的網絡 Ping 時延和丟包率監控,在異常時做輔助判斷。
這裏補充一點,公網公共 DNS 也並不是穩定的,需要對其進行監測和告警。目前我們的實踐經驗是阿里雲公共 DNS 穩定性相對更好一些。
04 踩坑經驗
一個複雜系統總會有很多細節是我們在使用初期沒能瞭解或掌握的,因此這裏分享一些我們踩過的坑幫助你走好自己的路。同時推薦閱讀**《常見 DNS 操作和配置錯誤》[3]**。
1. 保障 UDP 和 TCP 端口用戶皆可訪問
通常 DNS 默認使用 UDP 傳輸,同時在 rfc 中約定 DNS 使用 UDP 傳輸時,包體需小於等於 512 字節 (不包括 IP 或 UDP 包頭)。512 字節的限制在大部分場景都能滿足需求,但當記錄值過長超過限制時,Server 端需置 TC 位爲 1,告知 Client 響應被截斷。Client 在收到 TC 位爲 1 的響應時,需用 TCP 重新發起請求。這就要求 TCP 端口也必須可達。
根據以上信息,也額外提醒大家,在選域名時應儘量短小,記錄值儘量簡單,以便提高解析速度。
2. Zone 配置變更後必須增大序列號
主從權威的同步過程如下:
① 主節點 Zone 配置變更,向從節點發送 NOTIFY 通知
② 從節點返回 NOTIFY Respons,並向主節點發起 SOA 查詢
③ 主節點返回 SOA Respons
④ 從節點對比 SOA Respons 中的序列號是否比自身序列號大,僅當 SOA Respons 序列號大於自身序列號時才發起 Zone transfer request,並利用 TCP 53 端口進行數據傳輸
因此 Zone 配置變更後必須增大序列號,否則會導致主從節點數據不一致。
3. 慎用 rndc flush 刷新全量緩存
線上難免會遇到刷新緩存的需求,如果直接用 rndc flush 刷新全量緩存,在有客戶端緩存如 NSCD 的情況下,在每一次客戶端緩存過期的時間都可能會產生極高的 QPS 。
因此,儘量使用 flushname 或 flushtree 來刷新指定域名或 Zone。
4. 慎用泛域名解析
泛域名解析是指利用通配符 * 將所有的子域名都指向相同的解析記錄,實現靈活配置。然而當某個子域名需要獨立配置時,容易忽略泛域名的配置,引發故障。
舉個例子 (以真實故障爲藍本),方便大家理解:
① 業務上線初期爲了方便配置使用泛域名解析: *.example.com CNAME xxxcdn.com
② 發展一段時間後 a.example.com 有了新需求,需要加個 TXT 做驗證
③ 運維同學添加解析 a.example.com TXT xxx
④ 此時因爲 a.example.com 只有 TXT 記錄,沒有 A/AAAA 或 CNAME,直接導致 a 站點無法訪問
05 結語
基礎設施服務具有槓桿作用,良好的基礎設施服務可以幫助業務提高效率,降低開發運維成本。作爲基礎設施的一部分內網 DNS 亦是如此。我們始終以業務需求爲基礎,不斷演進與迭代,致力於提供穩定、可靠、易用、好用的服務。
參考文獻:
[1] BIND 9 管理員參考手冊(https://bind9.readthedocs.io/en/latest/index.html)
[2] 域名——實施和規範(https://www.ietf.org/rfc/rfc1035.txt)
[3] 常見 DNS 操作和配置錯誤(https://www.ietf.org/rfc/rfc1912.txt)
[4] ISC 知識庫中關於 BIND 及 DNS 的一系列文章(https://kb.isc.org/docs/monitoring-recommendations-for-bind-9)
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/iAPjhBlbusFLlFVUN4OLaA