使用etcd+confd+nginx实现动态反向代理

confd介绍

confd是一个轻量级的配置管理工具,源码地址:https://github.com/kelseyhightower/confd,它可以将配置信息存储在etcd、consul、dynamodb、redis以及zookeeper等。confd定期会从这些存储节点pull最新的配置,然后重新加载服务,完成配置文件的更新。

场景

现有应用服务a1,a2,a3,…提供http服务。
前面有nginx来当做代理,nginx的配置的upstream里配置以上应用服务的地址。
应用服务都是微服务化,跑在k8s里。根据业务发展需要,应用服务a1,a2,…要动态增删。
当前要解决的需求是,当动态增加a1,a2,…服务个数,要同步自动更新nginx的upstream列表。

我们期望的nginx的upstream的配置:

upstream hash_sid {
    hash $arg_sid;
    server addr_of_a1;
    server addr_of_a2;
    ...
}

编辑/etc/confd/templates/nginx.conf.tmpl:


worker_processes  2;

events {
    use epoll;
    worker_connections  10000;
}

http {
    include    mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    proxy_connect_timeout 2;
    client_max_body_size   100m;

    upstream hash_sid {
        hash $arg_sid;
        {{range getvs "/pro/nginx/upstream/*"}}
            server {{.}};
        {{end}}
    }


    server {


        #listen *:443;
        listen 443 ssl;
        server_name *.yourdomain.com;
        ssl_certificate   /etc/openresty/cert/yourdomain.pem;
        ssl_certificate_key  /etc/openresty/cert/yourdomain.key;
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        charset utf-8;

        access_log logs/443.access.log;
        error_log  logs/443.error.log;



        # http 路由
        location ^~ /shop/ {
            proxy_pass http://hash_sid;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # websocket路由 WebSocket
        location ^~ /chat {
            proxy_pass http://hash_sid;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
        }


        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

主要语法解释:
- {{range getvs “/pro/nginx/upstream/*”}} // 表示遍历哪个目录下的值
- server {{.}}; // 输出值
- {{end}} //range结束

编辑conf.d/nginx.toml:

[template]
src = "nginx.conf.tmpl"
dest = "/usr/local/openresty/nginx/conf/nginx.conf"
keys = [ 
    "/pro/nginx/upstream/",
    "/pro/nginx/redis/",
]

check_cmd = "/usr/local/openresty/bin/openresty -t -c {{.src}}"
reload_cmd = "/usr/local/openresty/bin/openresty -s reload"

参数解释:
- src: 表示nginx配置模板的地址
- dest: 表示模板替换后,输出的实际nginx的配置地址
- keys: 表示要监听的etcdkey,用到哪些就写哪些
- check_cmd: 表示使配置生效前,要检查配置可用性。如果检查失败,则不执行reload。可不配置,不检查,直接执行reload_cmd.
- reload_cmd: 表示重新加载nginx的命令。必须配置。

在nginx所在的docker里,同时启动confd:

confd -watch -backend etcdv3 -node http://172.16.1.1:2379 -node http://172.16.1.2:2379 -node http://172.16.1.3:2379

http://172.16.1.1:2379 等地址, 是对应的etcd的地址。

在应用a1,…中,启动后,将自己的ip注册到etcd中的/pro/nginx/upstream/addr_of_a1,值为对应的ip。

前提是nginx所在的pod要和应用a1等的网络在一个内网网段。

你可能感兴趣的:(微服务,云计算)