菜蜂 发表于 2018-11-11 09:30:47

CentOS7.1下生产环境Keepalived+Nginx配置

  注:下文涉及到配置的,如无特别说明,主备机则一致!
  一、环境介绍
  1、这是我CentOS的版本,CentOS7.1,主备都为该版本
  # cat /etc/redhat-release

  CentOS Linux>  # cat /proc/version
  Linux version 3.10.0-229.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.2 20140120 (Red Hat 4.8.2-16) (GCC) ) #1 SMP Fri Mar 6 11:36:42 UTC 2015
  2、修改主机名并修改host
  # hostnamectl set-hostname node-01
  # vi /etc/hosts
  127.0.0.1node-01在127后面添加node-01
  二、拓扑图的规划:
  A)
  |------------IP地址-----------|----------|------软件------|----------|-状态-|
  |172.21.4.51(VIP:172.21.4.44 )|----------|keepalived+nginx|----------|Master|
  |172.21.4.52(VIP:172.21.4.44 )|----------|keepalived+nginx|----------|Backup|
  |---------172.21.4.91---------|----------|------IIS-------|----------|-Web1-|
  |---------172.21.4.91---------|----------|------IIS-------|----------|-Web2-|
  B)
  Internet--
  |
  =============
  | ISP Router|
  =============
  |                               |
  |                               |---- Web1 (172.21.4.91)
  |-HA-|eth0--> 172.21.4.51               |
  |             \               /
  |            \               /
  |               ===VIP(172.21.4.44)===
  |            /               \
  |             /               \
  |-HA-|eth0--> 172.21.4.52               |
  |---- Web2 (172.21.4.92)
  |
  注:在网关上已针对VIP(172.21.4.44)作了80端口映射。
  此架构需考虑的问题:
  1、Master运行,则Master占有vip且Nginx能够正常服务;
  2、Master挂了,则Backup抢占vip且Nginx能够正常服务;
  3、任何一台前端nginx服务挂了,则vip资源转移到另一台服务器上,并发送提醒邮件;
  4、nginx需要检测后端服务器的健康状态(由于应用是挂在默认网站下的虚拟目录,且无法更改,必须能够对虚拟目录进行健康检查)
  5、由于应用需要Session保持,但由于没有做Session共享,实际服务器角色转换时,应用会受到一定的影响。
  三、安装前的准备工作
  CentOS7环境下,默认是使用FireWallD服务,即使你修改了iptables,重启又被初始化了,需要再次手动systemctl restartiptables.service才能使设置的iptables生效,由于FireWallD暂时还没有熟悉使用方法且不知道他比iptables到底有哪些优势,保险起见,还是换回原先的iptables
  1、关闭firewall:
  # systemctl stop firewalld.service
  #停止firewall
  # systemctl disable firewalld.service 或 systemctl mask firewalld.service
  #禁止firewall开机启动
  2、安装iptables防火墙
  # yum install iptables-services -y
  # systemctl enable iptables
  3、在进行Keepalived和nginx配置前,务必将集群内的几台主机的通讯相互完全放行(并开放80的Web访问规则),否则很有可能出现脑裂或其他问题,可直接在配置文件内加入以下语句;
  # vi /etc/sysconfig/iptables
  -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
  -A INPUT -s 172.21.4.51 -j ACCEPT
  -A INPUT -s 172.21.4.52 -j ACCEPT
  -A INPUT -s 172.21.4.91 -j ACCEPT
  -A INPUT -s 172.21.4.92 -j ACCEPT
  # systemctl restart iptables.service
  四、Keepalived与Nginx的安装
  1、安装ipvsadm
  # yum install ipvsadm
  # ipvsadm -v
  ipvsadm v1.27 2008/5/15 (compiled with popt and IPVS v1.2.1)
  ipvs(IP Virtual Server)是整个负载均衡的基础,如果没有这个基础,故障隔离与失败切换就毫无意义了。ipvs 具体实现是由 ipvsadm 这个程序来完成的。CentOS7.1默认自带安装了。
  2、安装keepalived(其实7.1自带了)
  # yum install keepalived
  # keepalived -v
  Keepalived v1.2.13 (03/06,2015)
  3、安装当前最新稳定版1.8.0
  注1:一开始是用yum安装的nginx,结果发现后端服务器Down机或状态不正常时,nginx也照常转发请求,后面yum erase nginx后,进行了手动安装。因为需要额外添加 nginx_upstream_check_module模块。
  注2:安装过程会提示类型这样的错误 ./configure: error: the HTTP rewrite module requires the PCRE library.
  所以先安装相应的支持库来解决。pcre,正则表达式匹配支持;zlib,用于压缩等等。
  # yum -y install gcc-c++ pcre-devel zlib-devel
  1) 为nginx建立一个www组,并建立一个不登录的账户nginx,放入www用户组
  # groupadd -f www
  # useradd -d /var/cache/nginx -s /sbin/nologin -g www nginx
  2) 建立目录用于存放nginx日志文件,并赋权限
  # mkdir /var/log/nginx
  # mkdir /usr/local/nginx
  # chown -R nginx.www /var/log/nginx
  # chown -R nginx.www /usr/local/nginx
  3) 分别下载nginx、额外模板及安装
  # mkdir /nginx
  # cd /nginx
  # wget http://nginx.org/download/nginx-1.8.0.tar.gz
  # wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/master.zip
  # tar -xvf nginx-1.8.0.tar.gz
  # unzip master.zip
  #在当前目录下解压出nginx_upstream_check_module-master这个目录
  # cd nginx-1.8.0/
  # patch -p1 < /nginx/nginx_upstream_check_module-master/check_1.7.5+.patch
  #由于安装版1.8.0稳定版,所以选check_1.7.5+.patch这个补丁包,其他版本相应选择即可
  #如果提示bash: patch: 未找到命令...应该安装一下patch命令包yum -y install patch
  # ./configure --prefix=/usr/local/nginx --user=nginx --group=www --pid-path=/run/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --add-module=/nginx/nginx_upstream_check_module-master
  # make && make install
  便于以后的操作,进行以下设置并制作自启动文件:
  # ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
  # vi /usr/lib/systemd/system/nginx.service
  #加下以下内容:
  #---------Begin------------------------------------
  
  Description=nginx - high performance web server
  Documentation=http://nginx.org/en/docs/
  After=network.target remote-fs.target nss-lookup.target
  
  Type=forking
  PIDFile=/run/nginx.pid
  ExecStartPre=/usr/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
  ExecStart=/usr/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
  ExecReload=/bin/kill -s HUP $MAINPID
  ExecStop=/bin/kill -s QUIT $MAINPID
  PrivateTmp=true
  
  WantedBy=multi-user.target
  #---------end--------------------------------------
  # systemctl enable nginx.service
  系统启动时让nginx.service自启动。
  4) keepalived和Nginx最好也设置开机启动
  # systemctl enable keepalived
  # systemctl enable nginx
  五、Keepalived配置
  在配置keepalived之前,先关闭selinux
  A、vi /etc/selinux/config
  B、设置 SELINUX=disabled 保存
  C、执行setenforce 0
  如果只想临时关闭,直接输入:setenforce 0
  # vi /etc/keepalived/keepalived.conf
  #############keepalived配置#############################################################
  ! Configuration File for keepalived
  global_defs {
  }
  vrrp_script chk_nginx {
  #必须放在track代码的上方,否则无效,测试了几次是这个情况
  script "killall -0 nginx"
  #用shell命令检查nginx服务是否存在
  interval 1
  #时间间隔为1秒检测一次
  weight -15
  #当nginx的进程不存在了,就把当前的权重-15
  }
  vrrp_instance VI_1 {
  state MASTER
  #主LVS是MASTER,从主机时此项要改为BACKUP,要大写
  interface enp4s0
  #LVS监控的网络接口
  virtual_router_id 51
  #同一实例下virtual_router_id必须相同,MASTRE/BACKUP 设置值要一样
  priority 100
  #定义优先级,数字越大,优先级越高,把此份Conf拷贝到另一台机器上时,设置的priority值要比MASTRE权重值低
  advert_int 1
  #MASTER与BACKUP负载均衡器之间同步检查的时间间隔,单位是秒
  authentication {
  auth_type PASS
  auth_pass 376879148
  #验证类型和密码,有PASS和AH两种,一般用PASS,据说AH有问题,认证密码主备服务器之间一定要一致,否则出错
  }
  virtual_ipaddress {
  172.21.4.44
  #设置虚拟IP,可以有多个地址,每个地址占一行,不需掩码。注意:这个 ip 必须与我们在 lvs 客户端设定的vip相一致
  }
  track_script {
  chk_nginx
  #引用上面的vrrp_script定义的脚本名称
  }
  notify_master "/etc/keepalived/changemail.py master"
  notify_backup "/etc/keepalived/changemail.py backup"
  notify_fault "/etc/keepalived/changemail.py fault"
  #指定当切换到主、备及故障状态时,执行的脚本
  }
  ###################################################################################
  五、HA状态切换时的邮件提醒
  # python -V
  Python 2.7.5
  # vi /etc/keepalived/changemail.py
  ########################changemail.py利用Python2.7程序发邮件###########################
  #!/usr/bin/python
  # -*- coding: UTF-8 -*-
  import smtplib
  import socket
  import time
  from email.MIMEText import MIMEText
  from email.Utils import formatdate
  from email.Header import Header
  import sys
  #发送邮件的相关信息,根据实际情况填写
  smtpHost = 'smtp.exmail.qq.com'
  smtpPort = '25'
  sslPort= '465'
  fromMail = 'youki@appi.com'
  toMail   = 'youki@appi.com'
  username = 'youki@appi.com'
  password = 'xxxxxxx'
  #解决中文问题
  reload(sys)
  sys.setdefaultencoding('utf8')
  #邮件标题和内容
  subject= socket.gethostname() + " HA status has changed"
  body   = (time.strftime("%Y-%m-%d %H:%M:%S")) + " vrrp transition, " + socket.gethostname() + " changed to be " + sys.argv
  #初始化邮件
  encoding = 'utf-8'
  mail = MIMEText(body.encode(encoding),'plain',encoding)
  mail['Subject'] = Header(subject,encoding)
  mail['From'] = fromMail
  mail['To'] = toMail
  mail['Date'] = formatdate()
  try:
  #连接smtp服务器,明文/SSL/TLS三种方式,根据你使用的SMTP支持情况选择一种
  #普通方式,通信过程不加密
  #smtp = smtplib.SMTP(smtpHost,smtpPort)
  #smtp.ehlo()
  #smtp.login(username,password)
  #tls加密方式,通信过程加密,邮件数据安全,使用正常的smtp端口
  #smtp = smtplib.SMTP(smtpHost,smtpPort)
  #smtp.ehlo()
  #smtp.starttls()
  #smtp.ehlo()
  #smtp.login(username,password)
  #纯粹的ssl加密方式,通信过程加密,邮件数据安全
  smtp = smtplib.SMTP_SSL(smtpHost,sslPort)
  smtp.ehlo()
  smtp.login(username,password)
  #发送邮件
  smtp.sendmail(fromMail,toMail,mail.as_string())
  smtp.close()
  print 'OK'
  except Exception:
  print 'Error: unable to send email'
  #
  #######################################################################################
  1、上面的脚本制作完成后,记得赋权,否则无法执行。
  # chmod +x /etc/keepalived/changemail.py
  #scp /etc/keepalived/keepalived.conf 172.21.4.52:/etc/keepalived
  把主机上的配置文件copy到Backup服务器上,现在在两台主机上可以利用 ip addr show命令来查看VIP的获取情况
  2、keeplived日志位置指定:
  在主从keeplived节点上编译/etc/sysconfig/keepalived文件
  # vi /etc/sysconfig/keepalived
  将最后一行KEEPALIVED_OPTIONS="-D" 修改为:KEEPALIVED_OPTIONS="-D -d -S 0"
  3、修改主从节点日志配置文件/etc/rsyslog.conf
  # vi /etc/rsyslog.conf
  加入如下配置:
  #keepalived -S 0
  local0.*/var/log/keepalived.log
  4、重启日志服务
  # systemctl restart rsyslog.service
  5、检查/var/log/keepalived.log文件是否存在
  注意事项:
  1、输出的日志信息: /var/log/messages ,更具体的日志信息输出需要在启动keepalived时加 -d 参数。
  2、在都为MASTER且priority一样的情况下,后启的节点(service vrrp start)会取代正在运行的节点变成主用的。
  3、一台为MASTER且priority较高的情况下,不受次节点down/up影响,并且其本身再从down变为up时,会抢夺控制权。
  4、在都为MASTER且priority一样的情况下,正在运行的主节点down(断网),次节点会自动接管,主节点再起来时不会去抢夺控制权。
  #keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。
  #如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加
  #如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少
  #其他情况,维持原本配置的优先级,即配置文件中priority对应的值。
  #这里需要注意的是:
  #1) 优先级“不会”不断的提高或者降低,当track的对象恢复时,又是一致的
  #2) 可以编写多个检测脚本并为每个检测脚本设置不同的weight
  #3) 不管提高优先级还是降低优先级,最终优先级的范围是在,不会出现优先级小于等于0或者优先级大于等于255的情况
  #这样可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
  六、nginx配置
  # vi /usr/local/nginx/conf/nginx.conf
  #############nginx配置#############################################################
  usernginx www;
  worker_processes2;
  #nginx进程数,建议设置为等于CPU总核心数
  #worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
  #为每个进程分配cpu,将N个进程分配到N个cpu,可以写多个或者将一个进程分配到多个cpu
  error_log/var/log/nginx/error.log crit;
  #pid       /run/nginx.pid;
  events {
  use epoll;
  #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以 能
  worker_connections 102400;
  #最大连接数量,根据硬件调整,理论上每台nginx服务器的最大连接数为worker_processes*s
  }
  http {
  include       /usr/local/nginx/conf/mime.types;
  default_typeapplication/octet-stream;
  log_formatmain'$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for"';
  access_log/var/log/nginx/access.logmain;
  sendfile      on;
  #tcp_nopush   on;
  server_tokens off;
  #nginx隐藏版本号
  keepalive_timeout65;
  proxy_intercept_errors on;
  #表示使nginx阻止HTTP应答代码为400或者更高的应答
  gzip on;
  #该指令用于开启或关闭gzip模块(on/off)
  gzip_min_length 1k;
  #设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于1k的字节数,小于1k可能会越压越大。
  gzip_buffers 4 8k;
  #设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 8k代表以8k为单位,安装原始数据大小以16k为单位的4倍申请内存。
  gzip_http_version 1.1;
  #识别http的协议版本(1.0/1.1)
  gzip_comp_level 3;
  #gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
  gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/xml+rss;
  #匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的,经实测对本网站的图片压缩后,积极反而增大,所以取消图片类的压缩。
  gzip_vary on;
  #和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
  upstream MyApp{
  ip_hash;
  #1.轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端 除
  #2.weight:指定轮询几率,weight和访问比率成正比,用于后端服务器性能不 况
  #3.ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后题
  #4.fair(第三方):按后端服务器的响应时间来分配请求,响应时间短的优先分配
  server 172.21.4.91:80 max_fails=2 fail_timeout=10s;
  server 172.21.4.92:80 max_fails=2 fail_timeout=10s;
  #max_fails默认为1,fail_timeout默认为10秒,默认情况下后端服务器在10秒内出错1次认为服务器异常将停止转发
  check interval=3000 rise=2 fall=2 timeout=1000 type=http;
  #对条目中的所有节点,每3秒检测1次,请求2次正常则标记该机状态为UP
  check_http_send "GET /appicrm HTTP/1.0\r\n\r\n";
  #检测网址子目录,在这里为http://mail.appi.cn/appicrm
  }
  server
  {
  listen       80;
  server_namemail.appi.cn;
  charset utf-8;
  location ~ .*\.(ico|gif|jpg|jpeg|png|bmp|swf|js|css|htm|html)$
  {
  access_log image.log;
  expires 14d;
  root /usr/local/nginx/proxy_cache;
  proxy_store on;
  proxy_temp_path /usr/local/nginx/proxy_cache_image;
  if ( !-e $request_filename)
  #文件和目录不存在的时候重定向
  {proxy_pass http://MyApp;}
  #rewrite ^(.*) http://www.test.com/test/$domain/ break;
  }
  #last:重新将rewrite后的地址在server标签中执行
  #break:将rewrite后的地址在当前location标签中执行
  location / {
  rewrite ^/(.*)$ /appicrm/$1 last;
  }
  location ~* ^/appicrm/.*$ {
  proxy_set_header      Host $host;
  proxy_set_header      REMOTE-HOST $remote_addr;
  proxy_set_header      X-Real-IP $remote_addr;
  proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_pass            http://MyApp;
  client_max_body_size    10m;
  client_body_buffer_size 128k;
  proxy_connect_timeout   90;
  proxy_send_timeout      90;
  proxy_read_timeout      90;
  proxy_buffer_size       4k;
  proxy_buffers         4 32k;
  proxy_busy_buffers_size 64k;
  proxy_temp_file_write_size 64k;
  }
  location /webstatus {
  check_status;
  access_log off;
  error_log off;
  auth_basic "Restricted";
  auth_basic_user_file/usr/local/nginx/conf/htpasswd/test;
  #allow IP;
  #deny all;
  }
  error_page   500 502 503 504/50x.html;
  location = /50x.html {
  root   html;
  }
  }
  }
  #
  ###################################################################################
  有几个需要注意的问题:
  1、如下提示的Pid错误
  7月 15 18:11:24 localhost.localdomain systemd: Failed to read PID from file /var/run/nginx.pid: Invalid argument
  解决:注释掉/usr/lib/systemd/system/nginx.service文件内的指定PID路径那一行,后面find nginx 的PID实际存的位置后再修改回正常的,或干脆注释掉,因为我的修改了后面又出错了。nginx安装的时候指定的位置居然不正确,不知道为何!网上有很多解决方法包括国外网站都说要安装各种支持文件,经测试都是错误答案。
  2、Webstatus这个状态查询页面,你肯定不希望所有人都能访问,所以需要加密
   mkdir /usr/local/nginx/conf/htpasswd/
   htpasswd -c /usr/local/nginx/conf/htpasswd/test Youki
  New password:
  Re-type new password:
  Adding password for user auth_user
   vi /usr/local/nginx/conf/nginx.conf
  auth_basic "Restricted";
  auth_basic_user_file/usr/local/nginx/conf/htpasswd/test;
  将以上两句加入/webstatus节
  以上配置自行经过各种切换测试且通过,如果有博友发现问题可与我交流,感谢阅读!

页: [1]
查看完整版本: CentOS7.1下生产环境Keepalived+Nginx配置