You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2021/06/30 08:24:59 UTC

[apisix-website] branch master updated: docs: added etcd3 support HTTP access perfectly blog (#396)

This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-website.git


The following commit(s) were added to refs/heads/master by this push:
     new d031a7a  docs: added etcd3 support HTTP access perfectly blog (#396)
d031a7a is described below

commit d031a7a5a3e1e94788530e8366b593cab0060aea
Author: Serendipity96 <ru...@outlook.com>
AuthorDate: Wed Jun 30 16:24:50 2021 +0800

    docs: added etcd3 support HTTP access perfectly blog (#396)
---
 ...21-06-30-etcd3-support-HTTP-access-perfectly.md |  96 +++++++++++++++++++++
 website/static/img/blog_img/2021-06-30-1.png       | Bin 0 -> 222248 bytes
 website/static/img/blog_img/2021-06-30-2.png       | Bin 0 -> 199227 bytes
 3 files changed, 96 insertions(+)

diff --git a/website/blog/2021-06-30-etcd3-support-HTTP-access-perfectly.md b/website/blog/2021-06-30-etcd3-support-HTTP-access-perfectly.md
new file mode 100644
index 0000000..236dc49
--- /dev/null
+++ b/website/blog/2021-06-30-etcd3-support-HTTP-access-perfectly.md
@@ -0,0 +1,96 @@
+---
+title: "差之毫厘:etcd 3 完美支持 HTTP 访问?"
+author: spacewander
+authorURL: "https://github.com/spacewander"
+authorImageURL: "https://avatars.githubusercontent.com/u/4161644?v=4"
+---
+> [@spacewander](https://github.com/spacewander), Core developer of Apache APISIX from [Shenzhen Zhiliu Technology Co.](https://www.apiseven.com/)
+>
+<!--truncate-->
+
+etcd 升级到 3.x 版本后,其对外 API 的协议从普通的 HTTP1 切换到了 gRPC。为了兼顾那些不能使用 gRPC 的特殊群体,etcd 通过 gRPC-gateway 的方式代理 HTTP1 请求,以 gRPC 形式去访问新的 gRPC API。(由于 HTTP1 念起来太过拗口,以下将之简化成 HTTP,正好和 gRPC 能够对应。请不要纠结 gRPC 也是 HTTP 请求的这种问题。)
+
+Apache APISIX 开始用 etcd 的时候,用的是 etcd v2 的 API。从 Apache APISIX 2.0 版本起,我们把依赖的 etcd 版本升级到 3.x。由于 Lua 生态圈里面没有 gRPC 库,所以 etcd 对 HTTP 的兼容帮了我们很大的忙,这样就不用花很大心思去补这个短板了。
+
+从去年 10 月发布 Apache APISIX 2.0 版本以来,现在已经过去了 8 个月。在实践过程中,我们也发现了 etcd 的 HTTP API 的一些跟 gRPC API 交互的问题。事实上,拥有 gRPC-gateway 并不意味着能够完美支持 HTTP 访问,这里还是有些细微的差别。
+
+### 打破 gRPC 的默认限制
+
+就在几天前,etcd 发布了 v3.5.0 版本。这个版本的发布,了却困扰我们很长时间的一个问题。
+
+跟 HTTP 不同的是,gRPC 默认限制了一次请求可以读取的数据大小。这个限制叫做 “MaxCallRecvMsgSize”,默认是 4MiB。当 Apache APISIX 全量同步 etcd 数据时,假如配置够多,就会触发这一上限,报错 “grpc: received message larger than max”。
+
+神奇的是,如果你用 etcdctl 去访问,这时候却不会有任何问题。这是因为这个限制是可以在跟 gRPC server 建立连接时动态设置的,etcdctl 给这个限制设置了一个很大的整数,相当于去掉了这一限制。
+
+由于不少用户碰到过同样的问题,我们曾经讨论过对策。
+
+一个想法是用增量同步模拟全量同步,这么做有两个弊端:
+
+1. 实现起来复杂,要改不少代码
+2. 会延长同步所需的时间
+
+另一个想法是修改 etcd。既然能够在 etcdctl 里面去除限制,为什么不对 gRPC-gateway 一视同仁呢?同样的改动可以作用在 gRPC-gateway 上。
+
+我们采用了第二种方案,给 etcd 提了个 PR:https://github.com/etcd-io/etcd/pull/13077
+
+![2021-06-30-1](../static/img/blog_img/2021-06-30-1.png)
+
+最新发布的 v3.5.0 版本就包含了我们贡献的这个改动。如果你遇到 “grpc: received message larger than max”,不妨试一下这个版本。这一改动也被 etcd 开发者 backport 到 3.4 分支上了。3.4 分支的下一个发布,也会带上这个改动。
+
+这件事也说明 gRPC-gateway 并非百试百灵。即使用了它,也不能保证 HTTP 访问能够跟 gRPC 访问有一样的体验。
+
+### 对服务端证书的有趣用法
+
+Apache APISIX 增加了对 etcd mTLS 的支持后,有用户反馈一直没法完成校验,而用 etcdctl 访问则是成功的。在跟用户交流后,我决定拿他的证书来复现下。
+
+在复现过程中,我注意到 etcd 日志里面有这样的报错:
+
+``` text
+2021-06-09 11:10:13.022735 I | embed: rejected connection from "127.0.0.1:50898" (error "tls: failed to verify client's certificate: x509: certificate specifies an incompatible key usage", ServerName "")
+WARNING: 2021/06/09 11:10:13 grpc: addrConn.createTransport failed to connect to {127.0.0.1:12379 0 }. Err :connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate". Reconnecting...
+```
+
+“bad certificate” 错误信息,初看像是因为我们发给 etcd 的客户端证书不对。但仔细瞧瞧,会发现这个报错是在 gRPC server 里面报的。
+
+gRPC-gateway 在 etcd 里面起到一个代理的作用,把外面的 HTTP 请求变成 gRPC server 能处理的 gRPC 请求。
+
+大体架构如下:
+
+```text
+etcdctl ----> gRPC server
+Apache APISIX ---> gRPC-gateway ---> gRPC server
+```
+
+为什么 etcdctl 直连 gRPC server 能通,而中间加一层 gRPC-gateway 就不行?
+
+原来当 etcd 启用了客户端证书校验之后,用 gRPC-gateway 连接 gRPC server 就需要提供一个客户端证书。猜猜这个证书从哪来?
+
+etcd 把配置的服务端证书直接作为这里的客户端证书用了。
+
+一个证书既在服务端上提供验证,又在客户端上表明身份,看上去也没什么问题。除非……
+
+除非证书上启用了 server auth 的拓展,但是没有启用 client auth。
+
+对有问题的证书执行`openssl x509 -text -noout -in /tmp/bad.crt`
+
+会看到这样的输出:
+
+```text
+X509v3 extensions:
+X509v3 Key Usage: critical
+Digital Signature, Key Encipherment
+X509v3 Extended Key Usage:
+TLS Web Server Authentication
+```
+
+注意这里的 “TLS Web Server Authentication”,如果我们把它改成 “TLS Web Server Authentication, TLS Web Client Authentication”,抑或不加这个拓展,就没有问题了。
+
+etcd 上也有关于这个问题的 issue:https://github.com/etcd-io/etcd/issues/9785
+
+![2021-06-30-2](../static/img/blog_img/2021-06-30-2.png)
+
+### 结语
+
+虽然我们在上文列出了几点小问题,但是瑕不掩瑜,etcd 对 HTTP 访问的支持还是一个非常有用的特性。
+
+感谢 Apache APISIX 的用户们,正是因为我们有着广阔的用户群,才能发现 etcd 的这些细节上的问题。我们作为 etcd 的一大用户,在之后的日子里也将一如既往地跟 etcd 的开发者多多交流。
diff --git a/website/static/img/blog_img/2021-06-30-1.png b/website/static/img/blog_img/2021-06-30-1.png
new file mode 100644
index 0000000..c0a18f4
Binary files /dev/null and b/website/static/img/blog_img/2021-06-30-1.png differ
diff --git a/website/static/img/blog_img/2021-06-30-2.png b/website/static/img/blog_img/2021-06-30-2.png
new file mode 100644
index 0000000..a8b05e6
Binary files /dev/null and b/website/static/img/blog_img/2021-06-30-2.png differ