嗶哩嗶哩內網 DNS 實踐

本期作者

衛智雄

基礎架構部高級運維工程師

01 引言

域名系統 (DNS) 就像是互聯網的地址簿,通過將一個或多個複雜難記的 IP 地址映射到容易識別和記憶的域名上,便於人們通過簡單的域名比如 bilibili.com 訪問互聯網資源。在此基礎上,DNS 還提供了負載均衡等重要服務。是極爲關鍵的互聯網基礎設施。

以 DNS 爲基礎的內網 DNS 服務則提供了一些額外的好處:

  1. 私有域名
  1. DNS 劫持
  1. 特定業務邏輯支持
  1. 極低的解析延遲以及極高的吞吐量

因此本文將分享 B 站內網 DNS 服務建設相關實踐。

02 架構演進

考慮到基礎設施的穩定性,我們選擇了知名度最高、普及範圍最廣的 DNS 實現 BIND9 作爲 DNS Server。

在介紹架構之前,我們簡單瞭解一下內網 DNS Server 中最常用的兩種角色:

權威 Name Server 是實際持有並負責特定域資源記錄的服務器,通常是解析器查找 IP 地址過程中的最後一步,擁有這些域的最終解釋權。

權威 Name Server 在軟件層的實現又可以分爲主權威和從權威。對 DNS 查詢來說主從權威完成是對等的,但是它在軟件架構上提供了必要的故障災備和橫向擴容能力。

解析器通常是 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 服務監控告警主要分爲三個層面:

  1. 主機層

  2. 業務層

  3. Client 端

1. 主機層

主機層通常都會有 CPU、內存、網絡、磁盤等資源的使用率、飽和度、錯誤監控告警。這裏主要強調兩點容易忽略或者對 DNS 服務比較重要的監控告警。

2. 業務層

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