Hlavní navigace

BIND 9.20: vylepšený výkon resolveru a nové databázové a aplikační jádro

4. 9. 2024
Doba čtení: 8 minut

Sdílet

 Autor: ISC
Nová verze DNS serveru BIND 9.20.0 přináší významná vylepšení po dvou letech vývoje. Klíčové novinky zahrnují nové aplikační a databázové jádro, optimalizovanou podporu DNSSEC a vylepšenou kompresi DNS jmen.

Po dvou letech vývoje vyšla nová verze DNS serveru BIND 9.20.0, která zahajuje novou stabilní řadu 9.20, která bude mít jako všechny sudé řady podporu následující čtyři roky. Lepší představu vám dá následující tabulka:

Co se dozvíte v článku
  1. Směr vývoje
  2. Novinky
  3. Výkon resolveru
  4. Pár slov na závěr
24 Q2 24 Q3 24 Q4 25 Q1 25 Q2 25 Q3 25 Q4 26 Q1 26 Q2 26 Q3 26 Q4 27 Q1 27 Q2 27 Q3 27 Q4 28 Q1 28 Q2
BIND 9.16 Stable EOL
BIND 9.18 Stable extended support ESV (security only) EOL
BIND 9.20 Stable stable extended support ESV (security only)
BIND 9.21 Development development
BIND 9.22 Stable stable extended support
BIND 9.23 Development development

Směr vývoje

První verze BIND 9 vyšla již v roce 2000 a původní kód byl psán pro jiná paradigmata – AMD v té době vydalo Athlon XP a Intel přišel s procesorem Pentium IV. V té době se také ještě používaly komerční Unixy a Linux nabíral dech s jádrem 2.2.0. Je tedy pochopitelné, že některá rozhodnutí, které byla učiněna v té době ohledně designu BIND 9, již dnes nejsou platná a je potřeba přizpůsobit kód moderním paradigmatům (vícejádrové procesory, NUMA architektura, atd.). Našim dlouhodobým cílem vývoje tedy není jen přidávání nových vlastností a opravy bezpečnostních chyb, ale také celkový refaktoring kódu aplikace tak, aby dobře škáloval, byl přizpůsobený moderním architekturám CPU, a také se do budoucna dobře udržoval.

Aktuální střednědobý plán je změnit architekturu BIND 9 tak, aby lépe škáloval na procesorech, které mají mnoho jader (16+), což kromě odstraňování současných pomalých mechanismů synchronizace dat zahrnuje také změnu v celkovém designu – k synchronizaci dat musí docházet pouze v případě, že je to bezpodmínečně nutné. Zájemce o tuto problematiku bych odkázal na skvělou knihu Is Parallel Programming Hard, And, If So, What Can You Do About It?.

Novinky

Nové aplikační jádro

Jádro celé aplikace zodpovědné za zpracovávání jednotlivých úloh bylo kompletně přepsáno pomocí asynchronního mechanismu poskytovaného knihovnou libuv. Verze BIND 9.16 uvedla novou síťovou vrstvu používající právě knihovnu libuv, ale tato síťová vrstva doposud používala pro běh hlavní aplikace stávající aplikační jádro a asynchronní zpracování síťových úloh běželo navíc v samostatných vláknech. Nyní ve verzi 9.20 byl přechod na libuv dokončen a asynchronní smyčky poskytované libuv jsou nyní základním stavebním kamenem celé aplikace. Tato změna zjednodušuje a zefektivňuje interní infrastrukturu, což dovoluje zpracovávat a odpovídat na DNS provoz ve stejném vlákně, které přijalo DNS dotaz od klienta. To ovlivňuje rychlost, latenci i paměťové nároky celého DNS serveru.

Jelikož je zapotřebí, aby vlákna zpracovávající síťový provoz fungovala co nejrychleji, zároveň byla přidána pomalá vlákna, která mají na starost pomalé operace, jako jsou příchozí zónové transfery, ověřování DNSSEC podpisů, zpracování katalogových zón, načítání souborů a další operace, které trvají déle a tak blokují zpracování příchozích a odchozích DNS zpráv.

Nové databázové jádro

BIND 9.20 přidává nové databázové jádro QPDB, které je postaveno nad datovou strukturou qp-trie optimalizovanou pro ukládání DNS dat. Tato nahrazuje původní databázi RBTDB, která je postavena nad datovou strukturou Red-Black Tree. Tato implementace Red-Black Tree v BIND 9 byla specifická v tom, že to byl spíše les než strom. Zjednodušeně řečeno – v rámci delegace se hlavní strom rozpadal na další Red-Black Tree stromy – což dělalo tuto původní datovou strukturu poměrně komplikovanou na údržbu. QPDB je nyní standardní databáze pro autoritativní zóny i pro DNS cache.

QPDB je implementováno nad knihovnou Userspace RCU, která poskytuje mechanismus pro synchronizaci dat mezi jednotlivými vlákny a lineárně škáluje přístupy pro čtení s počtem jader. Použití mechanismu Read-Copy-Update umožnilo odstranit některé stávající synchronizační mechanismy pomocí zámků (pthread_mutex) a read-write zámků (pthread_rwlock). Do budoucna bude základem pro další vylepšení databáze QPDB, která ve vyšších vrstvách ještě zachovává read-write zámky pro mechanismy, jakou je správa TTL pro záznamy v databázi nebo čištění keše při nedostatku paměti. V budoucích verzích by čtení DNS záznamů z databáze mělo ideálně lineárně škálovat.

Vylepšená podpora DNSSEC

BIND 9.20 odstraňuje volbu auto-dnssec a pro správu DNSSEC je nyní nutné přejít na DNSSEC Policy. Byla přidána podpora pro DNSSEC multi-signer model 2 (viz RFC 8901).

Správa klíčů pomocí DNSSEC Policy nyní navíc zahrnuje možnost uložení klíčů do HSM a BIND 9 nyní podporuje PKCS#11 i pro OpenSSL 3.x, ve které byl odstraněn původní mechanismus nazývaný Engine. Podpora pro PKCS#11 je implementována pomocí nového rozhraní Provider.

Další drobná vylepšení

  • Kompresní mechanismus DNS jmen byl vylepšen. Je nyní rychlejší a komprimuje jména důkladněji než předtím, obzvlášť v případě jmen, která obsahují mnoho částí.
  • Byla přidána podpora pro Katalogové zóny verze 2 (RFC 9432).
  • Implementace DNS over TCP, DNS over TCP a DNS over HTTP byly refaktorovány, aby používaly sjednocené implementace nižších vrstev. Díky tomu mohla být přidána podpora pro protokol PROXYv2, což oceníte zejména pokud BIND 9 integrujete společně s DNS load-balancerem dnsdist.
  • Do kódu byla přidána podpora pro uživatelské sondy USDT. Tyto sondy umožňují sledovat výkon aplikace pomocí příkazu perf a pokud nejsou používány, tak pro chod programu nepřidávají žádnou dodatečnou zátěž. Postupem času budeme do kódu přidávat další sondy a uvítáme i tipy na to, jaké sondy by se hodily uživatelům.
  • Statistiky nyní obsahují údaje o probíhajících zónových transferech.

Výkon resolveru

Vylepšení, která vidíte níže, jsou výsledkem kontinuální práce zmíněné na začátku článku a po zlepšení výkonu mezi verzemi 9.16 a 9.18 přichází další zlepšení výkonu mezi verzemi 9.18 a 9.20. Nejvýznamnější je asi fakt, že se nám povedlo zvýšit výkon zároveň se snížením spotřeby paměti. Pokud Vás zajímají detaily o tom, jak výkon resolveru měříme, tak více detailů je možné najít v předchozím blogu na stránkách ISC.

Latence odpovědí

Než se pustíme do dat, tak je potřeba zmínit, jakým způsobem data vizualizujeme. Bohužel data z DNS provozu jsou zkosená směrem k nule a nelze použít standardní deskriptivní statistiku. Proto se pro vizualizaci DNS latence používá graf, který vyvinuli kolegové z PowerDNS, logaritmický histogram percentilů, který umí zobrazit detaily jako jsou:

  • 95 % dotazů bylo zodpovězeno do 1 ms (cache-hit)
  • 99 % dotazů bylo zodpovězeno do 100 ms (cache-miss)
  • 99.5 % dotazů bylo zodpovězeno do 1000 ms (nějaký problém)

Pro interpretaci následujících grafů platí – čím blíže je křivka k levému dolnímu rohu, tím jsou výsledky lepší (bylo zodpovězeno více dotazů v kratším čase). Horní linka je limit 2 sekundy, kdy dojde k vypršení dotazu na straně klienta. Barevné pozadí v grafu zobrazuje rozptyl mezi jednotlivými měřeními (tři opakování).

UDP provoz

Pro měření UDP používáme reálný provoz poskytnutý skutečným ISP a do testovacího prostředí pouštíme provoz z 15 různých serverů ve stejný čas na jeden cílový server. Máme k dispozici celkem 40 unikátních záznamů provozu, ale kdybyste nám chtěli poskytnout další, tak se rozhodně nebudeme bránit.

UDP – Latence

Následující graf zobrazuje první polovinu měření, kdy je ze začátku cache ještě studená a resolver je pod největší zátěží – přijímá dotazy klientů, ale zároveň musí odesílat vlastní DNS dotazy autoritativním serverům, aby naplnil lokální cache.

Verze 9.20.0 není schopná při takové zátěži odpovědět asi na 3 % dotazů v rámci 2 sekund. Při stejných podmínkách není BIND 9.18.28 schopný odpovědět na 15 % dotazů, a BIND 9.16 nechá bez odpovědi celou čtvrtinu dotazů.

V druhé polovině měření je cache už naplněná a DNS server je schopný odpovídat na více dotazů:

V tomto případě je rozdíl mezi verzemi 9.18 a 9.20 marginální, ale jde vidět, že verze 9.16 má stále s takovou zátěží problém a výsledky jsou nestabilní.

UDP – Spotřeba CPU

Využití paměti měříme v Linuxu pomocí Control Group version 2 ( usage_usec) a následně normalizujeme tak, že 1 CPU je 100 %. Náš testovací stroj má 16 jader, takže teoretická maximální hodnota je 1600 %.

Vidíme, že v prvních sekundách běhu, je BIND 9.20 lépe paralelizovaný a využívá dostupné CPU lépe pro to, aby rychleji naplnil DNS cache. Pak je již zátěž CPU o něco menší než v případě verze 9.18.

UDP – Spotřeba paměti

Podobně jako v případě CPU měříme paměť pomocí cgroups ( memory.current) – tato metrika obsahuje veškerou paměť, kterou kernel přiřadil procesu včetně síťových bufferů.

Na začátku, kdy je cache ještě studená, je spotřeba paměti oproti předchozím verzím třetinová. Zároveň je dobré si všimnout, že BIND 9.20 má více předvídatelnou spotřebu paměti – rozptyl mezi měřeními je mnohem menší. V případě BIND 9.16 jde vidět, že alokátor paměti v podstatě nevracel pamět zpět do systému. BIND 9.18 a vyšší doporučují kompilaci s alokátorem jemalloc, který je mnohem efektivnější při mnoha manipulacích s malými kousky paměti. Konvergující hodnoty ke konci měření jsou způsobeny rozdíly v cache databázi (viz výše RBTDB vs QPDB) – nutné je poznamenat, že všechny verze dodržují nakonfigurovanou hodnotu pro max-cache-size .

TCP provoz

Zpracování TCP je a bude vždy o něco pomalejší než zpracování UDP, tudíž následující grafy používají pouze pětinásobný násobitel zaznamenaného provozu.

TCP – Latence

Následující graf opět zobrazuje první polovinu měření, kdy je na začátku cache ještě studená:

BIND 9.18.28 takový provoz zvládá, ale 0.5 % dotazů je bez odpovědi. Verze 9.20 tuto ztrátu stahuje na pouhých 0.2 %. Jak je vidět, tak na výkon TCP lze ve verzi 9.16 úplně zapomenout.

Ve chvíli, kdy už je cache naplněná, tak verze 9.20 zlepšuje latenci přibližně u 25 % dotazů – skoro 95 % dotazů je zodpovězeno do 1 ms, v případě předchozí verze to bylo jenom 70 %.

TCP – Spotřeba CPU

Podobně jako u UDP je vidět, že na začátku BIND 9.20 využívá zdroje lépe a je tedy schopný rychleji naplnit cache. BIND 9.16 vůbec nestíhá a využití CPU je velmi nestabilní:

TCP – Spotřeba paměti

V případě TCP verze 9.20.0 spotřebovává šestkrát méně paměti a zároveň vylepšuje latenci i využití CPU. A pokud používáte BIND 9.16, tak byste měli přejít alespoň na BIND 9.18.

DNS-over-TLS provoz

Podobně jako v předchozích případech, BIND 9.20 vylepšuje latenci a spotřebu paměti. Následující obrázky budou již bez komentáře.

DoT – Latence

DoT – Spotřeba CPU

DoT – Spotřeba paměti

Pár slov na závěr

I přestože první commit BIND 9 zažil již v roce 1998 a první verze vyšla v roce 2000, není potřeba nad tímto veteránem na poli DNS serverů lámat hůl. Myslím si, že celý tým, který pracuje na BIND 9, odvedl za těch posledních 7 let nesmírný kus práce, a zároveň s odmazáním velké části technického dluhu přinesly nové verze i nové nebo vylepšené vlastnosti.

CS24 tip temata

BIND 9 má také nyní mnohem více otevřený vývoj, které je možné sledovat na naší instanci GitLabu, kde také můžete nahlásit chyby, nebo přispět vlastním vylepšení. Kód BIND 9 je pod svobodnou licencí MPL 2.0.

(Autorem obrázků je Ondřej Surý.)

Autor článku

Autor spojil svůj profesní život s open-source a DNS.