网络出现的早期是使用IP地址通讯的,那时就几台主机通讯。但是随着接入网络主机的增多,这种数字标识的地址非常不便于记忆,UNIX上就出现了建立一个叫做hosts的文件(Linux和Windows也继承保留了这个文件)。这个文件中记录着主机名称和IP地址的对应表。这样只要输入主机名称,系统就会去加载hosts文件并查找对应关系,找到对应的IP,就可以访问这个IP的主机了。
但是后来主机太多了,无法保证所有人都能拿到统一的最新的hosts文件,就出现了在文件服务器上集中存放hosts文件,以供下载使用。互联网规模进一步扩大,这种方式也不堪重负,而且把所有地址解析记录形成的文件都同步到所有的客户机似乎也不是一个好办法。这时DNS系统出现了,随着解析规模的继续扩大,DNS系统也在不断的演化,直到现今的多层架构体系。
DNS(DomainNameSystem,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53。
DNS的分布式数据库是以域名为索引的,每个域名实际上就是一棵很大的逆向树中路径,这棵逆向树称为域名空间(domainnamespace)。如图所示树的最大深度不得超过127层,树中每个节点都有一个可以长达63个字符的文本标号。
首先,客户端先在本地缓存查找有没有域名缓存,如果没有,客户端发出DNS请求翻译IP地址或主机名。DNS服务器在收到客户机的请求后:
(1)检查DNS服务器的缓存,若查到请求的地址或名字,即向客户机发出应答信息;
(2)若没有查到,则在数据库中查找,若查到请求的地址或名字,即向客户机发出应答信息;
(3)若没有查到,则将请求发给根域DNS服务器,并依序从根域查找顶级域,由顶级查找二级域,二级域查找三级,直至找到要解析的地址或名字,即向客户机所在网络的DNS服务器发出应答信息,DNS服务器收到应答后现在缓存中存储,然后,将解析结果发给客户机。
(4)若没有找到,则返回错误信息。
主DNS服务器:就是一台存储着原始资料的DNS服务器。
从DNS服务器:使用自动更新方式从主DNS服务器同步数据的DNS服务器。也成辅助DNS服务器。
缓存服务器:不负责本地解析,采用递归方式转发客户机查询请求,并返回结果给客户机的DNS服务器。同时缓存查询回来的结果,也叫递归服务器。
转发器:这台DNS发现非本机负责的查询请求时,不再向根域发起请求,而是直接转发给指定的一台或者多台服务器。自身并不缓存查询结果。
SOA
可以理解为一段为自己dns做备注说明的文本,一般与ns一致
比如:dns.laonanhai.comsa.laonanhai.com
示例:
a.shifen.com.579INSOAdns.baidu.com.sa.baidu.com.(1408010001;serialnumber5;refresh5s5;retry5s86400;expire1d3600;minTTL1h)
NS
NSDName:DNS的FQDN
baidu.com.64899INNSns2.baidu.com.baidu.com.64899INNSns4.baidu.com.baidu.com.64899INNSdns.baidu.com.baidu.com.64899INNSns7.baidu.com.baidu.com.64899INNSns3.baidu.com.
MX
域的邮件交换器,要跟着一个优先级值,越小越高
baidu.com.7200INMX20jpmx.baidu.com.
baidu.com.7200INMX20mx50.baidu.com.
baidu.com.7200INMX10mx.n.shifen.com.
baidu.com.7200INMX20mx1.baidu.com.
A
IPV4主机地址
AAAA
IPV6主机地址
PTR
解析IP的指针,反向记录
CNAME
权威(正式)名称,定义别名记录
www.baidu.com.1154INCNAMEwww.a.shifen.com.
1.26个英文字母
2.“0,1,2,3,4,5,6,7,8,9”十个数字
3.“-”(英文中的连词号)
4.最多63字节长度
要不按照这个,bind支不支持,支持,合适么,不合适。
非要不按照这个,怎么办?master-view文件上配置check-namesignore;
Host命令也是大多数系统、软件库调用的解析命令,比如php中。
Nslookup能够反映出是哪个dnsserver返回的结果
Dig返回整个解析过程的详细路径,类似traceroute
Bind是一款开放源码的DNS服务器软件,Bind由美国加州大学Berkeley分校开发和维护的,全名为BerkeleyInternetNameDomain它是目前世界上使用最为广泛的DNS
配置yum源
使用centos6自带的yum源即可,同时确保机器可以解析外网域名,并能连接公网
Yum安装bind
yuminstallbind-utilsbindbind-develbind-chroot
编辑/etc/named.conf
options{
listen-onport53{any;};
allow-query{any;};
zone-statisticsyes;
empty-zones-enableno;
forwarders{202.106.196.115;8.8.8.8;};
};
algorithmhmac-md5;
controls{
inet127.0.0.1port953
logging{
channelwarning{
severitywarning;
print-categoryyes;
print-severityyes;
print-timeyes;
channelgeneral_dns{
severityinfo;
categorydefault{
warning;
categoryqueries{
general_dns;
编辑/etc/rndc.key
编辑/etc/rndc.conf
default-server127.0.0.1;
default-port953;
编辑/var/named/chroot/etc/view.conf
typemaster;
allow-transfer{
10.255.253.211;
notifyyes;
also-notify{
编辑/var/named/chroot/etc/lnh.com.zone
$ORIGIN.
$TTL3600;1hour
lnh.comINSOAop.lnh.com.dns.lnh.com.(
2000;serial
900;refresh(15minutes)
600;retry(10minutes)
86400;expire(1day)
3600;minimum(1hour)
)
NSop.lnh.com.
$ORIGINlnh.com.
shanksA1.2.3.4
opA1.2.3.4
1Serial:只是一个序号,但这个序号可被用来作为slave与master更新的依据。举例来说,master序号为100但slave序号为90时,那么这个zonefile的资料就会被传送到slave来更新了。由于这个序号代表新旧资料,通常我们建议你可以利用日期来设定!举例来说,上面的资料是在2006/10/20所写的第一次,所以用2006102001作为序号代表!(yyyymmddnn,nn代表这一天是第几次修改)
2Refresh:除了根据Serial来判断新旧之外,我们可以利用这个refresh(更新)命令slave多久进行一次主动更新;
5Minimun:这个就有点象是TTL!
修改目录权限,并启动服务
cd/var&&chown-Rnamed.namednamed/
/etc/init.d/namedstart
chkconfignamedon
我们试一把能不能解析
dig@127.0.0.1shanks.lnh.com
typeslave;
masters{10.6.0.253;};
修改master上view.conf配置,将slave节点ip加入,
之后修改lnh.com.zone将serial+1
之后在slave上修改目录权限,并启动
回到master节点,执行rndcreload
编辑master节点/var/named/chroot/etc/lnh.com.zone,在文件末尾添加一条记录
aA192.168.122.100
将serial值+1
执行rndcreload命令
分别对master、slave解析下:hosta.lnh.com127.0.0.1结果应该是192.168.122.100
cnameCNAMEa.lnh.com.
分别对master、slave解析下:hostcname.lnh.com127.0.0.1结果应该是192.168.122.101
mxMX5192.168.122.101
分别对master、slave解析下:hostmx.lnh.com127.0.0.1结果应该是192.168.122.101
编辑master节点/var/named/chroot/etc/view.conf,加入ptr的zone配置
10.6.0.254;
编辑master节点/var/named/chroot/etc/168.192.zone
@INSOAop.lnh.com.dns.lnh.com.(
2004;serial
102.122INPTRa.lnh.com.
修改168.192.zone文件的属性
chownnamed.named168.192.zone
rndcreload
编辑slave节点/var/named/chroot/etc/view.conf,加入ptr的zone配置
masters{10.5.35.14;};
使slave配置生效,slave上执行
分别对两台机器做ptr记录的解析
host192.168.122.102127.0.0.1结果应为a.lnh.com
aA192.168.122.102
分别对master、slave解析下:hosta.lnh.com127.0.0.1结果应该是192.168.122.100和192.168.122.102
编辑master节点vim/var/named/chroot/etc/named.conf,在include上面添加
aclgroup1{
10.5.35.14;
aclgroup2{
10.5.35.15;
编辑master节点vim/var/named/chroot/etc/view.conf为
match-clients{group1;};
match-clients{group2;};
编辑master节点vim/var/named/chroot/etc/group1.viewlnh.com.zone
viewlnh.comINSOAop.viewlnh.com.dns.viewlnh.com.(
2005;serial
NSop.viewlnh.com.
$ORIGINviewlnh.com.
opA192.168.122.1
viewA192.168.122.1
opA192.168.122.2
viewA192.168.122.2
修改文件所属,加载配置
chownnamed.named/var/named/chroot/etc/group*.zone
分别在主机A与B上做view.viewlnh.com的域名解析测试
结果应为主机A上是192.168.122.1主机B上是192.168.122.2
Cpu:12c以上配置
内存:16G
网络:千兆
关闭selinux:/etc/selinux/config
关闭iptables:chkconfigiptablesoff
采用lvs-dr模式负载均衡,多idc,多套dns集群,通过master-slave技术保证dns配置的一致性。
1、高可用
物理层:
首先确保两台lvs不在同一机柜、同一物理交换机接入;
其次确保将所有dns服务器也做到不在同一机柜、同一物理交换机接入。
同时,在不同的idc构建多套dns集群,为客户端提供可切换的配置。
服务层:
坚决摒弃lvs上端口检测这种方式,采用自定义脚本检测,为dns的健康检测单独设置一个域名,就为了lvs检测dns是否存活而设计。
脚本示例:
客户端层:
多idc之间的流量切换是通过客户端的健康检测cron实现的,脚本每分钟运行一次,分别检测每个dns集群虚地址的可用性。
1、高性能
通过lvs可以对每个集群做横向扩容,是否需要扩容的依据是对现有系统的压测结果,以及实时的监控数据。
亦或者可以在最靠近应用层处,加上一层cache-only集群,但前提是你的线上环境中,没有任何系统依赖于dns负载均衡。
安装queryperf
解压bind源码:tarzxfbind-9.7.3.tar.gz
进入解压后bind源码目录:cdbind-9.7.3/contrib/queryperf/
编译:./configure
make
会在当前目录下出现queryperf,可以将它拷贝至/usr/bin/下
编辑域名记录文件(test.txt),格式如下:
www.baidu.comA
压测命令:queryperf-dtest.txt-s8.8.8.8
按照3.1中的硬件选型,也做了3.2的初始化,这样在相同idc的压测下,单台dns-server的qps可以达到35~40k
监控结合zabbix实现
该架构中,dnsserver在集群中充当realserver的角色,在dr中,需要绑定loopback地址方能通信,因此当loopback地址没有绑定上时,lvs健康检测通过,但是当请求到达dnsserver时,请求被拒绝,dns集群会出现异常。
此处我的方案是分为两部分:
一是通过写zabbix自定义discovery,扫出dns配置中所有zone,然后分别对比slave和master每个zone的serial值,当slave与master的值持续5分钟不一致时报警
二是写脚本,每15分钟扫一遍master上所有域名解析结果,与每个slave的结果做对比,当出现结果不一致情况时,报警
在每台dns主机上,编写zabbix脚本,分析named_stats文件,获取每秒请求数
#!/bin/bash
#rndcstats
if[[$#-ne1]]
then
exit2
else
which=$1
fi
echo>${STATS}
rndcstats>/dev/null2>&1
case${which}in
querys)
;;
*)
esac
echo${RESULT}
远端一组主机跑在fullnat下(提供高可用),通过host命令检测dnsserver的可用性,脚本与lvs健康检测脚本类似。
通过定制saltstack配置,实现自动、批量安装、部署dns
业界最多的是bind-dlz,dlz是指将所有的配置都存在mysql表中,对bind做特殊配置,使得每次bind接受的请求都去mysql中查询数据之后返回给用户。
优势:将数据全部存在数据库,符合运维开发的理念。
劣势:每次解析都要select数据库,性能低下;
增加了系统的藕合性,还需要保证mysql的高可用。
采用dlz的数据库部分表结构;
用thinkphp实现对mysql的增删改查,和一些权限控制的页面,在该页面,用户可以完成对域名的增删改查操作,数据源在MySQL中;
通过saltstack+py实现从mysql中调数据,生成bind的配置文件,并检测文件格式,之后reload;
为什么做这些,我要将dns做成可交付、已维护的系统,交付给应用运维同学使用,我只负责dns架构的server端;
选用稍大些的厂商作为域名服务商,我们是万网;
Dns作为基础服务,在做好高可用、高性能、好扩容的基础上,任何时刻都不能掉以轻心!!!
确保所有监控均处于生效状态;
所有新机器,均在saltstack上完成初始化和安装、部署操作,不能单独操作;
所有针对dns架构调整的操作,均需在流量低谷时操作;
对集群扩容操作时,务必对新加入节点做压测,同时重启服务器并检测重启后各项指标是否正常;
有一些公司在每台服务器上都起着dnsmasq,充当本地dns缓存服务,来提高dns解析性能同时减轻dnsserver的压力。
但凡使用域名来给用户提供服务的互联网企业,都或多或少地无法避免在有中国特色的互联网环境中遭遇到各种域名被缓存、用户跨网访问缓慢等问题。
其次就是域名解析过了太多层的nat,这就导致dns获取客户端地址时很难准确定位,从而智能dns的准确度大打折扣。
用户明确的知道我在访问某厂的服务时,应该去找哪个ip要对应的域名,实现这个的前提是你可以左右用户的访问习惯,目前应用最适合的场景是app
在可预见的未来,不论在公司内网还是公网环境,dns在整个架构中,都将会以一个基础服务的位置存在,而目前最为稳定、高效的,依然是bind。
正常情况下dns会优先使用udp,但是在udp受限的情况下会使用tcp
记得那时我刚来公司还没转正的时候。有个哥们问我,dns现在没什么事吧?卧槽,dns?什么dns?
记得那会线上跑着多少dns,每台dns配置一不一样,没人说得清楚。于是我说兄弟,你什么dns,怎么了?他告诉我一个ip,说用的这个dns,现在解析不了了。我说我看下,你先改个别的dns,这种时候一定要先恢复业务,然后再排查、解决问题。
我尝试用那台dns解析域名,确实不行了,登上去看,dns进程还在,想来是有什么瓶颈了,看日志吧,在日志中发现有报netfilter满了的日志,怎么tm会报这个呢,难道机器起着iptables?卧槽,还真是起着呢,这不蛋逼呢么。赶紧把iptables停掉,问题恢复了。
在iptable运行时,即便是没有任何规则,所有的报文也要过netfilter表,而dns这种高并发的业务很容易把netfilter表填满,从而影响服务。
后续的工作就是整理线上dns,同一配置,做好监控,做好高可用和负载均衡
虽然恢复起来很快,但是这也提醒我,系统之间,一定要尽量减小藕合性,避免雪崩。
出现这种情况让人很头大,而旁边开发小妹还在殷切的看着你,你背后还有领导不时的喘着粗气,而恰恰此时你对这问题一点头绪也没有,怎么办?
越是这种时候,越要淡定,不然怎么办?!这玩意不是谁教的,是你多遇到几次这种情况,每次都要提醒自己,冷静、冷静、tmd冷静
1.递归查询:
一般客户机和服务器之间属递归查询,即当客户机向DNS服务器发出请求后,若DNS服务器本身不能解析,则会向另外的DNS服务器发出查询请求,得到结果后转交给客户机
2.迭代查询(反复查询):
一般DNS服务器之间属迭代查询,如:若DNS2不能响应DNS1的请求,则它会将DNS3的IP给DNS2,以便其再向DNS3发出请求;
以一个dns请求解析为例:
1、用户发起域名请求到dnsA,这时dnsA有这个记录,将结果返回给用户,这个过程是递归查询
2、用户发起域名请求到dnsA,这时dnsA没有这个记录,他去向dnsB问有没有这个记录,以此类推,直到把结果返回给用户,这个过程是递归查询
3、用户发起域名请求到dnsA,这时dnsA没有这个记录,他告诉用户,我没有这个记录,你去问dnsB吧,这个过程是迭代查询
首先,客户端发出DNS请求翻译IP地址或主机名。DNS服务器在收到客户机的请求后:
(2)若没有查到,则在自身配置中查找,若查到请求的地址或名字,即向客户机发出应答信息;
####################################################################
#Autoinstallbind
#CreateDate:2012-11-28
#Writtenby:shanks
#Organization:DangDang
cd/usr/local/src/
yum-yinstallbind-utilsbindbind-develbind-chrootbind-libs>>/tmp/init_sn.log-y&&rndc-confgen-r/dev/urandom-a||exit1
#***config/etc/named.conf***
cat<
shanks1
#***config/etc/rndc.key***
cat<
shanks2
#***config/etc/rndc.conf***
cat<
#Startofrndc.conf
shanks3
#***config/var/named/chroot/etc/view.conf***
cat<
#dns-ip-list;
#ixfr-from-differencesyes;
typeforward;
forwarders{10.255.253.220;};
shanks4
#***config/var/named/chroot/etc/com.zone***
cat<
\$ORIGIN.
\$TTL3600;1hour
comINSOAop.shanks.com.dns.shanks.com.(
NSop.shanks.com.
\$ORIGINcom.
shanks5
#checkinstallstatus.
exit5
rndcstats
if[-f/tmp/Install_bind.sh]
rm-rf/tmp/Install_bind.sh
cd/usr/local/src/bind-9.9.7-P2&&./configure--prefix=/usr/local/bind--enable-threads--with-libtool&&make&&makeinstall