构建企业级 DNS
服务压测, 服务的功能测试, 这些在生产中都要考虑到
1, 硬件选型
dns 对网卡和 CPU 消耗大
下面配置可以达到单台服务器每秒 3 万请求, 0 延时
CPU:12c 以上配置
内存: 16GB
网络: 千兆
2, 初始化系统
关闭 selinux,iptables, 调整 ulimit 限制
3, 构建高性能, 高可用 dns
采用 lvs-dr 模式负载均衡, 多 idc, 多套 dns 集群, 通过 master-slave 技术保证 dns 配置的一致性
(1), 高可用
物理层:
首先确保两台 lvs 不在统一机柜, 同一物理交换机接入;
其次确保将所有 dns 服务器也做到不在同一机柜, 同一物理交换机接入.
同时, 在不同的 idc 构建多套 dns 集群, 为客户端提供可切换的配置.
服务层:
坚决摒弃 lvs 上端口检测这种方式, 采用自定义脚本检测, 为 dns 的健康检测单独设置一个域名, 就为了 lvs 检测 dns 是否存活而设计.
脚本示例, 这个脚本是部署在 lvs 上, 做健康检测的
- #!/bin/sh
- timeout=5
- Q="baidu.com"
- host="/usr/bin/host"
- if test -z "$1" ;then
- echo "You need to supply a DNS Server to check. Quitting"
- exit;
- fi
- SERVER=$1
- ERC=`$host -s -w $timeout $Q $SERVER> /dev/null 2>&1;echo $?`
- if [ $ERC -eq 0 ];then
- exit 0
- else exit 1
- fi
客户端层:
多 idc 之间的流量切换是通过客户端的健康检测 cron 实现的, 脚本每分钟运行一次, 分别检测每个 dns 集群虚地址的可用性.
(2), 高性能
通过 lvs 可以对每个集群做横向扩容, 是否需要扩容的一句是对现有系统的压测结果, 以及实时的监控数据.
亦或者可以在靠近应用层处, 加上一层 cache-only 集群, 但前提是你的线上环境中, 没人任何系统依赖于 dns 负载均衡
4, 压测
安装 queryperf
下载 bind 源码: wget
解压 bind 源码: tar zxf bind-9.7.3.tar.gz
进入解压后的 bind 源码目录:
- [root@Linux-node1 tools]# wget http://ftp.isc.org/isc/bind9/9.7.3/bind-9.7.3.tar.gz
- --2017-05-19 15:38:02-- http://ftp.isc.org/isc/bind9/9.7.3/bind-9.7.3.tar.gz
- Resolving ftp.isc.org... 149.20.1.49
- Connecting to ftp.isc.org|149.20.1.49|:80... connected.
- HTTP request sent, awaiting response... 200 OK
- Length: 7653584 (7.3M) [application/x-gzip]
- Saving to: "bind-9.7.3.tar.gz"
- 100%[======================================================================>] 7,653,584 1.13M/s in 7.9s
- 2017-05-19 15:38:12 (950 KB/s) - "bind-9.7.3.tar.gz" saved [7653584/7653584]
- [root@Linux-node1 tools]# tar xfz bind-9.7.3.tar.gz
- [root@Linux-node1 tools]# cd bind-9.7.3/contrib/queryperf/
配置和编译
- [root@Linux-node1 queryperf]# ./configure
- checking for gcc... gcc
- checking for C compiler default output file name... a.out
- checking whether the C compiler works... yes
- checking whether we are cross compiling... no
- checking for suffix of executables...
- checking for suffix of object files... o
- checking whether we are using the GNU C compiler... yes
- checking whether gcc accepts -g... yes
- checking for gcc option to accept ISO C89... none needed
- checking for library containing res_mkquery... no
- checking for library containing __res_mkquery... -lresolv
- checking for socket in -lsocket... no
- checking for inet_ntoa in -lnsl... yes
- checking for gethostbyname2... yes
- checking for getaddrinfo... yes
- checking for getnameinfo... yes
- checking for socklen_t... yes
- checking for sa_len... no
- configure: creating ./config.status
- config.status: creating Makefile
- config.status: creating config.h
- [root@Linux-node1 queryperf]# make
- gcc -DHAVE_CONFIG_H -c queryperf.c
- gcc -DHAVE_CONFIG_H queryperf.o -lnsl -lresolv -lm -o queryperf
- [root@Linux-node1 queryperf]#
会在当前目录下出现 queryperf, 可以将它拷贝至 / usr/bin / 下
- [root@Linux-node1 queryperf]# ls
- config.h config.log configure input Makefile.in queryperf queryperf.o utils
- config.h.in config.status configure.in Makefile missing queryperf.c README
- [root@Linux-node1 queryperf]# cp queryperf /usr/bin/
- [root@Linux-node1 queryperf]#
测试, 可以查看解析成功率和解析时间
- [root@Linux-node1 queryperf]# cat test.txt
- www.baidu.com A
- www.qq.com A
- www.sina.com A
- www.dangdang.com A
- [root@Linux-node1 queryperf]# queryperf -d test.txt -s 10.0.1.161
- DNS Query Performance Testing Tool
- Version: $Id: queryperf.c,v 1.12 2007-09-05 07:36:04 marka Exp $
- [Status] Processing input data
- [Status] Sending queries (beginning with 10.0.1.161)
- [Status] Testing complete
- Statistics:
- Parse input file: once
- Ended due to: reaching end of file
- Queries sent: 4 queries
- Queries completed: 4 queries
- Queries lost: 0 queries
- Queries delayed(?): 0 queries
- RTT max: 0.172311 sec
- RTT min: 0.000703 sec
- RTT average: 0.075561 sec
- RTT std deviation: 0.063613 sec
- RTT out of range: 0 queries
- Percentage completed: 100.00%
- Percentage lost: 0.00%
- Started at: Fri May 19 15:43:39 2017
- Finished at: Fri May 19 15:43:39 2017
- Ran for: 0.172392 seconds
- Queries per second: 23.202933 qps
- [root@Linux-node1 queryperf]#
5, 监控
监控结合 zabbix 实现
系统基础性能:
使用 zabbix 自带模板即可. CPU, 内存, 主机存活, 磁盘空间, 主机运行时间, 系统 load
LOOPBACK 地址绑定状态监控:
该架构中, dnsserver 在集群中充当 realserver 的角色, 在 dr 中, 需要绑定 loopback 的地址方能通信, 因此当 loopback 地址没有绑定上时, lvs 健康检测通过, 但是当请求到达 dnsserver 时, 请求被拒绝, dns 集群会出现异常.
DNS 数据与 MASTER 一致性监控:
一是通过写 zabbix 自定义 discovery, 扫出 dns 配置中所有 zone, 然后分别对比 slave 和 master 每个 zone 的 serial 值, 当 slave 与 master 的值持续 5 分钟不一致时报警
二是写脚本, 每 15 分钟扫一遍 master 上所有域名解析结果, 与每个 slave 的结果做对比, 当出现结果不一致时, 报警
DNS 响应时间监控:
远端一组主机跑在 fullnat 下 (提供高可用), 通过 dig 命令监测 dnsserver 的响应时间.
其中 Query time 就是查询的时间
- [root@Linux-node1 ~]# dig @127.0.0.1 www.baidu.com
- ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.el6_9.2 <<>> @127.0.0.1 www.baidu.com
- ; (1 server found)
- ;; global options: +cmd
- ;; Got answer:
- ;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 31992
- ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
- ;; WARNING: recursion requested but not available
- ;; QUESTION SECTION:
- ;www.baidu.com. IN A
- ;; Query time: 2 msec
- ;; SERVER: 127.0.0.1#53(127.0.0.1)
- ;; WHEN: Fri May 19 17:10:27 2017
- ;; MSG SIZE rcvd: 31
- [root@Linux-node1 ~]#
有人觉得 3ms 慢, 有人觉得 30ms 慢, 没特别的统一的标准
DNS 每秒请求数监控:
主配置文件中, 这个文件可以用于监控
- [root@Linux-node1 ~]# grep stats /etc/named.conf
- Statistics-file "/var/named/chroot/var/log/named_stats";
- memstatistics-file "log/mem_stats";
- [root@Linux-node1 ~]#
先执行 rndc stats 生成状态文件
- [root@Linux-node1 ~]# rndc stats
- WARNING: key file (/etc/rndc.key) exists, but using default configuration file (/etc/rndc.conf)
查看状态文件
- [root@Linux-node1 ~]# cat /var/named/chroot/var/log/named_stats
- +++ Statistics Dump +++ (1495185099)
- ++ Incoming Requests ++
- 393 QUERY
- ++ Incoming Queries ++
- 23 A
- 362 SOA
- 3 MX
- 3 AAAA
- ++ Outgoing Queries ++
- [View: GROUP1]
- 11 A
- 3 NS
- 1 MX
- 1 AAAA
- [View: GROUP2]
- [View: _bind]
- ++ Name Server Statistics ++
- 393 IPv4 requests received
- 362 requests with EDNS(0) received
- 393 responses sent
- 362 responses with EDNS(0) sent
- 24 queries resulted in successful answer
- 6 queries resulted in authoritative answer
- 385 queries resulted in non authoritative answer
- 362 queries resulted in referral answer
- 5 queries resulted in nxrrset
- 14 queries caused recursion
- ++ Zone Maintenance Statistics ++
- ++ Resolver Statistics ++
- [Common]
- [View: GROUP1]
- 16 IPv4 queries sent
- 16 IPv4 responses received
- 14 queries with RTT 10-100ms
- 2 queries with RTT 100-500ms
- [View: GROUP2]
- [View: _bind]
- ++ Cache DB RRsets ++
- [View: GROUP1 (Cache: GROUP1)]
- 4 A
- 1 NS
- 6 CNAME
- 1 MX
- 1 RRSIG
- [View: GROUP2 (Cache: GROUP2)]
- [View: _bind (Cache: _bind)]
- ++ Socket I/O Statistics ++
- 18 UDP/IPv4 sockets opened
- 3 TCP/IPv4 sockets opened
- 16 UDP/IPv4 sockets closed
- 2 TCP/IPv4 sockets closed
- 16 UDP/IPv4 connections established
- 3 TCP/IPv4 connections accepted
- ++ Per Zone Query Statistics ++
- [viewlnh.com (view: GROUP1)]
- 1 queries resulted in successful answer
- 3 queries resulted in authoritative answer
- 2 queries resulted in nxrrset
- [viewlnh.com (view: GROUP2)]
- 1 queries resulted in successful answer
- 3 queries resulted in authoritative answer
- 2 queries resulted in nxrrset
- [version.bind (view: _bind)]
- [hostname.bind (view: _bind)]
- [authors.bind (view: _bind)]
- [id.server (view: _bind)]
- --- Statistics Dump --- (1495185099)
- [root@Linux-node1 ~]#
在每台 dns 主机上, 编写 zabbix 脚本, 分析 named_stats 文件, 获取每秒请求数
下面这个脚本比较粗略, 有时间可以自己优化下, 加锁, 记录日志等.
- #!/bin/bash
- #rndc stats
- STATS='/var/named/chroot/var/log/named_stats'
- if [ $# -ne 1 ];then
- echo "$0 [querys]"
- exit 2
- else
- which=$1
- fi
- if [ -f "${STATS}" ];then
- echo> ${STATS}
- rndc stats>dev/null 2>&1
- else
- echo "${STATS} not found"
- exit 2
- fi
- case ${which} in
- querys)
- RESULT=` awk '{if ($2=="QUERY") {print $1}}' ${STATS}`
- ;;
- *)
- echo "$0 [querys]"
- exit 2
- ;;
- esac
- echo ${RESULT}
DNS 可用性监控:
远端一组主机跑在 fullnat 下 (提供高可用), 通过 host 命令监测 dnsserver 的可用性, 脚本与 lvs 健康检测脚本类似
6, 自动化
saltstack 安装, 部署
通过定制 saltstack 配置, 实现自动, 批量安装, 部署 dns
配置管理自动化
业界最多的是 bind-dlz,dlz 是指将所有的配置都存在 MySQL 表中, 对 bind 做特殊配置, 使得每次 bind
接受的请求都去 MySQL 中查询数据之后返回给用户
bind-dlz 的优缺点
优势: 将数据全部存在数据库, 符合运维开发的理念.
劣势: 每次解析都要 select 数据库, 性能低下; 增加了系统的耦合性, 还需要保证 MySQL 的高可用
我的方案
采用 dlz 的数据库部分表结构;
用 ThinkPHP 实现对 MySQL 的增删改查, 和一些权限控制的页面, 在该页面, 用户可以完成对域名的增删改查操作, 数据源在 MySQL 中;
通过 saltstack+py 实现从 mytsql 中调数据, 生成 bind 的配置文件, 并检测文件格式, 之后 reload
改造了, 提前生成 dns 的配置文件. 这样 MySQL 挂了没事
为什么要做成页面可以管理的呢
为什么做这些, 我要将 dns 做成可交付, 已维护的系统, 交付给应用运维同学使用, 我只负责 dns 架构的 server 端
https://github.com/shanks1127/dns
7, 安全
时刻关注 dns 相关的抖动, 补丁;
选用稍大些的厂商作为域名服务商, 我们是万网;
对服务器的登录日志做监控分析;
8, 日常运维规范
dns 作为基础服务, 在做好高可用, 高性能, 好扩容的基础上, 任何时刻都不能掉以轻心
确保所有监控均处于生效状态;
所有新机器, 均在 saltstack 上完成初始化和安装, 部署操作, 不能单独操作;
所有针对 dns 架构调整的操作, 均需在流量低谷时操作;
对集群扩容操作时, 务必对新加入节点做压测, 同时重启服务器并检测重启后各项指标是否正常;
来源: http://www.bubuko.com/infodetail-2972647.html