惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - Franky
有赞技术团队
有赞技术团队
博客园 - 司徒正美
量子位
N
News and Events Feed by Topic
T
Threatpost
Last Week in AI
Last Week in AI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
酷 壳 – CoolShell
酷 壳 – CoolShell
C
CERT Recently Published Vulnerability Notes
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
I
Intezer
人人都是产品经理
人人都是产品经理
T
Tenable Blog
IT之家
IT之家
雷峰网
雷峰网
腾讯CDC
博客园 - 聂微东
V
Visual Studio Blog
S
SegmentFault 最新的问题
Scott Helme
Scott Helme
Spread Privacy
Spread Privacy
月光博客
月光博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
爱范儿
爱范儿
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
N
Netflix TechBlog - Medium
J
Java Code Geeks
宝玉的分享
宝玉的分享
F
Full Disclosure
WordPress大学
WordPress大学
A
Arctic Wolf
小众软件
小众软件
AWS News Blog
AWS News Blog
Attack and Defense Labs
Attack and Defense Labs
NISL@THU
NISL@THU
AI
AI
Hugging Face - Blog
Hugging Face - Blog
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
N
News | PayPal Newsroom
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19) 使用 Velero 备份 Kubernetes 集群 Kubernetes Cheat Sheet 开发 Tips(18) 如何构建一个 Java 工程 开发 Tips(17) KubeSpray 安装 Kubernetes 报错 ip in ansible_all_ipv4_addresses 基于 Kubernetes 和 Jenkins 搭建自动化测试系统 在 Kubernetes 上动态创建 Jenkins Slave 使用 Jenkins 进行服务拨测 开发 Tips(16) Kubernetes 签发 Ingress 证书及日常故障运维 Kubernetes 中 Deployment 的基本操作 Kubernetes 中的证书 如何使用 KubeBuilder 开发一个 Operator Kubernetes 1.6.0 安装问题汇总 镜像管理工具 -- Harbor 开发 Tips(15) Docker 如何拉取镜像 开发 Tips(14) 使用 Helm 安装 harbor 开发 Tips(13) 使用 S2I 构建云原生应用 在 Kubernetes 中使用 emptyDir、hostPath、localVolume 开发 Tips(12) 开发 Tips(11) 代码质量分析工具 SonarQube 使用 Kubeadm 安装 Kubernetes 集群 一起来学 Go --(4)常用函数 Kubernetes 中的 Ceph Kubernetes 之 Volumes Kubernetes 之 Labels、Selectors 开发 Tips(10) 开源正在重构商业模式 Kubernetes 之网络 Kubernetes 之 API 使用 Helm 和 Operator 快速部署 Prometheus Kubernetes 复杂有状态应用管理框架 -- Operator Kubernetes 的包管理器 -- Helm 一起来学 Go --(3)Go Modules 如何一步一步地优化博客方案 kubectl 实用指南 Kubernetes 中的基本概念 搭建远程 Kubernetes 开发环境 大公司和小公司的 ToB 思路 开发 Tips(9) Go 入门指南 一起来学 Go --(2)数据与逻辑结构 如何预防 Web 富文本中的 XSS 攻击 django-xss-cleaner 云工作时代 一起来学 Go --(1)背景与特点 SaaS 开发团队的不同阶段 你不知道的 Git 使用技巧 输出既服务 微服务设计 继续奔跑 开发 Tips(8) 从账户安全到二次验证 Django 性能之数据库查询优化 Django 性能之分库分表 敏捷开发之研发流程 打造一致性的团队 开发 Tips(7) Pytest 进阶学习之 Mock PaaS 部署之 buildpack Go 开发配置 领域输出才是 PaaS 的核心竞争力 Pytest 入门学习 开发 Tips(6) 如何使用 Jenkins、Docker、GitLab 搭建 Django 自动化部署流程
Etcd、Confd 、Nginx 服务发现
微信公众号 · 2018-02-08 · via 陈少文的网站

本篇主要阐述了为什么需要服务发现功能,对几种服务发现工具进行了比较。同时,在 CentOS 上,对 Etcd、Confd 、Nginx 实现服务发现功能进行了实践。

1. 服务注册与发现

1.1 为什么需要注册和发现服务

随着微服务的兴起,大量接口服务化。当新的微服务加入或微服务的信息发生变更时,服务方如何通知周边系统、使用方如何知道这些变更呢?

这时就需要服务的注册配置和发现功能。

  • 服务注册配置——存储的信息至少包括正在运行的服务的主机和端口信息
  • 服务发现——允许其他用户可以发现在服务注册配置阶段存储的信息。

1.2 几种服务发现工具的比较

FeatureConsulZookeeperEtcdEuerka
服务健康检查服务状态,内存,硬盘等(弱)长连接,keepalive连接心跳可配支持
多数据中心支持
kv存储服务支持支持支持
一致性raftpaxosraft
capcacpcpap
使用接口(多语言能力)支持http和dns客户端http/grpchttp(sidecar)
watch支持全量/支持long polling支持支持 long polling支持 long polling/大部分增量
自身监控metricsmetricsmetrics
安全acl /httpsaclhttps支持(弱)
spring cloud集成已支持已支持已支持已支持
注:
- C,强一致性 (Consistency)
- A,可用性 (Availability)
- P,网络分区故障的容错性 (Partition Tolerance)

Consul 是使用 Go 语言开发的分布式协调系统,对业务发现的管理提供很好的支持,它的 HTTP API 也能很好的和不同的语言绑定,并支持跨数据中心的应用。缺点是相对较新,适合喜欢尝试新事物的用户。

ZooKeeper 功能全,社区活跃,用户群体很大,对所有典型的用例都有很好的封装,支持不同语言的绑定。缺点是,整个应用比较重,依赖于 Java,不支持跨数据中心。

Etcd 是一个更轻量级的分布式协调的应用,更适合一些轻量级的应用来使用,同时 Etcd 也提供 HTTP API 操作接口。值得注意的是,Kubernetes 采用了 Etcd 作为配置中心。

Eureka 是 Netflix 开源的一个 RESTful 服务,主要用于服务的注册发现。Eureka 由两个组件组成:Eureka 服务器和 Eureka 客户端。Eureka 服务器用作服务注册服务器。Eureka 客户端是一个 Java 客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。

2. Etcd

2.1 简介

Etcd 是一个分布式、使用 Raft 算法维护一致性的 key-value 存储系统,与其类似产品有 Zookeeper、Consul 等,Etcd 相对 Zookeeper,更加轻量、易运维。同时,Etcd 支持 TLS 通信,具备高性能的写入能力。

2.2 Raft 算法

很多的分布式系统都会采用 Paxos 协议,但是 Paxos 协议难以理解,并且在实际实现中差别比较大。所以 Etcd 选择了 Raft 作为它的一致性协议。Raft 是 Diego Ongaro 和 John Ousterhout 在 In Search of an Understandable Consensus Algorithm 中提出的。它在牺牲很少可用性,达到相似功能的情况下,对 Paxos 做了很大的优化,并且比 Paxos 简单易懂很多。

它主要集中在解决两个问题:

  • 领导者选举(Leader Election)
    Raft 先通过领导选举选出一个 Leader,后续的一致性维护都由 Leader 来完成,这就简化了一致性的问题。Raft 会保证一个时间下只会有一个 Leader,并且在超过一半节点投票的情况下才会被选为 Leader。当 Leader 挂掉的时候,新的 Leader 将会被选出来。

  • 日志复制 (Log Replication)
    为了维护状态,系统会记录下来所有的操作命令日志。Leader 在收到客户端操作命令后,会追加到日志的尾部。然后 Leader 会向集群里所有其它节点发送 AppendEntries RPC 请求,每个节点都通过两阶段提交来复制命令,这保证了大部分的节点都能完成。

3. Etcd + Confd + Nginx

在进行应用部署时,服务运行起来后,通过接口向 Etcd 注册相关 key-value 信息,Confd 检测到 Etcd 的 key-value 变化后,立即触发程序通过模板形成新的 Nginx 配置文件。

Nginx 先做离线语法测试,如果没问题就覆盖原配置,进而 reload,测试不通过就不覆盖原配置,整个过程安全可控。

3.1 Nginx 安装配置

  • 安装以 CentOS 为例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 安装 nginx
yum install -y nginx
# 查看 nginx 安装位置
whereis nginx
nginx: /usr/sbin/nginx /usr/lib64/nginx /etc/nginx /usr/share/nginx /usr/share/man/man3/nginx.3pm.gz /usr/share/man/man8/nginx.8.gz
# 查看 nginx 配置文件位置
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# 查看配置
cat /etc/nginx/nginx.conf
...
    include /etc/nginx/conf.d/*.conf;
...

include /etc/nginx/conf.d/*.conf; 这句配置会将 conf.d 目录下 .conf 后缀的文件配置载入 Nginx。

3.2 Confd 安装配置

直接从 github 下载 Confd 的 Linux 编译版本,然后将可执行文件移动到 /usr/sbin/ 目录即可。

1
2
3
4
5
6
# 下载 Confd 包
wget https://github.com/kelseyhightower/confd/releases/download/v0.15.0/confd-0.15.0-linux-amd64
# 复制可执行文件
mv confd-0.15.0-linux-amd64 /usr/sbin/confd
# 增加可执行权限
chmod +x /usr/sbin/confd

3.3 Etcd 安装配置

  • 安装以 CentOS 为例
  • 配置文件目录,/etc/etcd/etcd.conf
1
2
3
4
5
# 默认配置,可以不修改
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"
  • 启动服务

3.4 Confd 安装配置

  • 创建配置目录
1
mkdir -p /etc/confd/{conf.d,templates}

在 conf.d 下创建 .toml 配置文件

/etc/confd/conf.d/app1.toml

1
2
3
4
5
6
7
8
[template]
prefix = "/app1"
src = "subdomain.conf.tmpl"
dest = "/tmp/app1-subdomain-confd-auto.conf"
keys = [
  "/subdomain",
  "/upstream",
]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[template]
prefix = "/app1"
src = "subdomain-nginx.conf.tmpl"
dest = "/etc/nginx/conf.d/app1-subdomain-confd-nginx-auto.conf"
keys = [
  "/subdomain",
  "/upstream",
]
check_cmd = "/usr/sbin/nginx -t"
reload_cmd = "/usr/sbin/nginx -s reload"

在 templates 下创建 .tmpl 模板文件

/etc/confd/templates/subdomain.conf.tmpl

1
2
3
[subdomain]
subdomain = {{getv "/subdomain"}}
upstream = {{getv "/upstream"}}

Nginx 模板配置

/etc/confd/templates/subdomain-nginx.conf.tmpl

upstream {{getv "/subdomain"}} {
{{range getvs "/upstream/*"}}
    server {{.}};
{{end}}
}

server {
    server_name  {{getv "/subdomain"}}.example.com;
    location / {
        proxy_pass        http://{{getv "/subdomain"}};
        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;
   }
}

监听 Etcd 的 key-value 值的变化

1
2
3
4
# 只处理一次
confd -onetime -backend etcd -node http://127.0.0.1:2379
# 按时间轮询
confd -interval=60 -backend etcd -node http://127.0.0.1:2379 &

3.5 注册服务

可以通过 etcdctl 命令,也可以通过 Etcd 提供的 HTTP API,在 Etcd 插入 subdomain 和 upstream 数据。下面以 etcdctl 为例:

1
2
etcdctl set /app1/subdomain app1
etcdctl set /app1/upstream/instance1 "127.0.0.1:5601"

由于在本地 5601 端口,启动了 ELK 服务,通过访问 http://app1.example.com 打开 Kibana 。

如果需要 Nginx 进行负载均衡,可以在 upstream 上配置多个键值。同时,需要在 /etc/confd/conf.d 目录下新建两个文件 app2-nginx.toml 和 app2.toml,内容上只需要将 app1-nginx.toml 和 app1.toml 中的 app1 修改为 app2 即可。

1
2
3
etcdctl set /app2/subdomain app2
etcdctl set /app2/upstream/instance1 "127.0.0.2:80"
etcdctl set /app2/upstream/instance2 "127.0.0.1:80"

4. 参考