基于etcd+confd通过nginx对docker服务注册发现详解

2023-10-20 17:59

本文主要是介绍基于etcd+confd通过nginx对docker服务注册发现详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文转载自http://www.net-add.com,原创愚人乙,如有侵权,联系本人,必删之。

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

在业务过程中,首先管理员操作Docker Client,除了提交容器(Container)启动与停止指令外,还通过REST-API方式向Etcd(K/V)存储组件注册容器信息包括容器名称、主宿机IP、映射端口等。confd检测到etcd的k/v变化后,立即触发程序通过模板形成新的nginx配置文件,先做离线语法测试,如果没问题就覆盖原配置,进而reload,测试不通过就不覆盖原配置,整个过程是安全可控的。在容器注册到nginx的upstream后,nginx会对容器做健康检查发现,如果正常,则分发流量过去。对应的业务流程图如下:在这里插入图片描述
根据业务情况,要解决如下几个问题:
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是可以直接下载二进制包,不存在安装问题,配置好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个元素去分析规划k/v规则,优化后发现注册一个服务要添加两个健值,并用etcdctl命令进行模拟测试,注册第一个服务如下:

3.1 示例
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,先看下注册后的结果:
在这里插入图片描述
然后我再继续注册第二个服务,对应命令如下:

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

注册后配置文件截图如下:
在这里插入图片描述

下面为启动Confd服务命令行,参数“interval”为指定探测etcd的频率,单位为秒,参数“-node”为指定etcd监听服务主地址,以便获取容器信息。

# /usr/local/bin/confd -verbose -interval 10 -node '192.168.1.21:4001' -confdir /etc/confd > /var/log/confd.log &

看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 ^/(.*)$ 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}}
}

模板引擎说明

本小节详细说明Confd模板引擎基础语法与示例,下面为示例用到的KEY信息。

# curl -XPUT http://192.168.1.21:4001/v2/keys/app/servers/backstabbing_rosalind-d value="192.168.1.22:49156"   
# curl -XPUT http://192.168.1.21:4001/v2/keys/app/servers/cocky_morse-d value="192.168.1.22:49158"   
# curl -XPUT http://192.168.1.21:4001/v2/keys/app/servers/goofy_goldstine-d value="192.168.1.22:49160"   
# curl -XPUT http://192.168.1.21:4001/v2/keys/app/servers/prickly_blackwell-d value="192.168.1.22:49162"
  1. base
    作为path.Base函数的别名,获取路径最后一段。
    {{ with get “/app/servers/prickly_blackwell”}}
    server {{base .Key}} {{.Value}} check
    {{end}}
prickly_blackwell 192.168.1.22:49162
  1. get
    返回一对匹配的KV,找不到则返回错误。
    {{with get “/app/servers/prickly_blackwell”}}
    key: {{.Key}}
    value: {{.Value}}
    {{end}}
/app/servers/prickly_blackwell 192.168.1.22:49162
  1. gets
    {{range gets “/app/servers/*”}}
    {{.Key}} {{.Value}}
    {{end}}
/app/servers/backstabbing_rosalind 192.168.1.22:49156  
/app/servers/cocky_morse 192.168.1.22:49158  
/app/servers/goofy_goldstine 192.168.1.22:49160  
app/servers/prickly_blackwell 192.168.1.22:49162
  1. getv
    返回一个匹配key的字符串型Value,找不到则返回错误
    {{getv “/app/servers/cocky_morse”}}
192.168.1.22:49158

5、getvs
返回所有匹配key的字符串型Value,找不到则返回错误。
{{range getvs “/app/servers/*”}}
value: {{.}}
{{end}}

value: 192.168.1.22:49156  
value: 192.168.1.22:49158  
value: 192.168.1.22:49160  
value: 192.168.1.22:49162  
  1. split
    对输入的字符串做split处理,即将字符串按指定分隔符拆分成数组
    {{ $url := split (getv “/app/servers/cocky_morse”) “:” }}
    host: {{index $url 0}}
    port: {{index $url 1}}
host: 192.168.1.22  
port: 49158  
  1. ls
    返回所有的字符串型子key,找不到则返回错误。
    {{range ls “/app/servers/”}}
    subkey: {{.}}
    {{end}}
subkey: backstabbing_rosalind  
subkey: cocky_morse  
subkey: goofy_goldstine  
subkey: prickly_blackwell 
  1. lsdir
    返回所有的字符串型子目录,找不到则返回一个空列表。
    {{range lsdir “/app/”}}
    subdir: {{.}}
    {{end}}
subdir: servers

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

这个其实看起来复杂,实施起来非常简单,为了节省资源,不可能每个机房都对应建etcd集群,这个时候就可以复用etcd集群,比如北显和亦庄机房的注册,可以使用改变默认etcd键值目录来实现:

prefix = "/service_sgin_bx" 
prefix  =  "/service_sgin_yz"

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

这个同样,看起来复杂,其实confd改一下模式就能实现,不要用watch模式,改而周期性去探测etcd的键值变化,比如说2秒探测一次,对应启动时的命令如下:

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

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

同样,只要修改下confd的启动命令即可,让confd监控更多node,我目前的etcd有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

五、权限问题的处理

对于权限有两种方式,一个是证书,一个是账号,业务本就跑到内网,再加之账号的配合是灵活迅速的,就从账号着手了,对于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身份监控k/v的,对应的规则就是guest;

后附1:etcd的集群配置,扩容

假设初始化3台etcd分别是10.211.103.152、10.211.103.153、10.211.103.154,etcd下载下来就可以用,主要是如何配置启动,分别再三台机器上编写如下启动脚本etcdnew.sh,然后依次启动即可:
10.211.103.152服务器:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd152 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.152:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.152:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd152=http://10.211.103.152:2380,etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380 \
--initial-cluster-state new  &

10.211.103.153服务器:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd153 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.153:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.153:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd152=http://10.211.103.152:2380,etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380 \
--initial-cluster-state new   &

10.211.103.154服务器:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd154 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.154:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.154:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd152=http://10.211.103.152:2380,etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380 \
--initial-cluster-state new  &

启动后可以看到集群成员和健康情况如下:
在这里插入图片描述

添加、删除etcd集群节点操作:

比如添加10.211.103.151节点

etcdctl member add etcd151 http://10.211.103.151:2380

执行命令后会有提示,然后再151上编写如下脚本etcdadd.sh:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd151 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.151:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.151:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380,etcd151=http://10.211.103.151:2380,etcd152=http://10.211.103.152:2380 \
--initial-cluster-state existing   &

删除节点的话执行如下命令:

etcdctl member remove cf5e47596c46611a #通过etcdctl member list 查看到id

后附2:etcd的api 2和api 3的转换及confd的使用转换

1、etcd通过环境变量的调整来修改

export ETCDCTL_API=2   #api2版本
export ETCDCTL_API=3   #api3版本

2、confd通过监控时的参数修改
下载二进制文件直接使用: https://github.com/bacongobbler/confd/releases

-backend etcdv3  即 etcd api v3
-backend etcd    即 etcd api v2

这篇关于基于etcd+confd通过nginx对docker服务注册发现详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/248766

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Nginx设置连接超时并进行测试的方法步骤

《Nginx设置连接超时并进行测试的方法步骤》在高并发场景下,如果客户端与服务器的连接长时间未响应,会占用大量的系统资源,影响其他正常请求的处理效率,为了解决这个问题,可以通过设置Nginx的连接... 目录设置连接超时目的操作步骤测试连接超时测试方法:总结:设置连接超时目的设置客户端与服务器之间的连接

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I