nginx后端服务动态配置

以下方式基于consul+upsync 一个最简化的demo

安装consul

wget https://releases.hashicorp.com/consul/1.4.0/consul_1.4.0_linux_amd64.zip

unzip consul_1.4.0_linux_amd64.zip

mv consul /usr/local/bin/

mkdir /etc/consul.d   #创建配置文件目录

启动consul

# 在开发者模式中启动Consul代理 一个单节点的consul,如果网络有多个ip, 那么就明确写出 其中-clinet的指的是启动web页面的时候, 谁可以访问, 0.0.0.0就是谁都可以访问,-config-dir指定配置文件目录
$ consul agent -dev -bind=192.168.200.148 -client 0.0.0.0 -config-dir /etc/consul.d/

# 创建一个服务定义配置文件,假设有一个名为web服务,它运行在80端口。
$ echo '{"service": {"name": "web", "tags": ["web"], "port": 80}}' >/etc/consul.d/web.json

启动consul web界面

默认的地址是http://IP:8500/ui 就是本地地址的8500端口

调用API

支持DNS API和HTTP API调用, 我们只说HTTP API

注册一个访问

$ vim redis.json

{
  "ID": "redis1",
  "Name": "redis",
  "Tags": [
    "primary",
    "v1"
  ],
  "Address": "127.0.0.1",
  "Port": 8000,
  "EnableTagOverride": false,
  "Check": {
    "DeregisterCriticalServiceAfter": "90m",
    "Script": "/usr/local/bin/check_redis.py",
    "HTTP": "http://localhost:5000/health",
    "Interval": "10s",
    "TTL": "15s"
  }
}

通过API提交

curl --request PUT --data @redis.json http://IP:8500/v1/agent/service/register

查询一个服务

curl http://IP:8500/v1/catalog/service/redis

删除一个服务

curl --request PUT http://IP:8500/v1/agent/service/deregister/redis1

为Consul创建Systemd服务

#  创建账号
useradd -M -s /sbin/nologin consul
chown -R consul.consul /opt/consul/
#创建systemd文件
$ vim /etc/systemd/system/consul.service

[Unit]
Description=Consul service discovery agent
Requires=network-online.target
After=network-online.target

[Service]
User=consul
Group=consul
EnvironmentFile=-/etc/default/consul
Environment=GOMAXPROCS=2
Restart=on-failure
ExecStartPre=[ -f "/opt/consul/run/consul.pid" ] && /usr/bin/rm -f /opt/consul/run/consul.pid
ExecStartPre=/usr/local/bin/consul configtest -config-dir=/opt/consul/conf
ExecStart=/usr/local/bin/consul agent $CONSUL_FLAGS
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGTERM
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target
# 启动服务
systemctl start consul.service

# 查看是否正常
systemctl status  consul.service
# 默认日志是在前台 ,我们配置为syslog , 在consul启动的时候加参数  -syslog
mkdir -p /var/log/consul/
chown -R syslog.syslog /var/log/consul/

# 创建日志配置文件
$ cat >/etc/rsyslog.d/consul.conf <<EOF
local0.* /var/log/consul/consul.log
EOF

# 修改默认配置文件中的以下内容
$ vim /etc/rsyslog.d/50-default.conf

# 变更前
*.*;auth,authpriv.none          -/var/log/syslog

# 变更后
*.*;auth,authpriv.none,local0.none          -/var/log/syslog

# 重启rsyslog让配置生效。
$ systemctl restart rsyslog

# 创建日志轮循规则
$ cat >/etc/logrotate.d/consul <<EOF
/var/log/consul/*log {
missingok
compress
notifempty
daily
rotate 5
create 0600 root root
}
EOF

配置upsync模块

安装nginx

wget 'http://nginx.org/download/nginx-1.9.2.tar.gz'
git clone https://github.com/weibocom/nginx-upsync-module
git clone https://github.com/xiaokai-wang/nginx_upstream_check_module

编译upsync模块

tar xzvf nginx-1.9.2.tar.gz
cd nginx-1.9.2
patch -p0 < ~/nginx_upstream_check_module/check_1.9.2+.patch
./configure --add-module=/root/nginx_upstream_check_module --add-module=/root/nginx-upsync-module
make && make install

创建相关用户和目录

$ useradd -M nginx -s /sbin/nologin
$ mkdir -p /var/log/nginx
$ chown -R nginx.nginx /var/log/nginx
$ mkdir /usr/local/nginx/conf/conf.d
$ mkdir -p /usr/local/nginx/conf/servers

修改配置文件

# 备份原配置文件
$ cd /usr/local/nginx
$ mv conf/nginx.conf conf/nginx.conf.bak

# 修改配置
$ vim /usr/local/nginx/conf/nginx.conf

user  nginx;
worker_processes  5;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /usr/local/nginx/conf/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$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.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /usr/local/nginx/conf/conf.d/*.conf;
}

创建站点配置文件

$ vim /usr/local/nginx/conf/conf.d/site.conf

upstream test {
  # fake server otherwise ngx_http_upstream will report error when startup
  server 127.0.0.1:11111;

  # all backend server will pull from consul when startup and will delete fake server

  # 后端使用consul存储
  # upsync YOUR-IP:8500/v1/kv/upstreams/test upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;


  # 后端使用etcd存储
  upsync YOUR-IP:2379/v2/keys/upstreams/test upsync_timeout=6m

  upsync_interval=500ms upsync_type=etcd strong_dependency=off;
  upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;

  #配置健康检查
  check interval=1000 rise=2 fall=2 timeout=3000 type=http default_down=false;
  check_http_send "HEAD / HTTP/1.0\r\n\r\n";
  check_http_expect_alive http_2xx http_3xx;

}

upstream bar {
  server YOUR-IP:8080 weight=1 fail_timeout=10 max_fails=3;
}

server {
  listen 80;

  location = / {
    proxy_pass http://test;
  }

  location = /bar {  
    proxy_pass http://bar;
  }

  location = /upstream_show {
    upstream_show;
  }

  location = /upstream_status {
    check_status;
    access_log off;
  }
}

创建nginx的systemd服务

$ vi /lib/systemd/system/nginx.service

[Unit]
Description=The NGINX HTTP and reverse proxy server
Documentation=http://nginx.org/en/docs/
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
加入开机启动
chmod +x /lib/systemd/system/nginx.service
systemctl enable nginx.service

验证upsync

在nginx的默认站点目录启动一个服务

cd /usr/local/nginx/html
python -m SimpleHTTPServer 8080

通过consul添加的后端服务器信息

# 增加一个后端服务器
curl -X PUT http://IP:8500/v1/kv/upstreams/test/IP:8080

# 删除一个服务器
curl -X DELETE http://IP:8500/v1/kv/upstreams/test/IP:8080

访问服务查看是否正常

页面自动根据proxy_pass http://test;成功转到了后端服务器

访问upstream状态

访问地址: IP:upstream_status即可

查看是否被dump下来

cat /usr/local/nginx/conf/servers/servers_test.conf
server IP:8080 weight=1 max_fails=2 fail_timeout=10s;