@adonia
2018-05-25T06:19:43.000000Z
字数 12663
阅读 303
nginx
Note:
--prefix=/opt/nginx/keepalived指定keepalived的安装目录
--disable-lvs-syncd --disable-lvs表示禁用LVS功能,使用keepalived自带的vrrp协议创建和切换浮动IP
安装后的目录结构如下:
/opt/nginx/keepalived|--bin\--etc|--keepalived|--keepalived.conf\--rc.d|--init.d|--keepalived\--sysconfig|--keepalived\--sbin|--keepalived
Note:
etc/keepalived/keepalived.conf为keepalived的默认配置文件
etc/rc.d/init.d/keepalived为keepalived给出的默认启动脚本
etc/sysconfig/keepalived为keepalived的启动参数定义,可以参照默认启动脚本
sbin/keepalived为keepalived的启动引导程序
新建keepalived_ctl脚本,放置在$KEEPALIVED_HOME/bin目录下,用于控制keepalived的启停,如下:
#!/bin/shBIN=$(cd $(dirname "$0"); pwd)KEEPALIVED=$(cd $(dirname "$BIN"); pwd)PATH=$KEEPALIVED/sbin:$PATHPID_FILE=$KEEPALIVED/run/keepalived.pidVRRP_PID=$KEEPALIVED/run/vrrp.pidCHECKER_PID=$KEEPALIVED/run/checker.pidDAEMON=$(which keepalived)CONFIG=$KEEPALIVED/etc/keepalived/keepalived.confRETVAL=0# RETVAL = 0 if running, != 0 if stoppedstatus_keepalived() {if [ -f "${PID_FILE}" ]; thenRETVAL=0for pid in $(cat "${PID_FILE}"); dokill -0 "${pid}" > /dev/null 2>&1 || RETVAL=3donekill -0 $(cat "${PID_FILE}") > /dev/null 2>&1if [ $? != 0 ]; thenRETVAL=3fielseRETVAL=1fi}ensure_dir() {local dir=$KEEPALIVED/runif [ ! -d $dir ]; thenmkdir -p $dirfi}start_keepalived() {status_keepalivedif [ "${RETVAL}" = 0 ]; thenecho "Keepalived is currently running"elseRETVAL=0echo "Starting Keepalived"ensure_dir"${DAEMON}" -f "${CONFIG}" -l -D -d -S 0 -p "${PID_FILE}" -r "${VRRP_PID}" -c "${CHECKER_PID}"<&-RETVAL=$?case "${RETVAL}" in0)echo "Finished starting Keepalived"echo "SUCCESS";;*)echo "Errored starting Keepalived"remove_pidecho "FAILED - check logs"RETVAL=1;;esacfi}stop_keepalived() {status_keepalivedif [ "${RETVAL}" = 0 ]; thenfor pid in $(cat "${PID_FILE}"); dokillproc -p ${pid} -t 10 ${DAEMON} || RETVAL=$?doneset -eif [ "${RETVAL}" = 0 ]; thenremove_pidelseecho "FAILED - check logs"fielseecho "Keepalived Manage not running"fi}remove_pid() {rm -f "${PID_FILE}"}case "$1" instart)start_keepalived;;stop)echo "Stopping Keepalived..."stop_keepalived;;status)status_keepalived;;force-reload|reload|restart)echo -n "Restarting Keepalived: "restart_keepalived;;*)echo "Usage: $0 {start|stop|restart|reload|force-reload}" >&2RETVAL=1;;esacexit "${RETVAL}"
上述脚本中,指定了keepalived引用的配置文件为${ALIVED_HOME}/etc/keepalived/keepalived.conf,
http://3ms.huawei.com/hi/group/1503825/wiki_2984117.html
keepalived是使用的syslog-ng作为日志记录载体,Linux中常见的系统日志像/var/log/messages、/var/log/localmessages等都是通过syslog控制的。
关于Suse Linux上的日志控制,有三个版本的实现---syslog、rsyslog和syslog-ng,参考之间的区别。
Suse Linux系统上syslog的启动可以通过service syslog start的方式,但是需注意下,这里的syslog可能是上述三种的任一种。服务的控制脚本如下(部分):
. /etc/sysconfig/syslogBINDIR=/sbin# update $SYSLOG_DAEMON if not up-to-datetest -n "$SYSLOG_DAEMON" && \test -x "${BINDIR}/$SYSLOG_DAEMON" || {for SYSLOG_DAEMON in rsyslogd syslog-ng syslogd ; dotest -x "${BINDIR}/$SYSLOG_DAEMON" && breakdone}# set daemon dependent variablesrsocks=""start_klogd=yescase "$SYSLOG_DAEMON" inrsyslogd)syslog=rsyslogdmkdir -p -m 0750 /var/run/rsyslogif test "$2" = "early" ; thenconfig=/etc/rsyslog.early.confelseconfig=/etc/rsyslog.confficompat=${RSYSLOGD_COMPAT_VERSION:-${RSYSLOGD_NATIVE_VERSION}}params="-c ${compat:-3} -f $config $RSYSLOGD_PARAMS"rsocks="/var/run/rsyslog/additional-log-sockets.conf"test -r "$config" && \while read one two rest ; dotest "x$one" = 'x$ModLoad' && \test "x$two" = 'ximklog.so' && {start_klogd=nobreak}done < $config;;syslog-ng)syslog=syslog-ngconfig=/etc/syslog-ng/syslog-ng.confparams="$SYSLOG_NG_PARAMS";;*)syslog=syslogdconfig=/etc/syslog.confparams="$SYSLOGD_PARAMS";;esac
Note:
从第8行可以看出,服务的选取方式是依次检测
sbin目录下,是否包含rsyslogd、syslog-ng或者syslogd(三种日志服务的daemon程序),检测到的第一个即为所使用的系统日志服务。测试所用的Suse Linux(Linux version 3.0.76-0.11-default),其上使用的
syslog-ng,从39行可以看出其配置文件为/etc/syslog-ng/syslog-ng.conf。具体脚本见
/etc/init.d/syslog。
看下/etc/syslog-ng/syslog-ng.conf中的配置,大体如下:
## Global options.#options { long_hostnames(off); sync(0); perm(0640); stats(3600); };## 'src' is our main source definition. you can add# more sources driver definitions to it, or define# your own sources, i.e.:##source my_src { .... };#source src {## include internal syslog-ng messages# note: the internal() soure is required!#internal();## the default log socket for local logging:#unix-dgram("/dev/log");## uncomment to process log messages from network:##udp(ip("0.0.0.0") port(514));};## Filter definitions#filter f_local { facility(local0, local1, local2, local3,local4, local5, local6, local7); };## Some boot scripts use/require local[1-7]:#destination localmessages { file("/var/log/localmessages"); };log { source(src); filter(f_local); destination(localmessages); };
分为五个模块---options、source、filter、destination和log。
options定义的是全局配置,详细配置如下:
options { long_hostnames(off); sync(0); perm(0640); stats(3600); };更多选项如下chain_hostnames(yes|no) # 是否打开主机名链功能,打开后可在多网络段转发日志时有效long_hostnames(yes|no) # 是chain_hostnames的别名,已不建议使用keep_hostname(yes|no) # 是否保留日志消息中保存的主机名称use_dns(yes|no) # 是否打开DNS查询功能,use_fqdn(yes|no) # 是否使用完整的域名check_hostname(yes|no) # 是否检查主机名有没有包含不合法的字符bad_hostname(regexp) # 可通过正规表达式指定某主机的信息不被接受dns_cache(yes|no) # 是否打开DNS缓存功能dns_cache_expire(n) # DNS缓存功能打开时,一个成功缓存的过期时间dns_cache_expire_failed(n) # DNS缓存功能打开时,一个失败缓存的过期时间dns_cache_size(n) # DNS缓存保留的主机名数量create_dirs(yes|no) # 当指定的目标目录不存在时,是否创建该目录dir_owner(uid) # 目录的UIDdir_group(gid) # 目录的GIDdir_perm(perm) # 目录的权限,使用八进制方式标注,例如0644owner(uid) # 文件的UIDgroup(gid) # 文件的GIDperm(perm) # 文件的权限,同样,使用八进制方式标注gc_busy_threshold(n) # 当syslog-ng忙时,其进入垃圾信息收集状态的时间一旦分派的对象达到这个数字,syslog-ng就启动垃圾信息收集状态。默认值是:3000。gc_idle_threshold(n) # 当syslog-ng空闲时,其进入垃圾信息收集状态的时间一旦被分派的对象到达这个数字,syslog-ng就会启动垃圾信息收集状态,默认值是:100log_fifo_size(n) # 输出队列的行数log_msg_size(n) # 消息日志的最大值(bytes)mark(n) # 多少时间(秒)写入两行MARK信息供参考,目前没有实现stats(n) # 多少时间(秒)写入两行STATUS信息,默认值是:600sync(n) # 缓存多少行的信息再写入文件中,0为不缓存,局部参数可以覆盖该值。time_reap(n) # 在没有消息前,到达多少秒,即关闭该文件的连接time_reopen(n) # 对于死连接,到达多少秒,会重新连接use_time_recvd(yes|no) # 宏产生的时间是使用接受到的时间,还是日志中记录的时间;建议使用R_的宏代替接收时间,S_的宏代替日志记录的时间,而不要依靠该值定义。
source定义了日志源,详细配置如下:
source s_name { internal(); unix-dgram("/dev/log"); udp(ip("0.0.0.0") port(514)); };file (filename) # 从指定的文件读取日志信息unix-dgram (filename) # 打开指定的SOCK_DGRAM模式的unix套接字,接收日志消息unix-stream (filename) # 打开指定的SOCK_STREAM模式的unix套接字,接收日志消息udp ( (ip),(port) ) # 在指定的UDP端口接收日志消息tcp ( (ip),(port) ) # 在指定的TCP端口接收日志消息sun-streams (filename) # 在solaris系统中,打开一个(多个)指定的STREAM设备,从其中读取日志消息internal() # syslog-ng内部产生的消息pipe(filename),fifo(filename) # 从指定的管道或者FIFO设备,读取日志信息
filter定义日志输出的过滤器,详细配置如下:
filter f_name { not facility(news, mail) and not filter(f_iptables); };更多规则函数如下facility(..) # 根据facility(设备)选择日志消息,使用逗号分割多个facilitylevel(..) # 根据level(优先级)选择日志消息,使用逗号分割多个level,或使用“..”表示一个范围program(表达式) # 日志消息的程序名是否匹配一个正则表达式host(表达式) # 日志消息的主机名是否和一个正则表达式匹配match(表达式) # 对日志消息的内容进行正则匹配filter() # 调用另一条过滤规则并判断它的值定义规则的时候也可以使用逻辑运算符and or not
Tips:
filter中支持正则表达式进行匹配,支持逻辑运算符---not、or和and。
destination定义了日志输出的目的,详细配置如下:
destination d_name { file("/var/log/messages"); };更多动作如下file (filename) # 把日志消息写入指定的文件unix-dgram (filename) # 把日志消息写入指定的SOCK_DGRAM模式的unix套接字unix-stream (filename) # 把日志消息写入指定的SOCK_STREAM模式的unix套接字udp (ip),(port) # 把日志消息发送到指定的UDP端口tcp (ip),(port) # 把日志消息发送到指定的TCP端口usertty(username) # 把日志消息发送到已经登陆的指定用户终端窗口pipe(filename),fifo(filename) # 把日志消息发送到指定的管道或者FIFO设备program(parm) # 启动指定的程序,并把日志消息发送到该进程的标准输入
可以看出,日志的输出目标可以是文件系统,也可以是远程服务。
log则是日志输出触发器,格式如下:
log { source(s_name); filter(f_name); destination(d_name);};
Tips:
filter可选。
既然keepalived中是使用syslog来记录日志的,那就可以看下如何输出keepalived的日志。
再看下keepalived的日志脚本(keepalived_ctl),第46行,内容如下:
"${DAEMON}" -f "${CONFIG}" -l -D -d -S 0 -p "${PID_FILE}" -r "${VRRP_PID}" -c "${CHECKER_PID}"<&-
查看下keepalived的启动帮助:
Usage: ./keepalived [OPTION...]-f, --use-file=FILE Use the specified configuration file-P, --vrrp Only run with VRRP subsystem-C, --check Only run with Health-checker subsystem-l, --log-console Log messages to local console-D, --log-detail Detailed log messages-S, --log-facility=[0-7] Set syslog facility to LOG_LOCAL[0-7]-X, --release-vips Drop VIP on transition from signal.-V, --dont-release-vrrp Don't remove VRRP VIPs and VROUTEs on daemon stop-I, --dont-release-ipvs Don't remove IPVS topology on daemon stop-R, --dont-respawn Don't respawn child processes-n, --dont-fork Don't fork the daemon process-d, --dump-conf Dump the configuration data-p, --pid=FILE Use specified pidfile for parent process-r, --vrrp_pid=FILE Use specified pidfile for VRRP child process-c, --checkers_pid=FILE Use specified pidfile for checkers child process-v, --version Display the version number-h, --help Display this help message
可以看出启动参数中的-S 0即指明了输出到syslog日志管道的路径入口---local0。
Note:
local0-local7为syslog提供给用户自定义的日志输出管道,用于记录本地进程的日志信息。也就是你可以在启动脚本中,随意指定0~7中的任一个。但是为了精确得到keepalived的日志,还是要规划好。
按照上述keepalived的启动脚本定义来看,只需要在syslog中,将local0中的日志输出到指定的文件即可了。
在/etc/syslog-ng/syslog-ng.conf中增加如下配置:
# 指定keepalived的日志过滤filter f_keepalived { facility(local0); };# 指定keepalived的日志输出至'/opt/nginx/log/keepalived.log'destination d_keepalived { file("/opt/nginx/log/keepalived.log"); };log { source(src); filter(f_keepalived); destination(d_keepalived); };
Note: 注意格式,尤其是
;
重启syslog---service syslog restart。
使用root用户执行keepalived_ctl start,启动keepalived服务。查看/opt/nginx/log目录,发现其下没有定义的keepalived.log日志文件。再查看下/var/log/localmessages,日志内容如下:
un 6 11:13:17 NKG1000009441 Keepalived[95840]: Starting Keepalived v1.2.20 (05/19,2016)Jun 6 11:13:17 NKG1000009441 Keepalived[95841]: Starting VRRP child process, pid=95842Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Registering Kernel netlink reflectorJun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Registering Kernel netlink command channelJun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Registering gratuitous ARP shared channelJun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Opening file '/opt/nginx/keepalived/etc/keepalived/keepalived.conf'.Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: VRRP_Instance(NGINX_1) removing protocol VIPs.Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: ------< Global definitions >------Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Router ID = LVS_DEVELJun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: VRRP IPv4 mcast group = 224.0.0.18Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: VRRP IPv6 mcast group = ff02::12Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Gratuitous ARP delay = 5......
可以看出keepalived已经启动成功,日志输出也是输出到了local0中(注: localmessages中收集了local0-local7的日志信息)。但是,为什么在/opt/nginx/log目录下却没有keepalived的日志呢?
那换个角度试试,观察可以发现,syslog的日志一般是存储在/var/log目录下的,那把keepalived的日志路径修改为/var/log/keepalived.log。修改/etc/syslog-ng/syslog-ng.conf配置,将d_keepalived的路径修改为/var/log/keepalived.log。
重启syslog和keepalived,查看日志正常。
那么,使用-S 0的方式来收集keepalived的日志是可行的,现在就要看下怎样来更改日志存储的路径,最好是放置在keepalived进程运行的目录下,而不是系统的默认路径,方便用户定位。
AppArmor是一款与SeLinux类似的安全框架/工具,其主要作用是控制应用程序的各种权限,例如对某个目录/文件的读/写,对网络端口的打开/读/写等等。
AppArmor通过配置文件(profile)来指定应用程序的权限,相关的配置放置在/etc/apparmor.d目录下:
drwxr-xr-x 2 root root 4096 Mar 27 2014 abstractions-rw-r--r-- 1 root root 732 Jan 17 2013 bin.pingdrwxr-xr-x 2 root root 4096 Mar 27 2014 program-chunks-rw-r--r-- 1 root root 809 Jan 17 2013 sbin.klogd-rw-r--r-- 1 root root 1350 Jun 6 11:05 sbin.syslog-ng-rw-r--r-- 1 root root 1087 Jan 17 2013 sbin.syslogddrwxr-xr-x 2 root root 4096 Mar 27 2014 tunables-rw-r--r-- 1 root root 231 Sep 26 2011 usr.lib.PolicyKit.polkit-explicit-grant-helper-rw-r--r-- 1 root root 588 Oct 17 2012 usr.lib.PolicyKit.polkit-grant-helper-rw-r--r-- 1 root root 255 Sep 26 2011 usr.lib.PolicyKit.polkit-grant-helper-pam-rw-r--r-- 1 root root 534 Oct 17 2012 usr.lib.PolicyKit.polkit-read-auth-helper-rw-r--r-- 1 root root 177 Sep 26 2011 usr.lib.PolicyKit.polkit-resolve-exe-helper-rw-r--r-- 1 root root 476 Sep 26 2011 usr.lib.PolicyKit.polkit-revoke-helper-rw-r--r-- 1 root root 424 Sep 26 2011 usr.lib.PolicyKit.polkitd-rw-r--r-- 1 root root 696 Jan 17 2013 usr.sbin.avahi-daemon-rw-r--r-- 1 root root 842 Jan 17 2013 usr.sbin.identd-rw-r--r-- 1 root root 853 Jan 17 2013 usr.sbin.mdnsd-rw-r--r-- 1 root root 1246 Jan 17 2013 usr.sbin.nscd-rw-r--r-- 1 root root 1880 Jan 17 2013 usr.sbin.ntpd-rw-r--r-- 1 root root 745 Jan 17 2013 usr.sbin.traceroute
可以看到syslog的配置为/etc/apparmor.d/sbin.syslog-ng,如下:
#include <tunables/global>#define this to be where syslog-ng is chrooted@{CHROOT_BASE}=""/sbin/syslog-ng {#include <abstractions/base>#include <abstractions/consoles>#include <abstractions/nameservice>#include <abstractions/mysql>capability chown,capability dac_override,capability fsetid,capability fowner,capability sys_tty_config,capability sys_resource,/dev/log w,/dev/syslog w,/dev/tty10 rw,/dev/xconsole rw,/etc/syslog-ng/* r,@{PROC}/kmsg r,/etc/hosts.deny r,/etc/hosts.allow r,/sbin/syslog-ng mr,/usr/share/syslog-ng/** r,# chrooted applications@{CHROOT_BASE}/var/lib/*/dev/log w,@{CHROOT_BASE}/var/lib/syslog-ng/syslog-ng.persist* rw,@{CHROOT_BASE}/var/log/** w,@{CHROOT_BASE}/var/run/syslog-ng.pid krw,@{CHROOT_BASE}/var/run/syslog-ng.ctl rw,/var/run/syslog-ng/additional-log-sockets.conf r,}
上述配置定义了syslog可以对目录和文件的访问权限,如:
/dev/log w表示对/dev/log具有写权限;
/etc/syslog-ng/* r表示对/etc/syslog-ng目录具有读权限;
/usr/share/syslog-ng/** r表示对/usr/share/syslog-ng目录下的文件具有读权限。
由此可见,如果想要通过syslog将keepalived的日志输出到/opt/nginx/log/keepalived.log下,syslog服务必须对/opt/nginx/log目录具有写权限,或者对/opt/nginx/log/keepalived.log文件具有写权限(注:文件可以不存在,但是目录需要存在)。
在/etc/apparmor.d/sbin.syslog-ng中增加如下配置:
/opt/nginx/log/keepalived.log rw,
重启AppArmor---/etc/init.d/boot.apparmor restart。
重启syslog和keepalived,在/opt/nginx/log/keepalived.log中应该就可以看到日志内容了。