bind

简介

BIND(Berkeley Internet Name Domain),是现今互联网上最常使用的DNS软件,使用BIND作为服务器软件的DNS服务器约占所有DNS服务器的九成。BIND现在由互联网系统协会(Internet Systems Consortium)负责开发与维护。

主从的作用

1、共同解析域名——如master与slave任何一端dns服务断掉,也可以通过从另外一端来解析域名。

2、自动更新——如果master修改完成信息后,slave也会自动更新。

系统及部署环境

获取操作系统命令

  1. uname -sr
  2. cat /etc/redhat-release

获取bind版本命令

  • named -v
主机 主备 操作系统 bind版本
fnc05 10.154.5.163 主机master CentOS Linux release 7.9.2009 (Core) / Linux 3.10.0-1160.11.1.el7.x86_64 BIND 9.16.17 (Stable Release)
fnc04 10.154.5.162 从机slave CentOS Linux release 7.8.2003 (Core) / Linux 3.10.0-1127.18.2.el7.x86_64 BIND 9.16.16 (Stable Release)
fnc03 10.154.5.214 从机slave BigCloud Enterprise Linux For LDK release 7.6.1906 (Core) / Linux 4.19.25-200.1.el7.bclinux.x86_64 BIND 9.16.17 (Stable Release)

上述主备机仍需注意如下配置:

  1. 确保防火墙的规则不会拦截Bind的监听端口,默认为53。

    1. systemctl status firewalld
  2. 确保主从服务器的时钟一致。

    • date

    • 1
      2
      3
      4
      5
      yum install -y ntpdate 
      ntpdate time.nist.gov
      hwclock -w
      date
      hwclock
  3. 确保named用户拥有操作相关目录的权限(默认安装后就有了)

  4. 曾尝试9.11版本的主机,与9.16版本的从机,也能和谐运行。

bind部署架构

主从架构:

  1. 每个机器,无论主从,都部署独立的bind服务。
  2. 主机可读写,能够进行zone文件的维护管理(增删改)。
  3. 从机只读,从主机同步读取zone数据后,只可提供查询服务。
  4. 从机其实是从主机同步的是.zone文件,但具体是哪些.zone文件呢?这由named.conf中所配置的zone参数决定,每个需要同步的zone文件都会在named.conf中配置如下参数:
1
2
3
4
5
zone "abc.com" IN {
type slave; #说明需要备份的.zone文件
file "slaves/abc.com.zone"; #备份目录
masters { 10.154.5.163; }; #主机
};

因此主机每对zone进行增删时,都要维护slave备机的named.conf文件。详见Catalog zones章节,可采用手段自动维护。

rndc主从分布

rndc(Remote Name Domain Controllerr)是一个远程管理bind的工具,通过这个工具可以在本地或者远程了解当前服务器的运行状况,也可以对服务器进行关闭、重载、刷新缓存、增加删除zone等操作。

rndc面对bind服务的主从配置,只有一个原则,即rndc的独立与否与bind主从没有必然联系。是故,可以做任意选择:

  1. 第一种:两类机器都有自己独立的rndc配置。相互之间没有什么关系。各自的rndc控制自己的dns bind服务。
  2. 第二种:主机拥有rndc,从机只作为主机的客户端,远程控制主机的rndc。适用于从机不需要rndc更新任何dns数据,只需要主机rndc的情况。

但是,从机为了能够独立的管理从机(对自己重启之类的),建议采用第一种各自的rndc控制自己的dns bind服务。

本文涉及到的常用命令:

  1. rndc reload:重新装入配置文件 + 全部zone。如修改了named.conf
  2. rndc reconfig:仅重新装入配置文件 + 新zone。如修改了named.conf,或在named.conf新增加了一个叫test.com 的zone,就用rndc reconfig来让更改生效。
  3. rndc reload zone:重新装入指定某个zone。如仅修改了具体的某个zone文件,在test.com里面增加一个www.test.com的a记录,所以用rndc reload test.com来更新。

比如,修改了named.conf文件中的also-notify { 10.154.5.162; 10.154.5.214; };,因为仅修改了配置文件,没有涉及到zone。采用rndc reload和rndc reconfig均可。

  1. rndc status: 显示bind服务器的工作状态

  2. rndc sync zone:zone文件修改后,一般改动的信息被储存在*.jnl文件(二进制文件不宜修改)中。一般情况下在15分钟内,Bind会将jnl文件转储到区域文件中。此时添加进入的DNS记录是能够正常提供服务的。但如果想要需要实时更新到区域文件中,需要使用rndc sync且需要注意区域文件的文件权限。

参考
  1. rndc(8) — bind-utils — Debian experimental — Debian Manpages
  2. rndc (greenend.org.uk)

自动同步zone配置

背景

在主机master定义了一个zone,然后必须到所有备机slave都新增相应zone的配置,才能实现主从同步。因此,主备配置的核心在于,如何维护备机的zone配置列表(maintaining slave zone lists)。

如,主机的named.conf文件中增加了zone的配置

1
2
3
4
zone "abc.com" IN {
type master;
file "abc.com.zone";
};

则,从机也需要在named.conf文件中增加zone的配置

1
2
3
4
5
zone "abc.com" IN {
type slave; #说明需要备份的.zone文件
file "slaves/abc.com.zone"; #备份目录
masters { 10.154.5.163; }; #主机ip
};

目前,已知向从机named.conf文件中增加zone配置的方案,总共可以归结为3类:

  1. 传统方式,手动配置。不适合rndc动态添加的zone。
  2. 用户编写脚本(linux监听变动脚本或者python脚本),实现自动维护从机的zone配置。
  3. catalog zone目录区域,主从一次性配置,后续自动同步zone。

本文详细介绍catalog zone目录区域的配置。

方案-传统手动方式

主机

1
2
3
4
5
主机手动添加到named.rfc1912.zones(最终include到named.conf):
zone "my_zone.com" {
type master;
file "/etc/bind/db.my_zone.com";
};

从机

1
2
3
4
5
6
从机手动添加到named.rfc1912.zones(最终include到named.conf):
zone "my_zone.com" {
type slave;
file "db.my_zone.com";
masters { master_ip_address; };
};

方案-用户编写脚本

Left to the user to create a script or process for maintaining slave zone lists

用户编写脚本运行示意图:

bind官网9.11的升级文档指出,用户脚本较为麻烦:

参考
  1. Jan-Piet Mens :: Automatic provisioning of slave DNS servers (jpmens.net)
  2. Automatically sync all zones between BIND 9 - Server Fault

方案-Catalog zone【重点】

简介

Catalog zone本质上还是master上的一个zone文件,但具有一些特点:

  1. 特殊的格式。in a special new format
  2. 内容是一系列的待同步zones列表,称为“成员区域”。(”member zones”.)。contains a list of zones (the CatZ)

用途:Catalog zone(目录区域)是一项新的 BIND 功能(BIND 9.11 (2018) ),无论多少从机,都可以轻松地将zone配置到从机。

  1. 当Catalog zone加载或传输到支持此功能的从机时,从机会自动创建member zones。

  2. 更新Catalog zone时(例如,添加、删除member zones,或更改其配置参数),这些更改会立即生效。

  3. 因为Catalog zone是一个普通的 DNS 区域,所以可以使用标准的 AXFR/IXFR 区域传输机制来传播这些配置更改。

Catalog zone使用条件:

  1. 要求主、从服务器都采用 BIND。
  2. 要求BIND 9.11+版本。
实践配置简介

Catalog zone配置过程如下:

  1. 主机,创建一个Catalog zone(catZ)文件。这个文件用来维护需要同步的zones列表。
  2. 主机,named.conf中配置catZ。
  3. 从机,named.conf中配置catZ。
  4. 一旦catZ建立,从机自动获取主机的zone Catalog,自动获取zone Catalog中的zones列表变化,从而实现同步。
  5. zone Catalog可以有多个!
主从配置

作用:完成catalog目录的配置。

主机
  1. 打开目录/var/opt/isc/isc-bind/named/data,新建catalog目录文件(后缀名可以为.db或者.zone)
1
2
3
4
5
#catalog.default.zone
$TTL 3600
@ IN SOA . . 1 86400 3600 86400 3600
@ IN NS nop.
version IN TXT "1"
1
2
#修改权限
chown named.named catalog.default.zone
  1. 将catalog目录文件引入到named.conf中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
options {
#...
allow-new-zones yes; # RNDC动态维护zones
notify yes; # 主动通知从机更新,而不需要等待轮询时间进行更新
also-notify { 10.154.5.162; }; # 被主动通知的从机地址,可多个地址
allow-transfer { 10.154.5.162; 10.154.5.163; }; # 只允许列表中的主机传递主域名服务器的数据,为了方便扩展可以设置为key
allow-update { any; }; #允许向主zone文件发送动态更新的匹配列表,如果设置为none,则无法使用update命令(更新记录zone等)
allow-query { any; }; #添加允许访问DNS的地址段
}

zone "catalog.default" {
type master;
file "catalog.default.zone";
#also-notify { 10.154.5.162; };
#allow-transfer { 10.154.5.162; 10.154.5.163; };
#allow-update { any; };
#allow-query { any; };
};
从机

named.conf配置catalog目录,与主机建立关联。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
options {
#...
listen-on port 53 { 127.0.0.1; 10.154.5.162; 10.154.5.163; }; # 主机
allow-new-zones yes; # RNDC动态维护zones
masterfile-format text; #从机乱码问题
catalog-zones {
zone "catalog.default" default-masters { 10.154.5.163; };
};
}
zone "catalog.default" {
type slave;
file "catalog.default.zone";
masters { 10.154.5.163; }; // 主机ip
};
验证

至此完成catalog目录的配置。

1
2
3
4
5
6
7
#主机、从机都重启
systemctl restart named 或
systemctl restart isc-bind-named

#在主机上验证主从是否搭建catalog成功
dig +short @10.154.5.163 soa catalog.default
dig +short @10.154.5.162 soa catalog.default
主从机同步演示

后续只需要在主机上对zone进行操作(增删改等),从机会自动实现同步了。如下示例:

新增zone
  1. 按传统方式,在主机通过rndc动态添加一个zone。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
vim luxia.com.zone

$TTL 1D
@ IN SOA luxia.com. root.luxia.com. (
1 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS ns1.luxia.com.
NS ns2.luxia.com.
ns1 IN A 10.154.5.163
ns2 IN A 10.154.5.214
www IN A 1.1.1.1


chgrp named luxia.com.zone

rndc addzone luxia.com '{type master; file "luxia.com.zone";};'

验证

1
2
3
dig +short soa luxia.com @10.154.5.163  // 主机可以dig

dig +short soa luxia.com @10.154.5.162 // 从机还没有同步
  1. 而后,利用nsupdate命令将luxia.com加到catalog zone,从而实现把luxia.com自动同步到从机。
1
2
3
4
5
$ cat << __EOF | nsupdate
> server 10.154.5.163
> update add 49c71169601a59cbd7f56dc8a4a1cdb335bb40d2.zones.catalog.example 3600 IN PTR luxia.com
> send
> __EOF

验证一下

1
dig +short soa luxia.com @10.154.5.162 // 发现从机可以dig

且从机出现如下文件:

1
__catz___default_catalog.example_luxia.com.db

其中,产出SHA1 的方式有两种:

第一种是shell命令行:

1
2
printf '\7luxia\3com\0' | openssl sha1
// 得到(stdin)= 49c71169601a59cbd7f56dc8a4a1cdb335bb40d2

第二种是python脚本catz-add.py

1
2
#使用
./nzf.py luxia.com
1
2
3
4
5
6
7
8
#!/usr/bin/env python
#nzf.py

import dns.name # pip install dnspython
import hashlib
import sys

print(hashlib.sha1(dns.name.from_text(sys.argv[1]).to_wire()).hexdigest())

最后,上述主机操作过程,可以总结为如下python语句自动执行:

调用

1
python ./catz-add.py luxia.com

书写catz-add.py文件,使用了isc.rndcdnspython 两个核心模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/python
# catz-add.py
import sys
import os
import isc
import dns.query
import dns.update
import dns.name
import hashlib

ZONEPATH='/tmp/'
MASTER='10.53.0.1'
DNSPORT=5300
RNDCPORT=9953
RNDCALGO='sha256'
RNDCKEY='1234abcd8765'
CATZONE='catalog.example'

def add_zone(name):
# Create a stub primary file
with file('%s%s.zone' % (ZONEPATH, name), 'w') as f:
f.write('@ 3600 IN SOA . . 1 3600 3600 3600 3600\n')
f.write('@ IN A 1.1.1.1\n')
f.write('@ IN NS ns.nice.org.\n')

# Add zone to primary using RNDC
r = isc.rndc((MASTER, RNDCPORT), RNDCALGO, RNDCKEY)
response = r.call('addzone %s {type master; file "%s%s.zone";};' % (name, ZONEPATH, name))
if response['result'] != '0':
raise Exception("Error adding zone to master: %s" % response['err'])

# Update catalog zone
update = dns.update.Update(CATZONE)
hash = hashlib.sha1(dns.name.from_text(name).to_wire()).hexdigest()
update.add('%s.zones' % hash, 3600, 'ptr', '%s.' % name)
response = dns.query.tcp(update, MASTER, port=DNSPORT)
if response.rcode() != 0:
raise Exception("Error updating catalog zone: %d" % response.rcode())

add_zone(sys.argv[1])
删除zone

与新增类似,仍然借助nsupdate,先把catalog目录列表中的域名删除。

1
2
3
4
5
6
7
$ cat << __EOF | nsupdate
> server 10.154.5.163
> update delete 49c71169601a59cbd7f56dc8a4a1cdb335bb40d2.zones.catalog.example
> send
> __EOF

#备注,cat<<EOF,指定以EOF输入字符为标准输入结束(也可以任意输入OOO,ZZZ等)

再rndc方式动态删除域名。

1
rndc delzone luxia.com

验证发现,发现从机的__catz___default_catalog.example_luxia.com.db文件消失,且dig不通。

更改serial,实现记录更新同步

上述新增zone和删除zone的过程演示了对zone配置的自动维护(主机zone配置同步到了从机zone配置)。当有zone有更新时,可以自动同步了!

现在我们仍然借助nsupdate进行更新zone记录演示。

1
2
3
4
5
$ cat << __EOF | nsupdate
> server 10.154.5.163
> update add www.luxia.com 3600 IN A 1.1.1.1
> send
> __EOF

而后

1
2
3
rndc sync luxia.com // 写入磁盘文件,可以cat luxia.com.zone看到修改

rndc reload

验证,发现已经修改。

1
2
3
cat luxia.com.zone
dig +short soa luxia.com @10.154.5.162
dig +short soa luxia.com @10.154.5.163
参考
  1. Introduction to Catalog Zones (isc.org)
  2. Jan-Piet Mens :: Catalog zones in BIND 9.11 (jpmens.net)

notify

主从同步消息机制

  1. 主机修改后重启服务,会主动传送notify。
  2. 如果从机没有收到notify,则Refresh。
  3. 如果从机Refresh 不成功,则Retry。
  4. 如果从机Retry 一直不成功, 则Expire。
  5. 如果Expire也不成功,则选择放弃zone transfer。

一个zone文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$TTL 1D #缓存时间
@ IN SOA ns1.test.com. root.localhost. (# SOA(Start of Authority)
2013070814 ; serial # 版本号
60 ; refresh # 刷新时间
1H ; retry # 刷新失败,重试更新时间
1W ; expire # 刷新失败多长时间后此DNS失效时间
3H ) ; minimum # 域名记录最小生存时间。当用户DNS查询到记录后,将存在缓存中,至少过了这个时间才将缓存刷新重新查询。

NS ns1.test.com.
NS ns2.test.com.
ns1 A 1.1.1.1
ns2 A 2.2.2.2

server A 2.1.1.1
--------------
$TTL 1D
@ IN SOA 域名解析服务器NS 域名管理者的电子邮件地址,第一个'.'代表电子邮件中的'@' (# SOA(Start of Authority)

notify主动发送消息的全过程

  1. 主机主动发送变更通知。
  2. 从机接收到通知,去查询主机zone文件的SOA记录。
  3. 主机告知从机SOA记录。
  4. 从机将主机拿到的SOA记录与自己本来就同步过的SOA记录进行对比,比较SOA中的serial no是否递增更新。
  5. 如果递增更新,从机向主机发起zone transfer请求,要求zone文件传输。
  6. 主机传输zone数据给从机更新。

从图中可看到,涉及到的配置如下:

  1. notify yes; # 【开启主动通知】

  2. also-notify { 10.154.5.162; }; # 【被通知的从机ip】

  3. allow-notify { 10.154.5.163; } #从机是否接收来着该主机ip的通知,因为默认接收主机ip,所以省略了。
  4. allow-transfer { 10.154.5.162; 10.154.5.163; }; #【允许zone传输的机器列表】设定允许哪台主机和本地服务器进行zone传输。

下面一一介绍上述配置参数。

notify与 also-notify

作用于主机。notify 结合 also-notify通过三种配置方式实现不同范围的通知:

  • notify yes;
    • sends notify to all name servers in RR (except itself and SOA master)
    • notifies are sent to all servers appearing in the NS RRset (except the server identified in the MNAME field of the SOA record)
    • will send notifications to all of the published NS records for the domain。
    • The messages are sent to the servers listed in the zone’s name server records
    • besides those in your zone’s NS records docstore.mik.ua/orelly/networking_2ndEd/dns/ch10_03.htm
    • 使用notify指令會自動通知所有這個域的所有在ns記錄上的機器,also-notify指令可以用來通知所有不在ns記錄上的dns伺服器。
      還是好好看文件吧,裡面還有很多有趣的功能呢。
    • 默认值。默认情况下,master 不必明确配置 slave ips,会自动向zone的每个 NS 记录发送NOTIFY。
  • notify yes; also-notify { x.x.x.x; y.y.y.y; };
    • sends notify to x.x.x.x, y.y.y.y and all name servers in RR (except itself and SOA master).
  • notify explicit; also-notify { x.x.x.x; y.y.y.y; };
    • sends notify to just x.x.x.x, y.y.y.y => 仅向also-notify列出的ips发送通知
NS记录

其中,NS记录是指zone文件中指定的ns解析记录(不包括SOA主机名部分,如下不包括ns1.test.com部分),如下示例中包括ns1和ns2部分。如果想要包括soa部分,可以设置为notify-to-soa yes

1
2
3
4
5
6
7
8
9
10
11
12
$TTL 1D #缓存时间
@ IN SOA ns1.test.com. root.localhost. (# SOA(Start of Authority)
2013070814 ; serial # 版本号
60 ; refresh # 更新时间
1H ; retry # 更新失败,重试更新时间
1W ; expire # 更新失败多长时间后此DNS失效时间
3H ) ; minimum # 解析不到请求不予回复时间

NS ns1.test.com.
NS ns2.test.com.
ns1 A 192.168.56.104
ns2 A 192.168.56.105

但存在问题:

新建域名时候,域名无法同步到从机(因为这个zone的NS记录还没有定)。

此时对域名进行ns记录操作,主机会派发notify消息,但从机则报错如下:

1
received notify for zone 'wei01.com': not authoritative

分析原因,可能因为这个zone在从机没有(因为NS地址还不知道,域名没有同步到从机),虽然接收到了更新消息但是没法更新zone.

目前尚未找到解决办法,只能仍然采用also-notify固定从机ip地址的方式。

注意修改,also-notify { 10.154.5.162; 10.154.5.214; }; 增改ip列表之后,采用rndc reload 或者 rndc reconfig重启服务即可。

尝试失败1:

创建域名时生成既定 NS记录 ns1.example.com,

且主机配置ns1.example.com 的hosts。

发现主机根本不会发送任何notify,从机也不会接收任何notify。

也就是在zone的NS记录已经定下来,且ns记录可通过hosts解析的情况下,域名仍然没有同步到从机。

1
2
3
4
#qing.com.zone
@ 604800 IN SOA ns1.example.com. admin.example.com. 147 604800 86400 2419200 604800
@ 604800 IN NS ns1.example.com.
www 604800 IN A 1.1.1.1
1
2
3
4
5
6
vim /etc/hosts
10.154.5.162 ns1.example.com
10.154.5.214 ns3.example.com
10.154.5.163 ns2.example.com

service network restart
1
grep qing.com notify.log #啥也没有

尝试失败2:

也就是在zone的NS记录已经定下来,且ns记录配置了A地址的情况下,域名仍然没有同步到从机。

1
2
3
4
#qing.com.zone
@ 604800 IN SOA ns1.example.com. admin.example.com. 147 604800 86400 2419200 604800
@ 604800 IN NS ns1.example.com.
www 604800 IN A 1.1.1.1
1
2
3
4
5
#example.com.zone
@ 604800 IN SOA ns1 admin 147 604800 86400 2419200 604800
@ 604800 IN NS ns1
ns1 604800 IN A 10.154.5.162
www 604800 IN A 1.1.1.1
1
grep qing.com notify.log #啥也没有
also-notify【目前采用】

also-notify,可设置扩展的名字服务器IP列表,无论何时只要有更新的内容加载,都会向这个表中的IP发出NOTIFY消息。有助于zone同步到隐藏的备机服务器。also-notify 在 bind 9.9.0+ 也可支持密钥形式。

1
2
3
4
also-notify [port gp-num] [dscp gd-num] { (masters-list|IP-address )[port p-num] [dscp d-num] 
[key key-name] ; [... ;] }; [ Opt, View, Zone ] BIND 9.9+

also-notify { ip_addr [port ip_port] ; ... ] }; [ Opt, View, Zone ] Pre BIND 9.9
1
2
3
4
5
6
7
8
9
10
11
key trusted-key {
algorithm HMAC-MD5;
secret some-secret;
};
view trusted {
zone "myzone.example" {
type master;
file "trusted/db.myzone.example";
also-notify { 192.168.7.28 key trusted-key; };
};
}

参考:Understanding views in BIND 9 (isc.org)

allow-notify

作用于从机。

  • 默认接收来自主机的notify消息
  • 也可以手动配置来确定从机接受哪些ip地址的notify

allow-transfer

简介

allow-transfer 设定哪台主机允许和本地服务器进行域传输,可以设置在 zone 语句或catalog中。有两种使用方式:

  1. 通过主机IP来限制访问—— allow-transfer : {address_list | none}。这种方式需要写死从机ip地址。不方便从机扩缩。

  2. 通过事务签名:只允许带有密钥认证的DNS服务器同步数据配置文件。这种方式不需要从机ip地址,方便从机扩缩

其中,对于事务签名:

  1. 通过密钥对数据加密。如,TSIG利用密码编码来保护区域信息的传输(Zone Transfer)
  2. 可分为两类:
    • TSIG:对称方式(常用)。
    • SIGO:非对称方式。

最终,如果要实现从机的热插拔,应采用TSIG事务签名的方式,设置允许带有密钥认证的DNS服务器同步数据配置文件。

操作过程以及主从机分别负责的工作:

主备 负责工作
主机 生成DNS服务密钥(公钥+私钥),复制生成私钥文件中的key值,到一个新建文件如tansfer.key中
主机 named.conf中include引入tansfer.key文件,设置allow-transfer { key 私钥key名; };
主机 重启named服务。
至此发现从机不能同步数据
从机 复制主机的tansfer.key到从机
从机 named.conf中include引入tansfer.key文件,设置 server 主机ip地址 { keys {私钥key名; };
至此发现从机可以同步数据

主机生成密钥

dnssec-keygen命令用于生成安全的DNS服务密钥,其格式为“dnssec-keygen [参数]”

  1. -a : 加密算法,包括RSAMD5(RSA)、RSASHA1、DSA、NSEC3RSASHA1、NSEC3DSA等
  2. -b : 密钥长度,HMAC-MD5的密钥长度在1~512位之间
  3. -n : 密钥类型,可以选择ZONE或者HOST,HOST表示与主机相关
  4. dnssec-transfer:密钥名称自定义
1
2
3
4
5
6
7
8
9
10
11
#生成一个主机名称为dnssec-transfer的128位HMAC-MD5算法的密钥文件(公钥+私钥)
dnssec-keygen -a HMAC-MD5 -b 128 -n HOST dnssec-transfer
#得到Kdnssec-transfer.+157+54187

ls -al Kdnssec-transfer.+157+54187.*
#-rw------- 1 root root 59 Jun 18 16:05 Kdnssec-transfer.+157+54187.key #公钥
#-rw------- 1 root root 165 Jun 18 16:05 Kdnssec-transfer.+157+54187.private #私钥

cat Kdnssec-transfer.+157+54187.private
#复制key参数
#Key: /y7HAkwBH0KP9g9M+jADJg==

将私钥key放到一个新的文件中,并将这个文件引入到named.conf中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cd /etc/opt/isc/isc-bind/ 或 cd /etc/  #密钥验证文件在/etc目录(与named.conf同一个目录下)

vim transfer.key
key "dnssec-transfer" { #密钥名称
algorithm hmac-md5; #加密算法
secret "/y7HAkwBH0KP9g9M+jADJg=="; #私钥加密字符串
};

chown root:named transfer.key #把文件所属组改为named,降低权限
chmod 640 transfer.key

vim /etc/named.conf
include "/etc/opt/isc/isc-bind/transfer.key";
allow-transfer { key dnssec-transfer; }; #只允许拥有该密钥验证文件的人进行同步
1
2
systemctl restart named  
systemctl restart isc-bind-named

从机引用密钥

1
2
3
4
5
6
7
scp /etc/transfer.key root@从机ip地址:/etc/opt/isc/isc-bind/transfer.key

scp /etc/transfer.key root@10.154.5.214:/etc/opt/isc/isc-bind/transfer.key
scp /etc/transfer.key root@10.154.5.162:/etc/opt/isc/isc-bind/transfer.key

chown root:named transfer.key
chmod 640 transfer.key

named.conf文件:

1
2
3
4
5
6
include "/etc/opt/isc/isc-bind/transfer.key";

#不属于全局options
server 10.154.5.163 { # 主机ip地址
keys { dnssec-transfer; };
};

重启从服务器的Bind服务

1
systemctl restart isc-bind-named

发现已经同步过来了。

参考

  1. 5. Advanced DNS Features — BIND 9 documentation
  2. BIND9 named.conf Zone Transfer and Update statements (zytrax.com)

bind9.16安装配置

9.16安装

不同版本centos系统的yum源包含了不同版本的bind,各版本略有差异。

1
2
# 安装yum自带bind版本,直接执行命令即可
yum install bind bind-utils xxxxx

但如果想要忽略centos版本,直接安装最新的bind,需要做如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
cd /etc/yum.repos.d/

vim bind.repo
[copr:copr.fedorainfracloud.org:isc:bind]
name=Copr repo for bind owned by isc
baseurl=https://download.copr.fedorainfracloud.org/results/isc/bind/epel-7-$basearch/
type=rpm-md
skip_if_unavailable=True
gpgcheck=1
gpgkey=https://download.copr.fedorainfracloud.org/results/isc/bind/pubkey.gpg
repo_gpgcheck=0

enabled=1
enabled_metadata=1

yum list isc-bind*

yum install isc-bind-bind isc-bind-bind-utils isc-bind-bind-libs -y

守护进程文件位置:/etc/opt/isc/isc-bind/sysconfig/named
配置文件位置:/etc/opt/isc/isc-bind/named.conf
发现有如下内容:
options {
directory "/var/opt/isc/isc-bind/named/data";
listen-on { 127.0.0.1; };
listen-on-v6 { ::1; };
dnssec-validation auto;
};

logging {
channel default_debug {
file "named.run";
print-time yes;
severity dynamic;
};
};

尝试启动,发现成功
systemctl start isc-bind-named
systemctl enable isc-bind-named
systemctl status isc-bind-named

安装过程可能确实某些安装包,可以自行安装:

1
2
3
4
5
6
7
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/scl-utils-20130529-19.el7.x86_64.rpm

yum install scl-utils-build-20130529-19.el7.x86_64.rpm -y

# iso-codes
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/iso-codes-3.46-2.el7.noarch.rpm
yum install iso-codes-3.46-2.el7.noarch.rpm -y

安装包下载网站

  1. Iso-codes Download (APK, DEB, EOPKG, RPM, TGZ, TXZ, XZ, ZST) (pkgs.org)
  2. scl-utils-20130529-19.el7.x86_64.rpm CentOS 7 Download (pkgs.org)
  3. RPM resource telnet (rpmfind.net)

9.16配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
在物理机/etc/profile.d/⽬录下创建isc-bind-named.sh⽂件。并输⼊以下内容,保存。
然后重启物理机即可。
#!/bin/bash
source scl_source enable isc-bind

或临时方案
scl enable isc-bind bash
rndc

---------------------
rndc-confgen 配置rndc (当同时存在rndc.conf文件和rndc.key文件的时候,默认是优先读取rndc.conf)
----------------------
dnssec-keygen 配置transfer-key
----------------------
主机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#secret和algorithm等,配置到python程序中
key rndc-key {
algorithm hmac-md5;
secret "rf27GDGjr6J2rRK5Ljsq2Q==";
};

include "/etc/opt/isc/isc-bind/transfer.key";
options {
directory "/var/opt/isc/isc-bind/named/data";
listen-on port 53 { 127.0.0.1; 10.154.5.163; };
#listen-on-v6 { ::1; };
dnssec-validation auto;

allow-query { any; }; #所有都可以查询
allow-update { any; };
allow-transfer {10.154.5.163; key dnssec-transfer; }; #9.11版本不需要本机ip,但9.16必须本机ip
notify yes;
also-notify { 10.154.5.162; 10.154.5.214; };
allow-new-zones yes;
};

statistics-channels {
inet 127.0.0.1 port 8888 allow { any; };
inet 10.154.5.163 port 8889 allow { any; };
};

# 要*,any,否则python程序无法rndc
controls {
inet * port 953
allow { any; } keys { "rndc-key"; };
};

logging {
channel default_debug {
file "named.run";
print-time yes;
severity dynamic;
};
};

zone "catalog.default" {
type master;
file "catalog.default.zone";
};
1
2
named-checkconf 验证配置
named-checkzone catalog.default catalog.default.zone

注意controls配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 监听网卡(inet)
# 允许IP(allow)
# 认证使用的keys**
# 如果要*,any,则监听机器上的所有网卡\并允许所有的来源IP进行访问(带key)
controls {
inet * port 953
allow { any; } keys { "rndc-key"; };
};

# 这种限制了在局域网和本机上使用rndc,如果有多个inet需要指定监听则需要分开多条配置
controls {
inet 127.0.0.1 allow { localhost; } keys { rndckey; };
inet 192.168.1.1 port 1953 allow { 192.168.1.1; 192.168.1.2; 192.168.1.0/24;} keys { rndckey; };
};
从机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
key "rndc-key" {
algorithm hmac-sha256;
secret "bshuXqh379VDuCYQqWJY68F1rkCEsf5LLfc274USvZQ=";
};

options {
directory "/var/opt/isc/isc-bind/named/data/slaves"; # 配置文件中所有使用的相对路径,都在该配置目录下。大多数服务器的输出文件(如named.run)都缺省生成在这个目录下。
listen-on port 53 { 127.0.0.1; 10.154.5.214; 10.154.5.163; }; # 监听本机所有地址及主机地址的53端口。
#listen-on-v6 { ::1; };
dnssec-validation auto;

allow-query { any; };#设定哪个主机可以进行普通的查询。所有主机都可以进行查询。
allow-update { any; }; # 设定哪台主机允许为主域名服务器提交动态DNS更新。默认为拒绝任何主机进行更新。
allow-transfer {any;};
allow-new-zones yes;
masterfile-format text;
#用于备机
catalog-zones {
zone "catalog.default" default-masters { 10.154.5.163; };
};
};

statistics-channels {
inet 127.0.0.1 port 8888 allow { any; };
inet 10.154.5.214 port 8889 allow { any; };
};

controls {
inet 127.0.0.1 port 953
allow { 127.0.0.1; } keys { "rndc-key"; };
};

logging {
channel default_debug {
file "named.run";
print-time yes;
severity dynamic;
};
};
#用于备机
zone "catalog.default" {
type slave;
file "catalog.default.zone";
masters { 10.154.5.163; };
};

从机配置同步数据所在目录slaves

1
2
3
4
5
cd /var/opt/isc/isc-bind/named/data
mkdir slaves
chown named.named slaves

systemctl restart isc-bind-named

参考

  1. Fedora中文社区 - fdzh.org

  2. isc/bind Copr

  3. ftp方式(源码安装)下载地址:BIND-9.16.16 (linuxfromscratch.org)

日志

简介

BIND默认把日志写到/var/log/messages。如果需要更详细的日志,需要自行配置named.conf的logging模块。

参数及说明

在日志配置中主要有channel(通道)、category(类别)二种定义:

  1. channel,通道指定了应该向哪里发送日志数据——是发送给syslog,还是写在一个文件里,或是发送给named的标准错误输出,还是发送到位存储桶(bit bucket)。
    • severity,系统会记录包括该级别以及比该级别更严重的级别的所有消息。比如定义级别为error,则会记录critical和error 两个级别的信息。一般情况下,我们记录到info级别就可以了
    • print-time是设定在日志中是否需要写入【时间】
    • print-severity是设定在日志中是否需要写入【消息级别】
    • print-category是设定在日志中是否需要写入【日志类别】。
  2. category,类别规定了哪些数据需要记录
    • default :【所有categories的默认目标】default类别匹配所有未明确指定通道的类别,但是不匹配不属于任何类别的消息。这些不属于任何类别的消息属于下面列出的这些类别。
    • general 包括所有未明确分类的BIND消息。
    • client 处理客户端请求。
    • config 配置文件分析和处理。
    • database 同BIND内部数据库相关的消息,用来存储区数据和缓存记录。
    • dnssec 处理DNSSEC签名的响应。
    • lame-servers 发现错误授权。
    • network 网络操作
    • notify 异步区变动通知。
    • queries 查询日志
    • resolver 名字解析,包括对来自解析器的递归查询的处理。
    • security 认可/非认可的请求。
    • update 动态更新事件。
    • xfer-in 从远程名字服务器到本地名字服务器的区传送。
    • xfer-out 从本地名字服务器到远程名字服务器的区传送。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#named.conf
logging {
[ channel channel_name {
( file path_name
[ versions ( number | unlimited ) ]
[ size size_spec ]
| syslog syslog_facility
| stderr
| null );
[ severity (critical | error | warning | notice | info | debug [ level ] | dynamic ); ]
[ print-category yes or no; ]
[ print-severity yes or no; ]
[ print-time yes or no; ]
}; ]
[ category category_name {
channel_name ; [ channel_name ; ... ]
}; ]
...
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#named.conf
logging {
channel default_debug {
file "named.run";
print-time yes;
severity dynamic;
};

channel access_log {
file "/var/log/named/access.log" versions 100 size 100M;
severity dynamic;
print-category yes;
print-severity yes;
print-time yes;
buffered yes;
};
category default {
access_log;
};
};

一个常用参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
logging {
channel default_file {
file "/var/opt/isc/isc-bind/log/default.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel general_file {
file "/var/opt/isc/isc-bind/log/general.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel database_file {
file "/var/opt/isc/isc-bind/log/database.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel security_file {
file "/var/opt/isc/isc-bind/log/security.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel config_file {
file "/var/opt/isc/isc-bind/log/config.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel resolver_file {
file "/var/opt/isc/isc-bind/log/resolver.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel xfer-in_file {
file "/var/opt/isc/isc-bind/log/xfer-in.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel xfer-out_file {
file "/var/opt/isc/isc-bind/log/xfer-out.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel notify_file {
file "/var/opt/isc/isc-bind/log/notify.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel client_file {
file "/var/opt/isc/isc-bind/log/client.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel unmatched_file {
file "/var/opt/isc/isc-bind/log/unmatched.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel queries_file {
file "/var/opt/isc/isc-bind/log/queries.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel network_file {
file "/var/opt/isc/isc-bind/log/network.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel update_file {
file "/var/opt/isc/isc-bind/log/update.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel dispatch_file {
file "/var/opt/isc/isc-bind/log/dispatch.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel dnssec_file {
file "/var/opt/isc/isc-bind/log/dnssec.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
channel lame-servers_file {
file "/var/opt/isc/isc-bind/log/lame-servers.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};

category default { default_file; };
category general { general_file; };
category database { database_file; };
category security { security_file; };
category config { config_file; };
category resolver { resolver_file; };
category xfer-in { xfer-in_file; };
category xfer-out { xfer-out_file; };
category notify { notify_file; };
category client { client_file; };
category unmatched { unmatched_file; };
category queries { queries_file; };
category network { network_file; };
category update { update_file; };
category dispatch { dispatch_file; };
category dnssec { dnssec_file; };
category lame-servers { lame-servers_file; };
}

上述参考中把日志按照category类别进行了详细的分类,分不到/var/opt/isc/isc-bind/log/目录下不同的日志文件中。可采用如下脚本进行生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# vim namelist.txt
default.log
general.log
database.log
security.log
config.log
resolver.log
xfer-in.log
xfer-out.log
notify.log
client.log
unmatched.log
queries.log
network.log
update.log
dispatch.log
dnssec.log
lame-servers.log

bash createlog.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

printf "*************************************\n"
echo " cat file whiel read line"
cat namelist.txt |while read line
do
echo $line;

touch $line;

done

chown named.named -R ../log

参考

  1. BIND Logging - some basic recommendations (isc.org)
  2. DNS BIND9 logging Clause (zytrax.com)
  3. How to enable named/bind/DNS full logging? - Stack Overflow

keepalived

DNS BIND主从结构虽然能够实现DNS的主备,但是无法使用统一的IP对外服务。

因此,引入LVS进行负载均衡,多台DNS服务器都配置统一的VIP作为业务IP,统一对外服务。

使用VIP可以让用户不知道实际DNS的情况下进行解析,同时DNS服务器可以增加到2台以上做一个更大的群组,提高可靠性。

问题1:vip转移抢占与非抢占

1
2
3
4
5
6
7
8
9
10
11
抢占:通常如果master服务死掉后backup会变成master,但是当master服务又好了的时候,master此时会抢占VIP(因为master优先级高,会抢回来)

非抢占式:MASTER恢复后不抢占BACKUP升级为MASTER后的VIP

抢占式会多一次多余的vip切换,对业务繁忙的网站来说是不好的。所以我们要在配置文件加入nopreempt非抢占,但是这个参数只能用于state为backup,
故我们在用HA的时候最好将master和backup的state都设置成backup,优先级高的设置为nopreempt,来解决master异常恢复后再次抢占的问题。

不抢占模式,优先级则失去作用。谁先启动谁就是MASTER,失败后必须杀死当前keepalived进程,再次重启不会立即抢占资源。实际场合中推荐使用该方式而不是使用优先级的抢占模式。抢占模式会出现一些数据同步的问题。


配置非抢占后,我们要注意启动服务的顺序,【优先启动】的获取master权限,【与优先级】没有关系了。
state nopreempt priority
主机 backup 设置 100
从机 backup 不设置 95

修改M,B服务器的 state BACKUP 都为【备】类型,同时设置 nopreempt 设置为不抢夺VIP,然后先启动M服务器,M服务器会成为【主】。然后启动B服务器,由于M的优先级高【priority 100】 所以B不会抢夺VIP,这时M宕机,B成为【主】,接着M恢复正常,由于设置了nopreempt 所以M不会抢夺VIP,B继续为【主】而M为【备】。

此时即使B又故障了,M也不会抢夺回来。

问题1:

1
2
3
4
5
6
7
protocol TCP
protocol UDP
这两个,同时使用?还是用哪个?
目前调研
同时都用的:
http://archive.linuxvirtualserver.org/html/lvs-users/2004-06/msg00104.html
https://serverfault.com/questions/763195/lvs-dns-load-balancing-on-machine-with-only-1-nic

结论:同时使用。

只用UDP的,大部分中文博客

Lvs+Keepalived+Bind+web构建高可用负载均衡系统 - Fatt - 博客园 (cnblogs.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如果UDP,则只能使用rr算法
如果UDP,LVS对UPD没有自带的检测功能,需要自己用MISC_CHECK写检查脚本,用于检测失败后发送通知或重试等
MISC_CHECK检测大有两类:
一类是针对端口的检测,如检测real server的udp 53端口启用与否
一类是针对bind服务器的检测,如检测real server上bind服务器是否真的启用,且能够dig成功

# MISC_CHECK { #指定脚本监测
# misc_path "/etc/keepalived/dnscheck.sh -h 192.168.0.12"
# misc_timeout 6
}


# 已知一个内置的域名ldap.xiguacity.cn,直接dig尝试是否成功
real_server 10.1.2.104 53 {
weight 1
MISC_CHECK {
misc_path "/usr/bin/dig ldap.xiguacity.cn @10.1.2.104 +time=1 +tries=3 +fail >/dev/null"
misc_timeout 6
}
}

MISC_CHECK主要根据检查脚本返回值来判断。

1) 当脚本返回值为0,表示真实服务器正常。

2) 当脚本返回值为1,表示真实服务器故障。

3) 当脚本返回值为2-255,表示当故障时将真实服务器权重改为返回值减2。

注意当脚本返回值为2-255时需添加misc_dynamic属性才生效。

只用TCP的

增加了notify_down和notify_up对lvs进行手动检测

Load balancing DNS with keepalived | Bill Boebel (bb.co)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
virtual_server 192.168.254.100 80 {
delay_loop 6 #设置运行情况检查时间,单位是秒
lb_algo rr #设置负载调度算法,这里设置为rr,即轮询算法
lb_kind DR #设置LVS实现负载均衡的机制,有NAT、TUN、DR三个模式可选
persistence_timeout 0 #会话保持时间,单位是秒。保持客户端的请求在这个时间段内全部发到同一个真实服务器。这个选项对动态网页是非常有用的,为集群系统中的session共享提供了一个很好的解决方案。
#有了这个会话保持功能,用户的请求会被一直分发到某个服务节点,直到超过这个会话的保持时间。
#需要注意的是,这个会话保持时间是最大无响应超时时间,也就是说,用户在操作动态页面时,如果50秒内没有执行任何操作
#那么接下来的操作会被分发到另外的节点,但是如果用户一直在操作动态页面,则不受50秒的时间限制
protocol TCP #指定转发协议类型,有TCP和UDP两种

real_server 192.168.254.15 80 {
weight 1 #配置服务节点的权值,权值大小用数字表示,数字越大,权值越高,设置权值大小可以为不同性能的服务器
#分配不同的负载,可以为性能高的服务器设置较高的权值,而为性能较低的服务器设置相对较低的权值,这样才能合理地利用和分配系统资源
TCP_CHECK {
connect_port 80
connect_timeout 3 #表示3秒无响应超时
nb_get_retry 3 #表示重试次数
delay_before_retry 3 #表示重试间隔
}
}
real_server 192.168.254.16 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}

同时都用的

lvs-dns - keepalived - linux [Knowledge Base] (xbits.net)

DNS服务器LVS方式负载均衡部署与测试 - 百度文库 (baidu.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
virtual_server 192.168.130.111 53 {
delay_loop 6
lb_algo wrr
lb_kind NAT
nat_mask 255.255.255.0
protocol TCP
real_server 10.1.110.201 53 {
weight 100
TCP_CHECK {
connect_timeout 3
connect_port 53
}
}
real_server 10.1.110.203 53 {
weight 100
TCP_CHECK {
connect_timeout 3
connect_port 53
}
}
}

! dns VIP for udp connections
virtual_server 192.168.130.111 53 {
delay_loop 6
lb_algo wrr
lb_kind NAT
nat_mask 255.255.255.0
protocol UDP
real_server 10.1.110.201 53 {
weight 100
}
real_server 10.1.110.203 53 {
weight 100
}
}

基础概念:

  1. 负载均衡:多台服务器同时、分摊工作。nginx。
  2. 高可用:主机一力承担工作。当主机故障时,从机接替工作。keepalived。

两个方案的选择:

  1. 仅高可用:自建DNS常用在公司内部平台之间的调用,所以负载均衡的意义并不是太大,高可用有必要。
    • keepalived (keepalived 的高可用是通过VRRP(virtual route redundancy protocol)实现的)
  2. 负载均衡+高可用:
    • keepalived + (LVS 、HAProxy 、Nginx等负载均衡方案)

Protocol transport(维基百科Domain Name System - Wikipedia

DNS primarily uses the User Datagram Protocol (UDP) on port number 53 to serve requests.

DNS queries consist of a single UDP request from the client followed by a single UDP reply from the server.

The Transmission Control Protocol (TCP) is used when the response data size exceeds 512 bytes, or for tasks such as zone transfers. Some resolver implementations use TCP for all queries.

DNS 通常在 UDP 端口 53 和 TCP 端口 53 上侦听查询。

DNS占用53号端口,同时使用TCP和UDP协议,关键区分在于数据包大小,如果数据包小到一定程度,UDP 协议绝对最佳的选择,但是当数据包逐渐增大直到突破 512 字节以及 MTU 1500 字节的限制时,我们也只能选择使用更可靠的 TCP 协议来传输 DNS 查询和相应。

  1. TCP:DNS在区域传输的时候使用TCP协议
    • 因为数据传输传送的数据量比一个请求应答的数据量要多得多
    • TCP是一种可靠连接,保证了数据的准确性——DNS 查询由于 DNSSEC 和 IPv6 的引入迅速膨胀,需要依靠更加可靠的 TCP 协议完成数据的传输
    • 随着 DNS 查询中包含的数据不断增加,TCP 协议头以及三次握手带来的额外开销比例逐渐降低,不再是占据总传输数据大小的主要部分
  2. UDP:非区域传输时都使用UDP协议
    • DNS 查询的数据包较小、机制简单——客户端向DNS服务器查询域名(域名解析),一般返回的内容都不超过512字节,用UDP传输即可。
    • UDP 协议的额外开销小、有着更好的性能表现——UDP不用经过三次握手,这样DNS服务器负载更低,响应更快。理论上说,客户端也可以指定向DNS服务器查询时用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。

LVS 可以简单地在一组 DNS 服务器之间对 UDP 端口 53 和 TCP 端口 53 进行负载均衡,而无需设置任何持久性选项。

Keepalived 本质上是 LVS的包装器, LVS 支持 TCP 和 UDP 流量的负载平衡。 (keepalived 还包括 VRRP 和 Healthchecks,但这是题外话)幸运的是,除了 UDP 之外,DNS 服务器碰巧还侦听 TCP 连接。他们这样做是为了处理大于 512 字节的旧 RFC 限制的查询。

配置 keepalived 以负载平衡 TCP 端口 53,就像您对任何其他 TCP 端口(例如 http 或 smtp)进行负载平衡一样。然后使用keepalived的notify_up/notify_down脚本调用功能手动配置LVS,对对应的UDP端口进行负载均衡。

keepalived 高可用示意图(Keepalived 作为 LVS 的有效补充可以构建一个高可用的 LB 前端):

image-20210624200408291

High Availability diagram

imgimg

2台服务器做LVS+keepalived。其中,

  • master和一台real_server在一台服务器
  • backup和一台real_server在一台机器上

按理来说,keepalive+lvs应该部署在独立的机器上。

节点类型 主机名 IP地址 网络类型 bind主从
realserver fnc03 10.154.5.214
realserver fnc04 10.154.5.162
VIP
keepalive+lvs MASTER,VIP占用 fnc04 10.154.5.162
keepalive+lvs BACKUP fnc03 10.154.5.214
fnc05 10.154.5.163 主机

image-20210625171855513

LVS+keepalived访问网页特别慢,求解。 - 集群和高可用-Chinaunix

实现过程:

  1. 当 Master 与 Slave 均运作正常时, Master负责服务,Slave负责Standby;
  2. 当 Master 挂掉,Slave 正常时, Slave接管服务;
  3. 当 Master 恢复正常,恢复Master身份
  4. 然后依次循环。需要注意的是修改数据只能在Master修改。

安装

在线安装
1
2
3
4
5
6
7
8
9
10
11
#下载
yum install -y keepalived

#版本
keepalived --version

#当前状态
systemctl status keepalived

#设置开机自动启动
systemctl enable keepalived.service

如果下载失败,且是yum源的问题,如下可以更改yum源为aliyun。

如果只是临时使用aliyun,记得还原。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
安装base reop源
# cd /etc/yum.repos.d/
接着备份旧的配置文件
# mv CentOS-Base.repo CentOS-Base.repo_back
下载阿里源的文件
# wget -O CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

如果wget命令不生效,说明还没有安装wget工具,在备份旧的配置文件之前输入 yum -y install wget 进行安装。
安装epel repo源:
epel(RHEL 7)
# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
epel(RHEL 6)
# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
epel(RHEL 5)
# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-5.repo

清理缓存
# yum clean all

重新生成缓存
# yum makecache

更新
# yum -y update
离线安装

前提依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash

wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libcom_err-1.42.9-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libselinux-2.5-15.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/keyutils-libs-1.5.8-3.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/krb5-libs-1.15.1-50.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libkadm5-1.15.1-50.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libss-1.42.9-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/openssl-1.0.2k-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/keyutils-libs-devel-1.5.8-3.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/e2fsprogs-libs-1.42.9-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libcom_err-devel-1.42.9-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libsepol-devel-2.5-10.el7.x86_64.rpm
#wget http://mirror.centos.org/centos/7/os/x86_64/Packages/pcre-devel-8.32-17.el7.x86_64.rpm
#wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libverto-devel-0.2.5-4.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libselinux-devel-2.5-15.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/krb5-devel-1.15.1-50.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/zlib-devel-1.2.7-18.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/openssl-devel-1.0.2k-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/e2fsprogs-1.42.9-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/krb5-workstation-1.15.1-50.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/keyutils-1.5.8-3.el7.x86_64.rpm
#wget http://mirror.centos.org/centos/7/os/x86_64/Packages/openssl-libs-1.0.2k-19.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libselinux-python-2.5-15.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libselinux-utils-2.5-15.el7.x86_64.rpm


#wget http://mirror.centos.org/centos/7/os/x86_64/Packages/pkgconfig-0.27.1-4.el7.x86_64.rpm

#*** 解决这个问题:WARNING - this build will not support IPVS with IPv6
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libnl-1.1.4-3.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libnl-devel-1.1.4-3.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libnfnetlink-devel-1.0.1-4.el7.x86_64.rpm
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libnfnetlink-1.0.1-4.el7.x86_64.rpm
1
2
3
4
chmod 777 wget_pkg.sh
rpm -Uvh --force *.rpm

scp -r ./keepalived root@10.154.5.163:/data/keepalived
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#获取源码
wget https://www.keepalived.org/software/keepalived-2.2.2.tar.gz
(https://www.keepalived.org/download.html)

#解压
tar -xf keepalived-2.2.2.tar.gz
#运行配置脚本
cd keepalived-2.2.2
./configure
#构建安装keepalived
make
make install
#查看安装
keepalived --version


#完成后会在以下路径生成:
/usr/local/etc/keepalived/keepalived.conf
/usr/local/etc/sysconfig/keepalived
/usr/local/sbin/keepalived

#--------注册到系统全局-----------------
cd /data/keepalived-2.2.2/keepalived/etc

mkdir /etc/keepalived/
cp keepalived/keepalived.conf /etc/keepalived/

#keepalived启动脚本(源码目录下),放到/etc/init.d/目录下就可以使用service命令便捷调用
cp init.d/keepalived /etc/init.d/

#keepalived启动脚本变量引用文件,默认文件路径是/etc/sysconfig/
cp sysconfig/keepalived /etc/sysconfig/

#将keepalived主程序加入到环境变量/usr/sbin/目录下
cp /usr/local/sbin/keepalived /usr/sbin/

systemctl daemon-reload

# 配置keepalived.conf

#启动
systemctl start keepalived

参考

  1. keeplived离线安装openssl-devel依赖包_afreon-CSDN博客
  2. Welcome to the BCLinux Open Source Mirror. /bclinux/dcos/ldk/v7.6/os/x86_64/Packages/
常用命令
1
2
3
4
5
6
1. systemctl start keepalived.service #启动服务
2. systemctl restart keepalived.service #重启服务
3. systemctl stop keepalived.service #停止服
4. systemctl status keepalived.service #查看服务状态
5. systemctl enable keepalived.service #设置开机自动启动
6. systemctl disable keepalived.service #取消开机自动启动

配置

cd /etc/keepalived/

主机

vrrp_script 一定要放在vrrp_instance之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
! Configuration File for keepalived

global_defs {
router_id LVS_DEVEL
}

vrrp_script chk_dns {
script "/etc/keepalived/chk_dns.sh"
weight -10
interval 2
fall 2
rise 1
}

vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.154.5.2
}
nopreempt
track_script {
chk_dns
}
}

! dns bind for tcp
virtual_server 10.154.5.2 53 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP

real_server 10.154.5.162 53 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 53
}
}

real_server 10.154.5.214 53 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 53
}
}
}

! dns bind for udp
virtual_server 10.154.5.2 53 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol UDP

real_server 10.154.5.162 53 {
weight 1
MISC_CHECK {
misc_path "/usr/bin/dig catalog.default soa @10.154.5.162 +time=1 +tries=3 +fail >/dev/null"
misc_timeout 8
}
}

real_server 10.154.5.214 53 {
weight 1
MISC_CHECK {
misc_path "/usr/bin/dig catalog.default soa @10.154.5.214 +time=1 +tries=3 +fail >/dev/null"
misc_timeout 8
}
}
}
1
misc_path "/usr/bin/dig catalog.default soa @10.154.5.162 +time=1 +tries=3 +fail >/dev/null"
  1. +time=T :为查询设置超时时间为 T 秒。缺省是 5 秒。如果将 T 设置为小于 1 的数,则以 1 秒作为查询超时时间。
  2. +tries=A :设置向服务器发送 UDP 查询请求的重试次数为 A,代替缺省的 3 次。如果把 A 小于或等于 0,则采用 1 为重试次数。
  3. +fail:如果您收到 SERVFAIL,请不要尝试下一个服务器。默认是不尝试下一个服务器。

查看bind服务是否有问题,如果有则设置为vip漂移。

(此处无法用grep 端口号或者named,因为很多干扰字符串)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# vim /etc/keepalived/chk_dns.sh

#!/bin/bash
ALIVE=$(/opt/isc/isc-bind/root/usr/sbin/rndc status | grep "server is up and running")
if [ $? == 0 ];then
echo "rndc status: running"
exit 0
else
LOGFILE="/var/log/keepalived.log"
echo "---------------------------------------" >>$LOGFILE
date "+%Y-%m-%d %H:%M:%S" >>$LOGFILE
echo "Using rndc status check failed" >>$LOGFILE
echo "---------------------------------------" >>$LOGFILE
exit 1
fi
1
chmod +x /etc/keepalived/chk_dns.sh

测试vip漂移

1
2
3
4
5
6
7
rndc stop
#发现vip漂移到从机ip addr | grep eth0
#且打印日志Using rndc status check failed

systemctl restart isc-bind-named
#主机重启服务,vip不会二次漂移
#注意,此处使用systemctl restart isc-bind-named 而非 rndc restart(尚未实现)

另外,如果MISC_CHECK监测脚本(当检测UDP ip 53端口成功时,会返回一个”succeeded”字段)

1
2
#使用示例
misc_path"/etc/keepalived/udp_check53.sh 10.154.5.214 53"
1
2
3
4
5
6
#udp_check53.sh

#!/bin/bash

nc -uz -w 1 $1 $2 | grep succeeded >/dev/null
exit $?
1
chmod +x /etc/keepalived/udp_chekc53.sh

53端口,tcp和udp的策略要开启。

1
2
3
4
5
iptables -I INPUT 4 -p tcp--dport 53 -j ACCEPT

iptables -I INPUT 4 -p udp--dport 53 -j ACCEPT

service iptables save

查看调度规则

1
2
3
ipvsadm

ipvsadm -L -n

停掉和启用一台DNS服务,观察调度器

1
2
3
systemctl stop isc-bind-named

ipvsadm -L -n

DNS+keepalived+lvs实现高可用负载均衡集群_6638225的技术博客_51CTO博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
! Configuration File for keepalived

global_defs {
#邮件部分,可以忽略
notification_email {
abc@abc.com
}
notification_email_from abc@abc.com
smtp_server 192.168.200.1
smtp_connect_timeout 30

#机器节点名标识,主要用于通知,必有
router_id LVS_DR01

#可以忽略
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}

vrrp_script chk_dns {
script "/etc/keepalived/scripts/dns_check.sh" # 定义检测的脚本和执行参数
interval 2 # 定义脚本的执行时间间隔为2秒

#weight -20 # 执行失败的时候weight-20

#fall 2 # 检测到脚本执行两次失败才算失败

#rise 1 # 检测到脚本执行成功一次就算成功
}

vrrp_instance VI_BIND {
state MASTER
interface eth0
virtual_router_id 51 #主从相同
priority 100 #从服务器要低一些,否则master将失去master状态
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #单个vrrp_instance最多支持20个virtual_ipaddress。如果想要更多,则增加vrrp_instance吧!
10.20.120.150 #VIP
}
track_script {
chk_dns #通过dns_check.sh来检测服务可用性
}

notify /etc/keepalived/scripts/keepalivednotify.sh

notify_master /etc/keepalived/scripts/dns_master.sh #当进入Master状态时会呼叫notify_master
notify_backup /etc/keepalived/scripts/dns_backup.sh #当进入Backup状态时会呼叫notify_backup
notify_fault /etc/keepalived/scripts/dns_fault.sh #当发现异常情况时进入Fault状态呼叫notify_fault
notify_stop /etc/keepalived/scripts/dns_stop.sh #当Keepalived程序终止时则呼叫notify_stop
}

#############LVS################对外公开一个vip节点,内部有多个真实的服务器负责处理请求. keepalived主要用作real_server的健康状态的检查,和负责均衡主备机之间的failover的实现。当真实的服务器节点宕机,keepalived的健康检查机制检查到了宕机的服务器不能再提供服务了,keepalived就将这个节点从虚拟ip(lvs服务器)上面剔除,保证对外提供的服务能够稳健的运行。

virtual_server 10.20.120.150 53 { #VIP
delay_loop 6 # 服务轮询的时间间隔
lb_algo rr #设置 LVS 调度算法,轮询,按照请求顺序轮流分发到后端RS。rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR #设置 LVS 集群模式, DR模式(Direct Routing)【这个模式比较常用】 NAT|DR|TUN
protocol UDP # 设置健康检查用的是 TCP 还是 UDP

real_server 10.20.121.179 53 { # 真实bind主机1
weight 1 #设置给每台的权重 0 表示失效 (不知给他转发请求知道他恢复正常) 默认是 1
#TCP_CHECK { # keepalived 健康检查方式有: HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
# connect_timeout 3
# retry 3
# delay_before_retry 3
# }

# MISC_CHECK { #指定脚本监测,
# misc_path "/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.20.121.179 +time=1 +tries=5 +fail > /dev/null"
# misc_timeout 6
}
}

real_server 10.20.121.184 53 { # 真实bind备机1
weight 1
#TCP_CHECK {
# connect_port 53
# connect_timeout 3
# retry 3
# delay_before_retry 3
#}

# MISC_CHECK { #指定脚本监测
# misc_path "/usr/bin/dig -b 10.1.53.1 a resolve.test.roka.net @10.20.121.184 +time=1 +tries=5 +fail > /dev/null"
# misc_timeout 6
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#检测bind53端口是否可用,从而来证明服务可用性
# vim /etc/keepalived/scripts/dns_check.sh
#!/bin/bash
ALIVE=`netstat -ntpl |grep "53"`
if [ $? == 0 ];then
exit 0
else
exit 1
fi

#当进入Master状态时启动bind
# vim /etc/keepalived/scripts/dns_master.sh
LOGFILE="/var/log/keepalived-dns-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1
echo "Run reload cmd ..." >> $LOGFILE
systemctl restart isc-bind-named >> $LOGFILE 2>&1
echo "Running systemctl restart isc-bind-named done ! " >>$LOGFILE

#当进入Backup状态时启动bind
# vim /etc/keepalived/scripts/dns_backup.sh
LOGFILE="/var/log/keepalived-dns-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
systemctl restart isc-bind-named >> $LOGFILE 2>&1
echo "Being slave...." >> $LOGFILE 2>&1

#当发现异常情况时进入Fault状态,写入日志而已
# vim /etc/keepalived/scripts/dns_fault.sh
#!/bin/bash
LOGFILE=/var/log/keepalived-dns-state.log
echo "[fault]" >> $LOGFILE
date >> $LOGFILE

#当Keepalived程序终止时,写入日志而已
# vim /etc/keepalived/scripts/dns_stop.sh
#!/bin/bash
LOGFILE=/var/log/keepalived-dns-state.log
echo "[stop]" >> $LOGFILE
date >> $LOGFILE


#keepalivednotify.sh
#!/bin/bash

TYPE=$1
NAME=$2
STATE=$3

case $STATE in
"MASTER") /etc/init.d/apache2 start
exit 0
;;
"BACKUP") /etc/init.d/apache2 stop
exit 0
;;
"FAULT") /etc/init.d/apache2 stop
exit 0
;;
*) echo "unknown state"
exit 1
;;
esac

给5个脚本都加上可执行权限:

1
chmod +x /etc/keepalived/scripts/*.sh

启动keepalived

1
systemctl restart keepalived

验证

1
netstat -ntpl |grep 53

模拟master挂掉(关闭master服务),查看vip的漂移情况。

1
ip addr show eth0

主从机器的named.conf都需要增加VIP,确保主从named.conf配置文件中的监听网卡和端口覆盖了本机IP和VIP。

1
listen-on port 53 { 127.0.0.1; 10.154.5.163; VIP; }; #增加VIP
备机

与主机基本一致,除了以下参数

1
2
3
state BACKUP
priority 95 #从服务器要低一些
nopreempt #没有

####

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
! Configuration File for keepalived

global_defs {
router_id LVS_DEVEL
}

vrrp_script chk_dns {
script "/etc/keepalived/chk_dns.sh"
weight -10
interval 2
fall 3
rise 1
}

vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 95
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.154.5.2
}
track_script {
chk_dns
}
}

! dns bind for tcp
virtual_server 10.154.5.2 53 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP

real_server 10.154.5.162 53 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 53
}
}

real_server 10.154.5.214 53 {
weight 1
TCP_CHECK {
connect_timeout 3
connect_port 53
}
}
}

! dns bind for udp
virtual_server 10.154.5.2 53 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol UDP

real_server 10.154.5.162 53 {
weight 1
MISC_CHECK {
misc_path "/usr/bin/dig catalog.default soa @10.154.5.162 +time=1 +tries=3 +fail >/dev/null"
misc_timeout 8
}
}

real_server 10.154.5.214 53 {
weight 1
MISC_CHECK {
misc_path "/usr/bin/dig catalog.default soa @10.154.5.214 +time=1 +tries=3 +fail >/dev/null"
misc_timeout 8
}
}
}

tcpdump

1
2
3
tcpdump udp port 53

tcpdump -i eth0

tcpdump抓包命令详解 - 知乎 (zhihu.com)

ipvsadm

CentOS 7已经包含LVS内核,只要安装LVS控制器ipvsadm.

ipvsadm可以查看lvs规则是否建立

1
2
3
-L|-l(–list):显示内核虚拟服务器表

-n(–numeric):输出IP 地址和端口的数字形式
1
2
3
4
Forward 转发方式,当前是路由转发
Weight 权重
ActiveConn 当前活跃的连接数
InActConn 当前不活跃的连接数
1
2
3
4
5
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/ipvsadm-1.27-8.el7.x86_64.rpm

yum install -y ipvsadm-1.27-8.el7.x86_64.rpm

#在线安装 yum install -y ipvsadm
1
2
3
4
5
6
7
8
9
查看调度情况
#ipvsadm -lcn

IPVS connection entries
pro expire state source virtual destination
UDP 03:03 UDP 10.154.5.2:42601 10.154.5.2:53 10.154.5.162:53
UDP 04:00 UDP 10.154.5.2:39982 10.154.5.2:53 10.154.5.214:53

#ipvsadm –lcn | grep 192.168.1.115
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ipvsadm

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP fnc04:https rr
-> fnc04:sun-sr-https Masq 1 0 0
TCP fnc04:domain rr
-> 100.92.165.194:domain Masq 1 0 0
-> 100.92.165.195:domain Masq 1 0 0
TCP fnc04:9153 rr
-> 100.92.165.194:9153 Masq 1 0 0
-> 100.92.165.195:9153 Masq 1 0 0
UDP fnc04:domain rr
-> 100.92.165.194:domain Masq 1 0 0
-> 100.92.165.195:domain Masq 1 0 0
UDP fnc04:domain rr
-> fnc04:domain Route 1 0 0
-> fnc03:domain Route 1 0 1

查看VIP是否已经成功映射到两台real服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ipvsadm -L -n

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.96.0.1:443 rr
-> 10.154.5.162:6443 Masq 1 0 0
TCP 10.96.0.10:53 rr
-> 100.92.165.194:53 Masq 1 0 0
-> 100.92.165.195:53 Masq 1 0 0
TCP 10.96.0.10:9153 rr
-> 100.92.165.194:9153 Masq 1 0 0
-> 100.92.165.195:9153 Masq 1 0 0
UDP 10.96.0.10:53 rr
-> 100.92.165.194:53 Masq 1 0 0
-> 100.92.165.195:53 Masq 1 0 0
UDP 10.154.5.2:53 rr
-> 10.154.5.162:53 Route 1 0 0
-> 10.154.5.214:53 Route 1 0 1

ipvsadm默认超时时间

1
2
3
# ipvsadm -L --timeout
Timeout (tcp tcpfin udp): 900 120 300
#单位秒 15分钟 2分钟 5分钟

900 120 300这三个数值分别是TCP TCPFIN UDP的时间.也就是说一条tcp的连接经过lvs后,lvs会把这台记录保存15分钟,就是因为这个时间过长,所以很多人都会发现做好LVS DR之后轮询现象并没有发生,实践中将此数值调整很小小,使用以下命令调整:

1
ipvsadm --set 1 2 1

Clear the LVS settings first because it is controled by Keepalived.

1
ipvsadm -C

telnet

查看是否安装

1
2
3
4
5
rpm -qa | grep xinetd

rpm -qa | grep telnet

rpm -qa | grep telnet-server
1
2
3
4
5
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/xinetd-2.3.15-14.el7.x86_64.rpm

wget http://mirror.centos.org/centos/7/os/x86_64/Packages/telnet-server-0.17-65.el7_8.x86_64.rpm

wget http://mirror.centos.org/centos/7/os/x86_64/Packages/telnet-0.17-65.el7_8.x86_64.rpm

telnet-server服务启动依赖xinetd服务,需要首先安装,如果telnet-server服务在xinetd之前安装了,要先删除telnet-server,再安装xinetd。

安装顺序:xinetd–>telnet–>telnet-server。

1
2
3
rpm -ivh xinetd-2.3.15-14.el7.x86_64.rpm
rpm -ivh telnet-0.17-65.el7_8.x86_64.rpm
rpm -ivh telnet-server-0.17-65.el7_8.x86_64.rpm

再次查看发现已经安装了。

1
2
3
4
5
6
7
8
9
10
#安装完成后,将xinetd服务加入开机自启动:
systemctl enable xinetd.service

#将telnet服务加入开机自启动:
systemctl enable telnet.socket

#重启服务
#因telnet服务也是由xinetd守护的,所以安装完telnet-server,要启动telnet服务就必须重新启动xinetd 。
systemctl start telnet.socket
systemctl start xinetd(或service xinetd start)

测试vip

1
telnet 10.154.5.2 53

用户程序

用户访问时,访问的是VIP

1
2


参考

  1. BIND + LVS + Keepalived 搭建内网DNS集群-分区域响应结果,可做智能解析 | 码农家园 (codenong.com)
  2. keepalived 仅高可用 Centos下高可用主从同步DNS服务部署_亮公子的技术博客_51CTO博客
  3. keepalived 仅高可用 How to Setup IP Failover with KeepAlived on Ubuntu & Debian - TecAdmin
  4. LVS + keepalived Ubuntu 16.04 LTS : LVS + Keepalived : Server World (server-world.info)
  5. LVS+Keepalived Build DNS HA LB Cluser (more higher HA) (atomicgain.com)
  6. DNS + LVS Building Scalable DNS Cluster using LVS - LVSKB (linuxvirtualserver.org)
  7. keepalived+lvs+负载均衡的windows实现_夏的博客-CSDN博客
  8. DNS系列之bind篇01-Bind+Keepalived安装高可用DNS集群 - TinyChen’s Studio
  9. How ClusterControl Configures Virtual IP and What to Expect During Failover | Severalnines
  10. How To Set Up Highly Available HAProxy Servers with Keepalived and Floating IPs on Ubuntu 14.04 | DigitalOcean
  11. ck :: Unbound DNS server behind a VIP - solving reply from unexpected source (claudiokuenzler.com)

性能监控

Bind基本配置

用于获取监控数据

vim /etc/opt/isc/isc-bind/named.conf

1
2
3
4
statistics-channels {
inet 127.0.0.1 port 8888 allow { any; };
inet 10.154.5.162 port 8889 allow { any; };
};

打开浏览器访问10.154.5.162:8889

注意端口号8889

bind_exporter

用于图形化展现。

bind_exporter基于statistics-channels记录的统计数据,并对数据统计分析并输出到Prometheus

下载

查看linux版本

1
2
# cat /proc/version
Linux version 3.10.0-1127.18.2.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Sun Jul 26 15:27:06 UTC 2020

根据版本下载

https://github.com/prometheus-community/bind_exporter/releases

如上图,linux是86_64,则下载版本

bind_exporter-0.4.0.linux-amd64.tar.gz

配置

解压到/usr/local/bin/

1
2
3
4
5
6
7
 
tar -xvf bind_exporter-0.4.0.linux-amd64.tar.gz

cd /usr/local/bin/
-rwxr-xr-x 1 3434 3434 15762489 Jan 14 22:55 bind_exporter
-rw-r--r-- 1 3434 3434 11357 Jan 14 23:57 LICENSE
-rw-r--r-- 1 3434 3434 252 Jan 14 23:57 NOTICE

创建⼀个systemd配置⽂件以运⾏bind_exporter

  1. –web.listen-address为对外暴露的metric地址和端⼝,Prometheus从此处抓取bind_exporter的metrics;即对外提供数据的端口。
  2. – bind.stats-url为本地bind服务绑定的地址和IP。即获取bind数据的地址。

注意此处的⽤⼾和组可以使⽤与named程序相同的⽤⼾和组“named”,也可 以使⽤root。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
vim /etc/systemd/system/bind_exporter.service

[Unit]
Description=bind_exporter
Documentation=https://github.com/prometheus-community/bind_exporter
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=root
Group=root
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/bind_exporter \
--bind.pid-file=/var/opt/isc/isc-bind/run/named/named.pid \
--bind.timeout=20s \
--web.listen-address=0.0.0.0:9154 \
--web.telemetry-path=/metrics \
--bind.stats-url=http://10.154.5.162:8889/ \
--bind.stats-groups=server,view,tasks
Restart=always
[Install]
WantedBy=default.target

注意端口号9154

加载并启动bind_export

1
2
systemctl daemon-reload
systemctl restart bind_exporter.service

Prometheus Server

Prometheus基于Go编写,编译后的软件包,不依赖于任何的第三⽅依赖。只需要下载对应平台的⼆进制包,解压并且添加基本 的配置即可正常启Prometheus Server。

Prometheus Server负责定时在目标上抓取Metrics数据,每个抓取目标都需要暴露一个HTTP服务接口用于Prometheus定时抓取。

这种调用被监控对象获取监控数据的方式被称为Pull。Pull方式体现了Prometheus独特的设计哲学与大多数采用了Push方式的监控系统不同。

但某些现有系统是通过push方式实现的,为了接入这个系统,Prometheus提供对PushGateway的支持,这些系统主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。

AlertManager是独立于Prometheus的一个组件,在触发了预先设置在Prometheus中的高级规则后,Prometheus便会推送告警信息到AlertManager。

根据版本下载:

Download | Prometheus

1
2
3
tar -xf prometheus-2.27.1.linux-amd64.tar.gz
mv prometheus-2.27.1.linux-amd64 /usr/local/
ln -s /usr/local/prometheus-2.27.1.linux-amd64/ /usr/local/prometheus

创建Prometheus的⽤⼾(此处用户prometheus)及数据存储⽬录(/data/prometheus)

1
2
3
4
5
# useradd -s /sbin/nologin -M prometheus
# mkdir /data/prometheus -p
#修改⽬录属主
# chown -R prometheus:prometheus /usr/local/prometheus/
# chown -R prometheus:prometheus /data/prometheus/

配置/usr/local/prometheus/promethes.yml

1
cp prometheus.yml prometheus.yml-default #备份一下默认配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets: ["localhost:9093"]
# - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090'] #浏览器访问9090打开管理界面

- job_name: 'bind-fnc04'
scrape_interval: 5s
static_configs:
- targets: ['10.154.5.162:9154'] #监听bind_exporter

默认启动后的端口为9090。

启动方式1

1
2
3
cd /usr/local/prometheus
./prometheus --version
./prometheus &

启动方式2

1
2
3
4
5
6
7
8
9
10
11
12
13
vim /etc/systemd/system/prometheus.service

[Unit]
Description=Prometheus
Documentation=https://prometheus.io/
After=network.target
[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml --storage.tsdb.path=/data/prometheus
Restart=on-failure
[Install]
WantedBy=multi-user.target

如此可以用命令启动服务

1
2
3
systemctl daemon-reload
systemctl enable prometheus
systemctl start prometheus

浏览器访问http://10.154.5.162:9090/targets

Grafana

一个数据分析统计可视化报表,⽤来展⽰ prometheus收集到的数据

Grafana+Prometheus的详解以及使用 - 知乎 (zhihu.com)

下载

1
wget https://dl.grafana.com/oss/release/grafana-7.5.7.linux-amd64.tar.gz
1
2
3
tar -xzvf grafana-7.5.7.linux-amd64.tar.gz
mv grafana-7.5.7 /usr/local/
ln -s /usr/local/grafana-7.5.7/ /usr/local/grafana

创建grafana⽤⼾及数据存放⽬录

1
2
3
4
useradd -s /sbin/nologin -M grafana
mkdir /data/grafana
chown -R grafana:grafana /usr/local/grafana/
chown -R grafana:grafana /data/grafana

修改目录

1
2
3
4
5
6
7
8
 cd /usr/local/grafana/conf/
cp defaults.ini defaults.ini-default 先备份

vim defaults.ini
data = /data/grafana/data
logs = /data/grafana/log
plugins = /data/grafana/plugins
provisioning = /data/grafana/conf/provisioning

新增 grafana-server.service ⽂件,使⽤systemd来管理grafana服务

1
2
3
4
5
6
7
8
9
10
11
12
13
vim /etc/systemd/system/grafana-server.service

[Unit]
Description=Grafana
After=network.target
[Service]
User=grafana
Group=grafana
Type=notify
ExecStart=/usr/local/grafana/bin/grafana-server -homepath /usr/local/grafana
Restart=on-failure
[Install]
WantedBy=multi-user.target
1
2
3
systemctl start grafana-server
systemctl status grafana-server
systemctl enable grafana-server

打开浏览器访问

http://10.154.5.162:3000/login

默认的账号密码 admin/admin

把grafana和prometheus关联起来,也就是在 grafana中添加添加数据源——

在配置⻚⾯点击添加数据源,然后选择prometheus,输⼊prometheus服务的参数即可。

Grafana三种方式导入Dashboard

参考:

  1. Grafana三种方式导入Dashboard_y368769的博客-CSDN博客_grafana import
  2. https://grafana.com/grafana/dashboards

Node Exporter

https://prometheus.io/download/

采集主机的运⾏指标如CPU,内存,磁盘等信息。可以使⽤Node Exporter

1
wget https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-amd64.tar.gz
1
2
3
4
5
6
ln -s  node_exporter-1.1.2.linux-amd64/  node_exporter

启动,默认会启动9100端⼝
nohup /usr/local/prometheus_exporter/node_exporter/node_exporter >/dev/null 2>&1 &

/usr/local/prometheus_exporter/node_exporter/node_exporter

开机启动

1
nohup /usr/local/prometheus_exporter/node_exporter/node_exporter >/dev/null 2>&1 &
加入prometheus

编辑prometheus.yml⽂件,增加后⾯4⾏.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090']

- job_name: 'bind-fnc04'
scrape_interval: 5s
static_configs:
- targets: ['10.154.5.162:9154'] #监听bind_exporter


- job_name: 'node'
static_configs:
- targets: ['localhost:9100']

重启

1
systemctl restart prometheus.service

存疑

dns bind Catalog zone notify yes 无法主动同步新建域名的zone(主机没有主动发送新建zone的消息,导致zone更新解析记录等时虽然发消息但从机同步失败)

其他概念

IXFR与AXFR

  1. 增量区传送(Incremental Zone Transfer,IXFR):
    • zone很大的话,zone传送需要一定的时间,IXFR是为了解决这个问题,它允许辅名字服务器告诉主名字服务器当前使用的区的版本,并仅仅请求传送它使用的版本和当前版本之间改动过的部分。这样就大大减少了区传送的大小和所需的时间。
    • 但是存在的问题比较多,如果最大限度的利用IXFR,最好动态更新修改区而不是手工编辑区数据文件。
    • 通过IXFR区域传输时,区域的复制版本和源区域之间的差异必须首先确定。如果该区域复制源DNS服务器的序号与申请同步复制的DNS服务器该区域的序列号所指示的版本相同,则不进行任何传送;如果复制源DNS服务器的序列号比申请同步复制的DNS服务器对应区域的序列号大,则传送的内容仅由区域中每个递增版本的资源记录的改动组成。
  2. 全量区传送(Full Zone Transfer,AXFR):默认,完全区域传输查询来完全传送整个区域数据。

PowerDNS

notify-to-soa

Normally a NOTIFY message is not sent to the SOA MNAME (SOA ORIGIN) as it is supposed to contain the name of the ultimate master.

1
2
3
4
5
cat /etc/named.conf
options {
..........
notify-to-soa yes;
};

view

mastert利用view进行分界,针对不同查询来源IP,返回不同DNS答案。

  1. BIND 9 利用 TSIG KEY 实现主从服务器多 view 同步说法语的猪新浪博客 (sina.com.cn)

  2. 多个view的时候使用nsupdate更新记录 | GNUer’s blog (gnuers.org)

  3. bind主备同步的关键配置 | GNUer’s blog (gnuers.org)
  4. bind多个view的主备同步 | GNUer’s blog (gnuers.org)

主从机介绍 Chapter 4 DNS Configuration Types (zytrax.com)

  1. 假设您想将主服务器隐藏,那么至少一个从服务器将位于防火墙或类似配置的公共端,提供外围防御(defence)
  2. 为了提供弹性(resilience),您需要两个或更多这样的公共slave(第二个slave可以从master获取数据,也可以从另一个slave(称为’boss’ slave)中)
  3. 这种类型的配置将略微增加更新第二个从站上的区域的延迟 - 但这可能会被增加的隐蔽性抵消。
  4. 在 DNSSEC 环境中,master 可能会拥有各种与保持密钥安全有关的配置。而 DNSSEC 从站只是简单地发送区域文件中的数据来响应查询,并且没有安全密钥维护的要求。在这种环境中,隐藏的主配置将越来越成为常态。
-------------Keep It Simple Stupid-------------
0%