ansible管理nginx负载均衡

2016-12-30 06:08

因为手头自己有三个服务器,所以想折腾一下负载均衡。

两个 CentOS ,一个 Ubuntu ,都是比较新的。

一开始准备用 haproxy 来做负载均衡服务器,因为 haproxy 相比与 nginx 对 cookie 和 session 支持比较好,但是由于两个原因还是放弃了。

  1. 服务器被阿里云封掉

简单的在 haproxy 中设置后端服务器后,过一段时间就显示强制备案页面,由于我的域名没有备案。

后来我翻看了 nginx 日志发现, haproxy 默认在 request header 里面带了 X-Host ,被阿里云发现了,这里提供一个解决方法

# 删除掉你header里面的 Host
# 在backend里面添加一句
http-request del-header Host

然而 nginx 里面默认是没有添加 Host 这个的,要你在 localtion 中添加两句,如下面

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            www.example.com; # add Host
        proxy_set_header X-Forwarded-For $remote_addr; # add X-Forwarded
  }
}
  1. haproxy支持多开

我试了很多种选项,确定 pidfile 、改变 uid 、 gid 等等, haproxy 似乎可以允许很多个相同进程绑定同一个端口,虽然可以通过 pid 来写一套类似 service 管理的脚本,但终归很麻烦

我看网上有人写了这个脚本,但是 nginx 自带了,还是用 nginx 比较好,而且 ansible 与 service 的交互还不错。

nginx负载均衡

nginx负载均衡是通过反向代理来实现的,也就是把一台服务器的压力分摊到多台上面

要想实现这个必须要有后端服务器,假设我们有一台后端服务器 1.1.1.1 ,在代理主机的 nginx 配置系统 location 里面只要添加一条 proxy_pass 就行了

server {
listen 80;
server_name example.com;
location / {
    proxy_pass http://1.1.1.1;
}
}

上面只是简单的实现了一个反向代理的功能,当你有一个后端服务群的时候,你就要使用负载均衡模块了,负载均衡模块在 nginx 配置特别简单,添加一个 upstream 模块,把服务器ip或者域名放到里面

upstream webservers{
    server 1.1.1.1 weight=10;
    server my.domain.com  weight=10;

}

然后修改 proxy_pass 后的为 http://webservers 就行了

ps: nginx 对于后端反向代理服务器有个 max_fails 和 fail_timeout 属性,你要是设定了一个 max_fails 次数,你代理服务器拿取失败了几次就会在 fail_timeout 值之后尝试,和 haproxy 的 retry 属性差不多,但是似乎 haproxy 的 retry 不好使,我故意使用两个错误 ip 和正确 ip ,结果 nginx 能一直正确返回正确 ip 响应,而 haproxy 有时候能,有时候不行。

nginx错误日志

在调试 nginx 碰到一些错误,记录一下如何系统的解决方法

  • 调用 service nginx start 失败

首先看给的错误信息,假如让你看 systemctl status nginx.service 或 journalctl -xn ,输入去看

  1. 格式错误(format error)

一般你写的 nginx 的配置文件有问题,这时候可以用 nginx -t 检查格式,修改正确后会显示 success

  1. 无法绑定地址(bind error)

一般是因为有别的应用程序占用端口造成的,这时候用 netstat -tulpn 检查端口,然后选择 kill 掉占用端口的程序或者换一个端口

ansible playbook 编写

具体代码可以参考 nginx均衡负载ansible-playbook

首先你得写一个 hosts

[ali]
my ansible_ssh_host=1.1.1.1 ansible_ssh_user=root 
[tencent]
main ansible_ssh_host=1.1.1.2 ansible_ssh_user=root
[digital]
google ansible_ssh_host=1.1.1.3 ansible_ssh_user=root

前面 [ ] 包着的是组名,最前面的 my 和 main 和 google 是 别名 ,后面就是ip和用户名了。

写完 hosts 后要写两个 nginx 配置文件一个代理服务器的配置文件和一个后端服务器配置文件, playbook 很简单就是复制 nginx 配置文件和重启 nginx 。

---
- hosts: tencent
  remote_user: root

    tasks:
  - name: copy nginx config file 
    template: src=~/test/lunge_proxy.conf  dest=/etc/nginx/conf.d/lungelog.conf
    notify: restart nginx

    handlers:
  - name: restart nginx
    service: name=nginx state=restarted enabled=yes

解释一下 notify ,在复制完成之后就启用一个 handler 完成 nginx 的重启,当然这里也可以使用 reload ,假如在生产环境的话。

客户端和代理的 playbook 差不多就不多介绍了。