@adonia
2018-05-25T06:19:43.000000Z
字数 12663
阅读 234
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/sh
BIN=$(cd $(dirname "$0"); pwd)
KEEPALIVED=$(cd $(dirname "$BIN"); pwd)
PATH=$KEEPALIVED/sbin:$PATH
PID_FILE=$KEEPALIVED/run/keepalived.pid
VRRP_PID=$KEEPALIVED/run/vrrp.pid
CHECKER_PID=$KEEPALIVED/run/checker.pid
DAEMON=$(which keepalived)
CONFIG=$KEEPALIVED/etc/keepalived/keepalived.conf
RETVAL=0
# RETVAL = 0 if running, != 0 if stopped
status_keepalived() {
if [ -f "${PID_FILE}" ]; then
RETVAL=0
for pid in $(cat "${PID_FILE}"); do
kill -0 "${pid}" > /dev/null 2>&1 || RETVAL=3
done
kill -0 $(cat "${PID_FILE}") > /dev/null 2>&1
if [ $? != 0 ]; then
RETVAL=3
fi
else
RETVAL=1
fi
}
ensure_dir() {
local dir=$KEEPALIVED/run
if [ ! -d $dir ]; then
mkdir -p $dir
fi
}
start_keepalived() {
status_keepalived
if [ "${RETVAL}" = 0 ]; then
echo "Keepalived is currently running"
else
RETVAL=0
echo "Starting Keepalived"
ensure_dir
"${DAEMON}" -f "${CONFIG}" -l -D -d -S 0 -p "${PID_FILE}" -r "${VRRP_PID}" -c "${CHECKER_PID}"<&-
RETVAL=$?
case "${RETVAL}" in
0)
echo "Finished starting Keepalived"
echo "SUCCESS"
;;
*)
echo "Errored starting Keepalived"
remove_pid
echo "FAILED - check logs"
RETVAL=1
;;
esac
fi
}
stop_keepalived() {
status_keepalived
if [ "${RETVAL}" = 0 ]; then
for pid in $(cat "${PID_FILE}"); do
killproc -p ${pid} -t 10 ${DAEMON} || RETVAL=$?
done
set -e
if [ "${RETVAL}" = 0 ]; then
remove_pid
else
echo "FAILED - check logs"
fi
else
echo "Keepalived Manage not running"
fi
}
remove_pid() {
rm -f "${PID_FILE}"
}
case "$1" in
start)
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}" >&2
RETVAL=1
;;
esac
exit "${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/syslog
BINDIR=/sbin
# update $SYSLOG_DAEMON if not up-to-date
test -n "$SYSLOG_DAEMON" && \
test -x "${BINDIR}/$SYSLOG_DAEMON" || {
for SYSLOG_DAEMON in rsyslogd syslog-ng syslogd ; do
test -x "${BINDIR}/$SYSLOG_DAEMON" && break
done
}
# set daemon dependent variables
rsocks=""
start_klogd=yes
case "$SYSLOG_DAEMON" in
rsyslogd)
syslog=rsyslogd
mkdir -p -m 0750 /var/run/rsyslog
if test "$2" = "early" ; then
config=/etc/rsyslog.early.conf
else
config=/etc/rsyslog.conf
fi
compat=${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 ; do
test "x$one" = 'x$ModLoad' && \
test "x$two" = 'ximklog.so' && {
start_klogd=no
break
}
done < $config
;;
syslog-ng)
syslog=syslog-ng
config=/etc/syslog-ng/syslog-ng.conf
params="$SYSLOG_NG_PARAMS"
;;
*)
syslog=syslogd
config=/etc/syslog.conf
params="$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) # 目录的UID
dir_group(gid) # 目录的GID
dir_perm(perm) # 目录的权限,使用八进制方式标注,例如0644
owner(uid) # 文件的UID
group(gid) # 文件的GID
perm(perm) # 文件的权限,同样,使用八进制方式标注
gc_busy_threshold(n) # 当syslog-ng忙时,其进入垃圾信息收集状态的时间一旦分派的对象达到这个数字,syslog-ng就启动垃圾信息收集状态。默认值是:3000。
gc_idle_threshold(n) # 当syslog-ng空闲时,其进入垃圾信息收集状态的时间一旦被分派的对象到达这个数字,syslog-ng就会启动垃圾信息收集状态,默认值是:100
log_fifo_size(n) # 输出队列的行数
log_msg_size(n) # 消息日志的最大值(bytes)
mark(n) # 多少时间(秒)写入两行MARK信息供参考,目前没有实现
stats(n) # 多少时间(秒)写入两行STATUS信息,默认值是:600
sync(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(设备)选择日志消息,使用逗号分割多个facility
level(..) # 根据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=95842
Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Registering Kernel netlink reflector
Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Registering Kernel netlink command channel
Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: Registering gratuitous ARP shared channel
Jun 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_DEVEL
Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: VRRP IPv4 mcast group = 224.0.0.18
Jun 6 11:13:17 NKG1000009441 Keepalived_vrrp[95842]: VRRP IPv6 mcast group = ff02::12
Jun 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.ping
drwxr-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.syslogd
drwxr-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
中应该就可以看到日志内容了。