add cloud native communnity

pull/398/head
Jimmy song 2020-05-08 23:22:37 +08:00
parent 4bd1076a58
commit 4c95a6c073
10 changed files with 615 additions and 840 deletions

View File

@ -1,6 +1,8 @@
# Kubernetes Handbook——Kubernetes中文指南/云原生应用架构实践手册
[Kubernetes](http://kubernetes.io)是Google基于[Borg](https://research.google.com/pubs/pub43438.html)开源的容器编排调度引擎,作为[CNCF](https://cncf.io)Cloud Native Computing Foundation最重要的组件之一它的目标不仅仅是一个编排系统而是提供一个规范可以让你来描述集群的架构定义服务的最终状态Kubernetes可以帮你将系统自动地达到和维持在这个状态。Kubernetes作为云原生应用的基石相当于一个云操作系统其重要性不言而喻。
[Kubernetes](http://kubernetes.io)是Google基于其内部使用的[Borg](https://research.google.com/pubs/pub43438.html)系统开源出来的容器编排调度引擎Google 将其作为初始和核心项目贡献给[CNCF](https://cncf.io)(云原生计算基金会),近年来逐渐发展出了云原生生态。
Kubernetes的目标不仅仅是一个编排系统而是提供一个规范用以描述集群的架构定义服务的最终状态使系统自动地达到和维持该状态。Kubernetes作为云原生应用的基石相当于一个云操作系统其重要性不言而喻。
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括**容器**、**服务网格**、**微服务**、**不可变基础设施**和**声明式API**。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。——CNCF云原生计算基金会
@ -18,7 +20,7 @@
</a>
</p>
本书开源于2017年3月是第一本系统整理的开源中文版Kubernetes参考资料记录了本人从零开始学习和使用Kubernetes的历程着重于总结和资料分享同时也会有相关的概念解析希望能够帮助大家少踩坑少走弯路还会指引大家关注Kubernetes生态周边如微服务构建、DevOps、大数据应用、[Service Mesh](https://jimmysong.io/blog/what-is-a-service-mesh/)、Cloud Native等领域。
Kubernetes Handbook开源于2017年3月并在其后不断完善是第一本系统介绍Kubernetes的中文书籍。写作本书的过程中笔者记录了从零开始学习和使用Kubernetes的历程着重于经验总结和资料分享亦有Kubernetes核心概念解析希望能够帮助大家少走弯路为大家介绍Kubernetes周边生态如微服务、DevOps、大数据应用、[Service Mesh](https://jimmysong.io/blog/what-is-a-service-mesh/)、[OAM](https://oam.dev)、Serverless等领域。
### 开始之前
@ -50,8 +52,6 @@
- 按照[说明](https://github.com/rootsongjc/kubernetes-handbook/blob/master/CODE_OF_CONDUCT.md)自行编译成离线版本
- Fork 一份添加你自己的笔记自行维护,有余力者可以一起参与进来
**注意Service Mesh 已成立独立的 [istio-handbook](https://www.servicemesher.com/istio-handbook),本书中的 Service Mesh 相关内容已不再维护。**
## 快速开始
如果您想要学习Kubernetes和云原生应用架构但是又不想自己从头开始搭建和配置一个集群那么可以直接使用[kubernetes-vagrant-centos-cluster](https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster)项目直接在本地部署一个3节点的分布式集群及其他如Heapster、EFK、Istio等可选组件或者使用更加轻量级的[cloud-native-sandbox](https://github.com/rootsongjc/cloud-native-sandbox)在个人电脑上使用Docker运行单节点的Kubernetes、Istio等组件。
@ -76,10 +76,11 @@
[![Stargazers over time](https://starcharts.herokuapp.com/rootsongjc/kubernetes-handbook.svg)](https://starcharts.herokuapp.com/rootsongjc/kubernetes-handbook)
## 社区&读者交流
## 云原生社区
- [云原生社区](https://cloudnative.to/contact/)
- [知乎专栏:云原生应用架构](https://zhuanlan.zhihu.com/cloud-native)
云原生社区是一个有技术、有温度、有情怀的开源社区,由 [Jimmy 和他的伙伴们](https://cloudnative.to/team)发起与 2020 年 2 月,秉持“共识、共治、共建、共享”的原则。立足中国,面向世界,企业中立,旨在借助开源打破企业的边界,关注技术人的成长,促进中国云原生开源的发展。
如果您也有志于投身云原生的历史洪流中,不要犹豫,[加入我们](https://cloudnative.to/contact/)
## 云原生出版物
@ -93,12 +94,13 @@
## 推荐
- [极客时间专栏《深入剖析 Kubernetes](https://tva1.sinaimg.cn/large/006y8mN6ly1g7vf4p12rpj30u01hdjwp.jpg)快速入门学习 Kubernetes
- [深入剖析 Kubernetes](https://tva1.sinaimg.cn/large/006y8mN6ly1g7vf4p12rpj30u01hdjwp.jpg)极客时间推出的 Kubernetes 专栏
- [深入浅出云计算](https://time.geekbang.org/column/intro/292?code=EhFrzVKvIro8U06UyaeLCCdmbpk7g010iXprzDxW17I%3D&utm_term=SPoster):云原生时代给开发者和架构师的云计算指南
- [《Istio Handbook——Istio 服务网格进阶实战》](https://www.servicemesher.com/istio-handbook/)ServiceMesher 社区出品的开源电子书
## 支持本书
为云原生干杯🍻!使用微信扫一扫请我喝一杯☕️
如果您觉得本书给您带来帮助,可以使用微信扫一扫请我喝杯☕️,谢谢!
<p align="center">
<img src="images/wechat-appreciate-qrcode.jpg" alt="微信赞赏码"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
images/iptables.jpg 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -10,3 +10,4 @@ CNCF 提出了分布式追踪的标准 [OpenTracing](https://opentracing.io/)
- [OpenTracing 官方网站](https://opentracing.io/)
- [Jaeger 官方网站](https://www.jaegertracing.io/)
- [Apache SkyWalking 官方网站](https://skywalking.apache.org/)

View File

@ -1,5 +1,7 @@
# 使用Helm管理kubernetes应用
**本文基于 Helm v2待更新 Helm v3 的说明。**
读完本文后您应该可以自己创建chart并创建自己的私有chart仓库。
[Helm](http://helm.sh)是一个kubernetes应用的包管理工具用来管理[charts](https://github.com/kubernetes/charts)——预先配置好的安装包资源有点类似于Ubuntu的APT和CentOS中的yum。

View File

@ -1,6 +1,6 @@
# 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由转发
**注意:本文基于 Istio 1.0。**
**注意:本文基于 Istio 1.5。**
本文以 Istio 官方的 bookinfo 示例来讲解在进入 Pod 的流量被 iptables 转交给 Envoy sidecar 后Envoy 是如何做路由转发的,详述了 Inbound 和 Outbound 处理过程。关于流量拦截的详细分析请参考[理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持](understand-sidecar-injection-and-traffic-hijack-in-istio-service-mesh.md)。
@ -8,362 +8,4 @@
![Bookinfo 示例](../images/006tNbRwgy1fvlwjd3302j31bo0ro0x5.jpg)
下面是 Istio 自身组件与 Bookinfo 示例的连接关系图,我们可以看到所有的 HTTP 连接都在 9080 端口监听。
![Bookinfo 示例与 Istio 组件连接关系图](../images/006tNbRwly1fyitp0jsghj31o70u0x6p.jpg)
可以在 [Google Drive](https://drive.google.com/open?id=19ed3_tkjf6RgGboxllMdt_Ytd5_cocib) 上下载原图。
## Sidecar 注入及流量劫持步骤概述
下面是从 Sidecar 注入、Pod 启动到 Sidecar proxy 拦截流量及 Envoy 处理路由的步骤概览。
**1.** Kubernetes 通过 Admission Controller 自动注入,或者用户使用 `istioctl` 命令手动注入 sidecar 容器。
**2.** 应用 YAML 配置部署应用,此时 Kubernetes API server 接收到的服务创建配置文件中已经包含了 Init 容器及 sidecar proxy。
**3.** 在 sidecar proxy 容器和应用容器启动之前,首先运行 Init 容器Init 容器用于设置 iptablesIstio 中默认的流量拦截方式,还可以使用 BPF、IPVS 等方式) 将进入 pod 的流量劫持到 Envoy sidecar proxy。所有 TCP 流量Envoy 目前只支持 TCP 流量)将被 sidecar 劫持,其他协议的流量将按原来的目的地请求。
**4.** 启动 Pod 中的 Envoy sidecar proxy 和应用程序容器。这一步的过程请参考[通过管理接口获取完整配置](https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/#%E9%80%9A%E8%BF%87%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3%E8%8E%B7%E5%8F%96%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE)。
> **Sidecar proxy 与应用容器的启动顺序问题**
>
> 启动 sidecar proxy 和应用容器,究竟哪个容器先启动呢?正常情况是 Envoy Sidecar 和应用程序容器全部启动完成后再开始接收流量请求。但是我们无法预料哪个容器会先启动,那么容器启动顺序是否会对 Envoy 劫持流量有影响呢?答案是肯定的,不过分为以下两种情况。
>
> **情况1应用容器先启动而 sidecar proxy 仍未就绪**
>
> 这种情况下,流量被 iptables 转移到 15001 端口,而 Pod 中没有监听该端口TCP 链接就无法建立,请求失败。
>
> **情况2Sidecar 先启动,请求到达而应用程序仍未就绪**
>
> 这种情况下请求也肯定会失败,至于是在哪一步开始失败的,留给读者来思考。
**问题**:如果为 sidecar proxy 和应用程序容器添加[就绪和存活探针](https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html)是否可以解决该问题呢?
**5.** 不论是进入还是从 Pod 发出的 TCP 请求都会被 iptables 劫持inbound 流量被劫持后经 Inbound Handler 处理后转交给应用程序容器处理outbound 流量被 iptables 劫持后转交给 Outbound Handler 处理,并确定转发的 upstream 和 Endpoint。
**6.** Sidecar proxy 请求 Pilot 使用 xDS 协议同步 Envoy 配置,其中包括 LDS、EDS、CDS 等不过为了保证更新的顺序Envoy 会直接使用 ADS 向 Pilot 请求配置更新。
## Envoy 如何处理路由转发
下图展示的是 `productpage` 服务请求访问 `http://reviews.default.svc.cluster.local:9080/`,当流量进入 `reviews` 服务内部时,`reviews` 服务内部的 Envoy Sidecar 是如何做流量拦截和路由转发的。可以在 [Google Drive](https://drive.google.com/file/d/1n-h235tm8DnL_RqxTTA95rgGtrLkBsyr/view?usp=sharing) 上下载原图。
![Envoy sidecar 流量劫持与路由转发示意图](../images/006tNbRwly1fyl39icd27j31c70u04gc.jpg)
第一步开始时,`productpage` Pod 中的 Envoy sidecar 已经通过 EDS 选择出了要请求的 `reviews` 服务的一个 Pod知晓了其 IP 地址,发送 TCP 连接请求。
Istio 官网中的 Envoy 配置深度解析中是以发起 HTTP 请求的一方来详述 Envoy 做流量转发的过程,而本文中考虑的是接受 downstream 的流量的一方,它既要接收 downstream 发来的请求,自己还需要请求其他服务,例如 `reviews` 服务中的 Pod 还需要请求 `ratings` 服务。
`reviews` 服务有三个版本,每个版本有一个实例,三个版本中的 sidecar 工作步骤类似,下文只以 `reviews-v1-cb8655c75-b97zc` 这一个 Pod 中的 Sidecar 流量转发步骤来说明。
## 理解 Inbound Handler
Inbound handler 的作用是将 iptables 拦截到的 downstream 的流量转交给 localhost与 Pod 内的应用程序容器建立连接。
查看下 `reviews-v1-cb8655c75-b97zc` pod 中的 Listener。
运行 `istioctl pc listener reviews-v1-cb8655c75-b97zc` 查看该 Pod 中的具有哪些 Listener。
```ini
ADDRESS PORT TYPE
172.33.3.3 9080 HTTP <--- Inbound HTTP Pod IP
10.254.0.1 443 TCP <--+
10.254.4.253 80 TCP |
10.254.4.253 8080 TCP |
10.254.109.182 443 TCP |
10.254.22.50 15011 TCP |
10.254.22.50 853 TCP |
10.254.79.114 443 TCP |
10.254.143.179 15011 TCP |
10.254.0.2 53 TCP | 接收与 0.0.0.0_15001 监听器配对的 Outbound 非 HTTP 流量
10.254.22.50 443 TCP |
10.254.16.64 42422 TCP |
10.254.127.202 16686 TCP |
10.254.22.50 31400 TCP |
10.254.22.50 8060 TCP |
10.254.169.13 14267 TCP |
10.254.169.13 14268 TCP |
10.254.32.134 8443 TCP |
10.254.118.196 443 TCP <--+
0.0.0.0 15004 HTTP <--+
0.0.0.0 8080 HTTP |
0.0.0.0 15010 HTTP |
0.0.0.0 8088 HTTP |
0.0.0.0 15031 HTTP |
0.0.0.0 9090 HTTP |
0.0.0.0 9411 HTTP | 接收与 0.0.0.0_15001 配对的 Outbound HTTP 流量
0.0.0.0 80 HTTP |
0.0.0.0 15030 HTTP |
0.0.0.0 9080 HTTP |
0.0.0.0 9093 HTTP |
0.0.0.0 3000 HTTP |
0.0.0.0 8060 HTTP |
0.0.0.0 9091 HTTP <--+
0.0.0.0 15001 TCP <--- iptables Inbound Outbound
```
当来自 `productpage` 的流量抵达 `reviews` Pod 的时候已经downstream 必须明确知道 Pod 的 IP 地址为 `172.33.3.3` 所以才会访问该 Pod所以该请求是 `172.33.3.3:9080`
**`virtual` Listener**
从该 Pod 的 Listener 列表中可以看到0.0.0.0:15001/TCP 的 Listener其实际名字是 `virtual`)监听所有的 Inbound 流量,下面是该 Listener 的详细配置。
```json
{
"name": "virtual",
"address": {
"socketAddress": {
"address": "0.0.0.0",
"portValue": 15001
}
},
"filterChains": [
{
"filters": [
{
"name": "envoy.tcp_proxy",
"config": {
"cluster": "BlackHoleCluster",
"stat_prefix": "BlackHoleCluster"
}
}
]
}
],
"useOriginalDst": true
}
```
**UseOriginalDst**:从配置中可以看出 `useOriginalDst` 配置指定为 `true`,这是一个布尔值,缺省为 false使用 iptables 重定向连接时proxy 接收的端口可能与[原始目的地址](http://www.servicemesher.com/envoy/configuration/listener_filters/original_dst_filter.html)的端口不一样,如此处 proxy 接收的端口为 15001而原始目的地端口为 9080。当此标志设置为 true 时Listener 将连接重定向到与原始目的地址关联的 Listener此处为 `172.33.3.3:9080`。如果没有与原始目的地址关联的 Listener则连接由接收它的 Listener 处理,即该 `virtual` Listener经过 `envoy.tcp_proxy` 过滤器处理转发给 `BlackHoleCluster`,这个 Cluster 的作用正如它的名字,当 Envoy 找不到匹配的虚拟监听器时,就会将请求发送给它,并返回 404。这个将于下文提到的 Listener 中设置 `bindToPort` 相呼应。
**注意**:该参数将被废弃,请使用[原始目的地址](http://www.servicemesher.com/envoy/configuration/listener_filters/original_dst_filter.html)的 Listener filter 替代。该参数的主要用途是Envoy 通过监听 15001 端口将 iptables 拦截的流量经由其他 Listener 处理而不是直接转发出去,详情见 [Virtual Listener](https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/#virtual-listener)。
**Listener 172.33.3.3_9080**
上文说到进入 Inbound handler 的流量被 `virtual` Listener 转移到 `172.33.3.3_9080` Listener我们在查看下该 Listener 配置。
运行 `istioctl pc listener reviews-v1-cb8655c75-b97zc --address 172.33.3.3 --port 9080 -o json` 查看。
```json
[{
"name": "172.33.3.3_9080",
"address": {
"socketAddress": {
"address": "172.33.3.3",
"portValue": 9080
}
},
"filterChains": [
{
"filterChainMatch": {
"transportProtocol": "raw_buffer"
},
"filters": [
{
"name": "envoy.http_connection_manager",
"config": {
...
"route_config": {
"name": "inbound|9080||reviews.default.svc.cluster.local",
"validate_clusters": false,
"virtual_hosts": [
{
"domains": [
"*"
],
"name": "inbound|http|9080",
"routes": [
{
...
"route": {
"cluster": "inbound|9080||reviews.default.svc.cluster.local",
"max_grpc_timeout": "0.000s",
"timeout": "0.000s"
}
}
]
}
]
},
"use_remote_address": false,
...
}
}
]
"deprecatedV1": {
"bindToPort": false
}
...
},
{
"filterChainMatch": {
"transportProtocol": "tls"
},
"tlsContext": {...
},
"filters": [...
]
}
],
...
}]
```
**bindToPort**:注意其中有一个 [`bindToPort`](https://www.envoyproxy.io/docs/envoy/v1.6.0/api-v1/listeners/listeners) 的配置,其值为 `false`,该配置的缺省值为 `true`,表示将 Listener 绑定到端口上,此处设置为 `false` 则该 Listener 只能处理其他 Listener 转移过来的流量,即上文所说的 `virtual` Listener我们看其中的 filterChains.filters 中的 `envoy.http_connection_manager` 配置部分:
```json
"route_config": {
"name": "inbound|9080||reviews.default.svc.cluster.local",
"validate_clusters": false,
"virtual_hosts": [
{
"domains": [
"*"
],
"name": "inbound|http|9080",
"routes": [
{
...
"route": {
"cluster": "inbound|9080||reviews.default.svc.cluster.local",
"max_grpc_timeout": "0.000s",
"timeout": "0.000s"
}
}
]
}
]
}
```
该配置表示流量将转交给 Cluster `inbound|9080||reviews.default.svc.cluster.local` 处理。
**Cluster `inbound|9080||reviews.default.svc.cluster.local`**
运行 `istioctl pc cluster reviews-v1-cb8655c75-b97zc --fqdn reviews.default.svc.cluster.local --direction inbound -o json` 查看该 Cluster 的配置如下。
```json
[
{
"name": "inbound|9080||reviews.default.svc.cluster.local",
"connectTimeout": "1.000s",
"hosts": [
{
"socketAddress": {
"address": "127.0.0.1",
"portValue": 9080
}
}
],
"circuitBreakers": {
"thresholds": [
{}
]
}
}
]
```
可以看到该 Cluster 的 Endpoint 直接对应的就是 localhost再经过 iptables 转发流量就被应用程序容器消费了。
## 理解 Outbound Handler
因为 `reviews` 会向 `ratings` 服务发送 HTTP 请求,请求的地址是:`http://ratings.default.svc.cluster.local:9080/`Outbound handler 的作用是将 iptables 拦截到的本地应用程序发出的流量,经由 Envoy 判断如何路由到 upstream。
应用程序容器发出的请求为 Outbound 流量,被 iptables 劫持后转移给 Envoy Outbound handler 处理,然后经过 `virtual` Listener、`0.0.0.0_9080` Listener然后通过 Route 9080 找到 upstream 的 cluster进而通过 EDS 找到 Endpoint 执行路由动作。
**Route 9080**
`reviews` 会请求 `ratings` 服务,运行 `istioctl proxy-config routes reviews-v1-cb8655c75-b97zc --name 9080 -o json` 查看 route 配置,因为 Envoy 会根据 HTTP header 中的 domains 来匹配 VirtualHost所以下面只列举了 `ratings.default.svc.cluster.local:9080` 这一个 VirtualHost。
```json
[{
"name": "ratings.default.svc.cluster.local:9080",
"domains": [
"ratings.default.svc.cluster.local",
"ratings.default.svc.cluster.local:9080",
"ratings",
"ratings:9080",
"ratings.default.svc.cluster",
"ratings.default.svc.cluster:9080",
"ratings.default.svc",
"ratings.default.svc:9080",
"ratings.default",
"ratings.default:9080",
"10.254.234.130",
"10.254.234.130:9080"
],
"routes": [
{
"match": {
"prefix": "/"
},
"route": {
"cluster": "outbound|9080||ratings.default.svc.cluster.local",
"timeout": "0.000s",
"maxGrpcTimeout": "0.000s"
},
"decorator": {
"operation": "ratings.default.svc.cluster.local:9080/*"
},
"perFilterConfig": {...
}
}
]
},
..]
```
从该 Virtual Host 配置中可以看到将流量路由到 Cluster `outbound|9080||ratings.default.svc.cluster.local`
**Endpoint `outbound|9080||ratings.default.svc.cluster.local`**
Istio 1.1 以前版本不支持使用 `istioctl` 命令直接查询 Cluster 的 Endpoint可以使用查询 Pilot 的 debug 端点的方式折中。
```bash
kubectl exec reviews-v1-cb8655c75-b97zc -c istio-proxy curl http://istio-pilot.istio-system.svc.cluster.local:9093/debug/edsz > endpoints.json
```
`endpoints.json` 文件中包含了所有 Cluster 的 Endpoint 信息,我们只选取其中的 `outbound|9080||ratings.default.svc.cluster.local` Cluster 的结果如下。
```json
{
"clusterName": "outbound|9080||ratings.default.svc.cluster.local",
"endpoints": [
{
"locality": {
},
"lbEndpoints": [
{
"endpoint": {
"address": {
"socketAddress": {
"address": "172.33.100.2",
"portValue": 9080
}
}
},
"metadata": {
"filterMetadata": {
"istio": {
"uid": "kubernetes://ratings-v1-8558d4458d-ns6lk.default"
}
}
}
}
]
}
]
}
```
Endpoint 可以是一个或多个Envoy 将根据一定规则选择适当的 Endpoint 来路由。
**注**Istio 1.1 将支持 `istioctl pc endpoint` 命令来查询 Endpoint。
## 参考
- [理解 Istio Service Mesh 中 Envoy 代理 Sidecar 注入及流量劫持 - jimmysong.io](understand-sidecar-injection-and-traffic-hijack-in-istio-service-mesh.md)
- [Istio流量管理实现机制深度解析 - zhaohuabing.com](https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/)
请读者参考 ServiceMesher 社区出品的 Istio Handbook 中的 [Sidecar 流量路由机制分析](https://www.servicemesher.com/istio-handbook/concepts/sidecar-traffic-route.html)一节。

View File

@ -2,9 +2,7 @@
MOSN 是蚂蚁金服开源的,使用 Go 语言开发的网络代理软件作为云原生的网络数据平面旨在为服务提供多协议模块化智能化安全的代理能力。MOSN 是 Modular Open Smart Network-proxy 的简称。MOSN 可以与任何支持 xDS API 的 Service Mesh 集成亦可以作为独立的四、七层负载均衡API Gateway云原生 Ingress 等使用。
- MOSN 开源地址:<https://github.com/mosn/mosn>
- MOSN 官网:<https://mosn.io>
MOSN 开源地址:<https://github.com/mosn/mosn>
## 特点
@ -73,4 +71,10 @@ MOSN 使用 Go 语言编写Go 语言在生产效率,内存安全上有比
- MOSN 支持多协议框架,用户可以比较容易的接入私有协议,具有统一的路由框架;
- 多进程的插件机制,可以通过插件框架很方便的扩展独立 MOSN 进程的插件,做一些其他管理,旁路等的功能模块扩展;
- 具备中国密码合规的传输层国密算法支持;
## 参考
- [MOSN - github.com](https://github.com/mosn/mosn)
- [MOSN 官网 - mosn.io](https://mosn.io/zh)