52

Etcd + confd 通过 Nginx 对后端服务的注册发现

 5 years ago
source link: https://mp.weixin.qq.com/s/sEL5in3LrWowN2C1WqjnJA?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

yIv6BfB.gif

本文介绍了Etcd+confd通过Nginx对后端服务的注册过程总结出的实用经验。

上篇文章回顾: 处理器核心真的越多越好?

先简单介绍下用到的产品,Etcd是一个分部式KV存储系统,confd是一个对Etcd key或目录做变化监控的工具,并配有相关语法,可以将变化的KV处理后形成配置文件,假设后端服务用的是Docker,Nginx就是对Docker做7层负载和流量调度的。

再看业务逻辑,Docker容器起来后,会通过接口(rest api或者rpc)向Etcd注册相关KV信息,confd检测到Etcd的KV变化后,立即触发程序通过模板形成新的Nginx配置文件,先做离线语法测试,如果没问题就覆盖原配置,进而reload,测试不通过不覆盖原配置,整个过程安全可控。在容器注册到Nginx的upstream后,Nginx会对容器做健康检查,如果正常,则分发流量过去。对应的业务流程图如下:

JfYnuaZ.jpg!web

根据业务情况,目前要考虑的问题有5个:

1、Nginx多域名多server的混合注册,使Nginx可以混合调度多个业务;

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

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

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

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

1

Nginx如何实现多域名多server的混合注册

先分析下Nginx做负载均衡时的配置文件,分析后发现能 决定不同的注册服务的3个 关键元素:

  • server_name的域名

  • upstream的名称

  • upstream里的server,

有了这个思路后,设计confd对应的Nginx的模板文件(confd是可以直接下载二进制包,不存在安装问题,配置好path后直接使用,在使用中默认读取/etc/confd下的conf.d和templates下两个目录的配置,对应github: https://github.com/coreos/etcd  ),具体是操作步骤如下:

1、创建confd使用的目录

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

2、在conf.d下创建.toml配置文件,在templates下创建.tmpl模板文件(后面介绍,想看步骤3注册效果)

3、根据Nginx的3个元素去分析规划KV规则,优化后发现注册一个服务要添加两个健值,并用e tcdctl命令进行模拟测试,注册第一个服务如下:

 $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,先看下注册后的结果:

7vAvUzV.jpg!web

然后再继续注册第二个服务,对应命令如下:

$etcdctl set /service_sgin/subdomain/service2  "www.service2.com  page.service2.com"$etcdctl set  /service_sgin/upstream/service2/server1  192.168.1.2

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

IFNZja2.jpg!web

达到了混合注册的效果,另外加了一个默认的server,当过来没有符合业务的域名,直接302到小米的主页http://www.mi.com,好了剖开看confd的两个概要配置编码如下:

$vim /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

$vim /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 ^/(.*)$ http://www.sina.cn redirect;
                   }
                }

    
    #####################对应server的模板部分####################
    {{range gets "/subdomain/*"}}
        server {
            listen  80;
            server_name  {{.Value}};
            location / {
                    proxy_pass              http://{{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}}
    }

2

不同机房如何在同一Etcd集群上进行注册

这个看起来复杂,实施起来并不复杂简单,为了合理利用资源和便于管理,不可能每个机房都对应建Etcd集群,这个时候几个邻近机房可以复用Etcd集群,比如c3和c4机房的注册,可以使用改变默认Etcd键值目录来实现:

prefix = "/service_sgin_c3" prefix  =  "/service_sgin_c4"

3

confd更新频率如何周期可控制上进行注册

KV每有变化实时触发reload太敏感,况且每个容器要注册多个KV,在整体注册完之前,是不需要reload的,即使后面可以用事务实现,不过confd本身也可以做一些调整,调整confd不要用watch模式,改而周期性去探测Etcd的键值变化,比如说2秒探测一次,这样处理相对是比较友好的,对应启动的命令如下:

./confd -backend="etcd" -node=10.211.103.151:2379 -interval=2

4

confd启动时如何容灾多个Etcd节点

同样,只要修改下confd的启动命令即可,让confd监控更多node(当然生产化境也可以用比如四层vip等其它方案实现),目前测试环境有3个node,全部监控进去如下:

 ./confd -backend="etcd" -node=10.211.103.151:2379 -node=10.211.103.152:2379 -node=10.211.103.153:2379 -interval=2

5

权限问题的处理

对于权限有两种方式,一个是证书,一个是账号。一般生产环境直接用证书即可,不过还是介绍一下Etcd的账号管理,Etcd的权限设计主要通过用户、规则来控制,将用户和规则对应起来就是用户的权限,默认安装后是不开启权限的,整理后相关的权限操作如下:

用户管理:

 etcdctl user add root:123   #加root用户,开启权限必须先加
  etcdctl auth enable         #权限管理开启
  etcdctl --username root:123 user list                   #查看用户
  etcdctl --username root:123 user remove test_user       #删除用户

role规则管理:

 etcdctl --username root:123 role add test_role          
  etcdctl --username root:123 role grant --path "/*"  --rw  test_role      #加权限
  etcdctl --username root:123 role revoke --path "/*" --write test_role    #减权限
  etcdctl --username root:123 role remove test_role       
  etcdctl --username root:123 role list
  etcdctl --username root:123 role get test_role

用户规则管理:

 etcdctl --username root:123 user add test_user:123
  etcdctl --username root:123 user grant --roles test_role   test_user  #加规则
  etcdctl --username root:123 user revoke  --roles test_role test_user  #减规则
  etcdctl --username root:123 user get test_user  #查看某个用户下的规则

备注:

1、guest用户的规则是guest,默认是全部权限。

2、confd是以访客guest身份监控KV的,对应的规则就是guest。

y6NJ3iI.png!web

vammAf6.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK