基于etcd+confd通过Nginx对Docker服务混合注册发现详

先简单说下业务逻辑,etcd是一个分部式k/v存储系统,confd是一个对etcd的key或者目录做变化监控的软件,并配有相关语法,可以将变化的k/v处理后形成配置文件,nginx不用多说了,做docker容器的负载均衡流量调度。

在业务过程中,docker容器健康起来后,会通过接口向etcd注册相关k/v信息,confd检测到etcd的k/v变化后,立即触发程序通过模板形成新的nginx配置文件,先做离线语法测试,如果没问题就覆盖原配置,进而reload,测试不通过就不覆盖原配置,整个过程是安全可控的。在容器注册到nginx的upstream后,nginx会对容器做健康检查发现,如果正常,则分发流量过去。对应的业务流程图如下:

基于etcd+confd通过Nginx对Docker服务混合注册发现详解

根据业务情况,要解决如下几个问题:

1、nginx负载均衡的混合注册,使得nginx可以混合负载多个业务;

2、不同机房如何在同一etcd集群上进行注册,如何规划;

3、confd更新频率如何周期可控制,k/v每有变化实时触发reload太敏感,况且每个容器要注册多个k/v,在整体注册完之前,是不需要reload的;

4、confd启动时如何关联多个etcd的地址,保证高可用;

5、权限问题如何处理,怎么做,如果任何人知道ip和端口就可以注册,那么服务就垮了。

一、nginx负载均衡的混合注册,使得nginx可以混合负载多个业务域名容器

先分析下nginx做负载均衡时的配置文件,分析后注册时的变化因子主要有3个,1是server_name的域名,2是upstream的名称,3是upstream里的server,这三个元素就决定了不同的注册服务。有了这个思路后,设计confd对应的nginx的模板文件,先简单说下confd,confd可以直接下载二进制包,不存在安装的问题,配置好path后直接使用命令,在使用中默认读取/etc/confd下的conf.d和templates下两个目录的配置,对应github是https://github.com/coreos/etcd ,创建过程如下:

mkdir -p /etc/confd/{conf.d,templates}

然后在conf.d下创建.toml配置文件,在templates下创建.tmpl模板文件。
根据nginx的3个元素去分析规划k/v规则,优化后发现注册一个服务要添加两个健值,并用etcdctl命令进行模拟测试,注册第一个服务如下:
etcdctl set /service_sgin/subdomain/service1  "www.service1.com"
etcdctl set /service_sgin/upstream/service1/server1 192.168.1.1

其中service1是对应业务名称,"www.service1.com"是域名,192.168.1.1对应是server,先看下注册后的结果:

基于etcd+confd通过Nginx对Docker服务混合注册发现详

然后我再继续注册第二个服务,对应命令如下:
etcdctl set /service_sgin/subdomain/service2  "www.service2.com  page.service2.com"
etcdctl set  /service_sgin/upstream/service2/server1  192.168.1.2

注册后配置文件截图如下:

基于etcd+confd通过Nginx对Docker服务混合注册发现详

要的就是这个效果,另外加了一个默认的server,当过来没有符合业务的域名,直接302到某个业务地址,好了剖开看confd的两个概要配置如下:

/etc/confd/conf.d/nginx.conf.toml
[template]
prefix = "/service_sgin"  #此配置对应etcd的默认目录
src = "nginx.conf.tmpl"    #对应templates下的模板文件
dest = '/usr/local/nginx/conf/nginx.conf'  #对应nginx的配置文件
owner = "root"
mode = "0666"
keys = [
  "/upstream",  #监控的键值目录
  "/subdomain",  #监控的键值目录
]
check_cmd = "/usr/local/nginx/sbin/nginx -t -c {{.src}}"  #检测到变化后的测试
reload_cmd = "/usr/local/nginx/sbin/nginx -s reload"      #配置文件没问题后的reload

/etc/confd/templates/nginx.conf.tmpl
user root;
worker_processes auto;
worker_cpu_affinity auto;
pid  logs/nginx.pid;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#error_log_bind 192.168.1.31;
worker_rlimit_nofile 512000;
events {
    use epoll;
    worker_connections  20480;
}
http {
    include      mime.types;
    default_type  application/octet-stream;
    resolver 127.0.0.1 valid=10m;
    sendfile        on;
    keepalive_timeout  65s;
    proxy_next_upstream error timeout;
    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 32 4k;
######################对应upstream的模板部分################
{{range $sub := ls "/subdomain"}}
    upstream {{base $sub}} {
{{$subdir := printf "/upstream/%s/*" $sub}}{{range getvs $subdir}}
        server {{.}}; {{end}}
        keepalive_timeout 65s;
    }
{{end}}
#############################################################
    server {
        listen 80 backlog=65535 default;
        server_name localhost;
        location / {
                rewrite ^/(.*)$ redirect;
              }
            }
#####################对应server的模板部分####################
{{range gets "/subdomain/*"}}
    server {
        listen  80;
        server_name  {{.Value}};
        location / {
                proxy_pass              {{base .Key}};
                proxy_redirect  off;
                proxy_set_header  Host                  $host;
                proxy_set_header  X-Real-IP            $remote_addr;
                proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
          }
    }
{{end}}
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/bd2d8e50c7fd4e89f814e0dc8508e838.html