MOSN 作为 Istio 的数据平面

本文将介绍如何使用 MOSN 在 Istio 框架下搭建 Service Mesh 的开发环境,并验证 MOSN 的一些基础路由能力、负载均衡能力等。

MOSN 已通过 Istio 1.5.2 的 BookInfo 测试,关于最新版 Istio 的支持情况可关注 MOSN Istio WG

本文介绍的内容将包括 :

  • MOSN 与 Istio 的关系
  • MOSN 与 Istio 的 proxyv2 镜像 build 方法
  • 准备工作
  • 部署 Istio 与 MOSN
  • Bookinfo 实验

MOSN 与 Istio 的关系

我们曾在 MOSN 介绍中介绍过,MOSN 是一款采用 Go 语言开发的 Service Mesh 数据平面代理。

下图是 Istio 整体框架下,MOSN 的工作示意图。

MOSN 介绍

MOSN 与 Istio 的 proxyv2 镜像 build 方法

MOSN 提供了如下两种方式来构建 Istio 的 proxyv2 镜像,如果只有 MOSN 代码发生变化,则推荐使用方式二。

方式一(更新 Istio 版本)

1、下载对应的 Istio 版本,当前 MOSN 的 master 分支是支持 istio 1.5.2 ,feature-istio_adapter 分支是支持 istio 1.7.x。 2、下载完 Istio 代码后,进入到 istio 目录执行如下命令: 注意:在执行如下命令前,还需要做一些准备工作,将对应的 mosn 版本编译为二进制后压缩为 mosn.tgz 并上传至对应的存储服务中(如 github),另外 macos 的也得编译一份 mosn-macos.tar.gz

  1. ISTIO_ENVOY_VERSION=v0.15.0 # 对应 mosn 的版本
  2. ISTIO_ENVOY_RELEASE_URL=https://github.com/mosn/mosn/releases/download/0.15.0/mosn.tgz # 对应 Linux 环境下的二进制压缩包下载路径(存储路径需自定义)
  3. ISTIO_ENVOY_MACOS_RELEASE_URL=https://github.com/mosn/mosn/releases/download/0.15.0/mosn-macos.tar.gz # 对应 Macos 环境下的二进制压缩包下载路径
  4. ISTIO_ENVOY_MACOS_RELEASE_NAME=mosn-0.15.0 # 设置 macos 的 sidecar 名称
  5. SIDECAR=mosn # 设置 istio 的 sidecar 为 mosn
  6. make docker.proxyv2 # 编译构建 proxv2 镜像

另外由于目前 istio 默认在构建 proxyv2 image 的时候会默认加载 wasm,所以需要显示的在其编译脚本里面注释掉 wasm 相关的编译内容:

  1. bin/init.sh
  2. bin/update_proxy.sh
  3. tools/istio-docker.mk

3、将新构建的 proxyv2 镜像打上对应的版本 tag

  1. docker images | grep proxyv2 # 找到上一步 build 出来的 image,如名称为${PROXYV2} 版本为 ${TAG}
  2. docker tag ${PROXYV2}:${TAG} mosnio/proxyv2:${MOSNVERSION} # ${MOSNVERSION}代码 MOSN 版本 ,其值是 `cat ./VERSION` 的输出

方式二(更新 MOSN 版本)

将编译好的 mosn 二进制拷贝到当前目录并在当前目录增加 Dockerfile 文件,其文件内容如下:

  1. FROM mosnio/proxyv2:1.5.2-mosn
  2. COPY mosn /usr/local/bin/mosn

然后在当前目录执行如下命令:

  1. docker build --no-cache --rm -t mosnio/proxyv2:${MOSNVERSION} ./

其中 ${MOSNVERSION} 的值是 cat ./VERSION 的输出,当执行完成后就会在本地生成一个 mosnio/proxyv2 镜像。

准备工作

本文以 macOS 为例,其他环境可以安装对应版本的软件。

安装 hyperkit

先安装 docker-for-mac,之后安装驱动

安装 docker

下载软件包安装,或者使用如下的命令安装。

  1. $ brew cask install docker

安装驱动

  1. $ curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit \
  2. && chmod +x docker-machine-driver-hyperkit \
  3. && sudo mv docker-machine-driver-hyperkit /usr/local/bin/ \
  4. && sudo chown root:wheel /usr/local/bin/docker-machine-driver-hyperkit \
  5. && sudo chmod u+s /usr/local/bin/docker-machine-driver-hyperkit

安装 Minikube(也可以购买商业 Kubernetes 集群)

推荐使用 Minikube v0.28 以上来体验,请参考 minikube doc

  1. $ brew cask install minikube

启动 Minikube

注意,pilot 至少需要 2G 内存,所以在启动的时候,可以通过加参数的方法给 minikube 添加分配的资源,如果你机器的资源不够,推荐使用商业版本的 Kubernetes 集群。

  1. $ minikube start --memory=8192 --cpus=4 --kubernetes-version=v1.15.0 --vm-driver=hyperkit

创建 istio 命名空间

  1. $ kubectl create namespace istio-system

安装 kubectl 命令行工具

kubectl 是用于针对 Kubernetes 集群运行命令的命令行接口,安装参考 kubectl doc

  1. $ brew install kubernetes-cli

部署Istio与MOSN

安装 Istio

您可以在 Istio release 页面下载与您操作系统匹配的压缩文件,该文件中包含:安装文件、示例和 istioctl 命令行工具。使用如下命令来下载 Istio(本文示例使用的是 Istio 1.5.2):

  1. $ export ISTIO_VERSION=1.5.2 && curl -L https://istio.io/downloadIstio | sh -

下载的 Istio 包名为 istio-1.5.2,包含:

  • install/kubernetes:包含 Kubernetes 相关的 YAML 安装文件;
  • examples/:包含示例应用程序;
  • bin/:包含 istioctl 的客户端文件;

切换到 Istio 包所在目录:

  1. $ cd istio-$ISTIO_VERSION/

使用如下命令将 istioctl 客户端路径加入 $PATH 中:

  1. $ export PATH=$PATH:$(pwd)/bin

截止目前,我们已经可以通过 istioctl 命令行工具来灵活的自定义 Istio 控制平面和数据平面配置参数。

设置 MOSN 作为 Istio 的 Sidecar

通过 istioctl 命令的参数指定 MOSN 作为 Istio 中的数据面:

  1. $ istioctl manifest apply --set .values.global.proxy.image="mosnio/proxyv2:1.5.2-mosn" --set meshConfig.defaultConfig.binaryPath="/usr/local/bin/mosn"

修改 prometheus deployment

当前版本的部署的 istio 自带的 prometheus,有2个小问题需要手动调整下。

  1. $ kubectl edit deployments -n istio-system prometheus
  1. 将容器 istio-proxy 的镜像改为 mosnio/proxyv2:1.5.2-mosn
  2. 将容器 istio-proxy 启动参数中的 --binaryPath 的值改为 /usr/local/bin/mosn

验证安装

检查 Istio 相关 pod 服务是否部署成功:

  1. $ kubectl get pod -n istio-system
  2. NAME READY STATUS RESTARTS AGE
  3. istio-ingressgateway-6f68796974-mtp2q 1/1 Running 0 6h10m
  4. istiod-768488f855-c7bf6 1/1 Running 0 6h35m
  5. prometheus-6cd5bb8f99-8szvt 2/2 Running 0 13m

如果服务状态 STATUS 为 Running,则表示 Istio 已经成功安装,后面就可以部署 Bookinfo 示例了。

我们可以登录到 istio-ingressgateway-6f68796974-mtp2q pod 上查看该网关已经成功使用MOSN作为 ingress-gateway

  1. $ kubectl -n istio-system exec -it istio-ingressgateway-6f68796974-mtp2q -- bash
  2. root@istio-ingressgateway-6f68796974-mtp2q:/# ps aux | grep mosn
  3. root 21 0.1 0.3 129588 26080 ? Sl 10:47 0:38 /usr/local/bin/mosn start --config /etc/istio/proxy/envoy-rev0.json --service-cluster istio-ingressgateway --service-node router~172.17.0.5~istio-ingressgateway-6f68796974-mtp2q.istio-system~istio-system.svc.cluster.local
  4. root 57 0.0 0.0 11468 1012 pts/0 S+ 16:58 0:00 grep --color=auto mosn

Bookinfo 示例

MOSN 已通过 Istio 1.5.2 的 BookInfo 测试,相关支持动态请关注 MOSN Istio WG

可以通过 MOSN with Istio 的教程来进行 Bookinfo 示例的演示操作,另外在该教程中您也可以找到更多关于使用 MOSN 和 Istio 的说明。

BookInfo 实验

BookInfo 是一个类似豆瓣的图书应用,它包含四个基础服务:

  • Product Page:主页,由 python 开发,展示所有图书信息,它会调用 Reviews 和 Details 服务
  • Reviews:评论,由 java 开发,展示图书评论,会调用 Ratings 服务
  • Ratings:评分服务,由 nodejs 开发
  • Details:图书详情,由 ruby 开发

bookinfo

部署 BookInfo 应用并注入 MOSN

详细过程可以参考 BookInfo doc

通过 kube-inject 的方式实现Sidecar注入:

  1. $ istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml > bookinfo.yaml && sed -i "s/\/usr\/local\/bin\/envoy/\/usr\/local\/bin\/mosn/g" ./bookinfo.yaml

部署注入 Sidecar 后的 Bookinfo 应用:

  1. $ kubectl apply -f bookinfo.yaml

验证部署是否成功:

  1. $ kubectl get services
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. details ClusterIP 10.107.154.89 <none> 9080/TCP 65m
  4. kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10h
  5. productpage ClusterIP 10.101.154.61 <none> 9080/TCP 65m
  6. ratings ClusterIP 10.103.70.21 <none> 9080/TCP 65m
  7. reviews ClusterIP 10.96.56.145 <none> 9080/TCP 65m

等待所有的 pod 等成功运行起来:

  1. $ kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. details-v1-547d75b975-zrhtf 2/2 Running 0 66m
  4. productpage-v1-84b8bbd5bb-pc2hc 2/2 Running 0 66m
  5. ratings-v1-b78b5cb7-hvtwv 2/2 Running 0 66m
  6. reviews-v1-576d4b46f4-84cw9 2/2 Running 0 66m
  7. reviews-v2-68b67dcd98-d286b 2/2 Running 0 66m
  8. reviews-v3-784c6444b-blbgr 2/2 Running 0 66m

当上述状态为 Running 后,可通过如下方式确认 Bookinfo 应用是否正常运行:

  1. kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"

同样我们可以查看此时 BookInfo 应用的每一个 pod 都运行了 2 个容器,一个容器是 BookInfo 自身业务容器,另一个容器是Istio注入的 sidecar MOSN 容器。

  1. $ kubectl exec -it productpage-v1-84b8bbd5bb-pc2hc -c istio-proxy -- bash
  2. istio-proxy@productpage-v1-84b8bbd5bb-pc2hc:/$ ps aux | grep mosn
  3. istio-p+ 1 0.1 0.5 153964 41372 ? Ssl 16:59 0:04 /usr/local/bin/pilot-agent proxy sidecar --domain default.svc.cluster.local --configPath /etc/istio/proxy --binaryPath /usr/local/bin/mosn --serviceCluster productpage.default --drainDuration 45s --parentShutdownDuration 1m0s --discoveryAddress istiod.istio-system.svc:15012 --zipkinAddress zipkin.istio-system:9411 --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --connectTimeout 10s --proxyAdminPort 15000 --concurrency 2 --controlPlaneAuthPolicy NONE --dnsRefreshRate 300s --statusPort 15020 --trust-domain=cluster.local --controlPlaneBootstrap=false
  4. istio-p+ 18 0.1 0.3 129584 25904 ? Sl 16:59 0:05 /usr/local/bin/mosn start --config /etc/istio/proxy/envoy-rev0.json --service-cluster productpage.default --service-node sidecar~172.17.0.14~productpage-v1-84b8bbd5bb-pc2hc.default~default.svc.cluster.local
  5. istio-p+ 59 0.0 0.0 11464 1156 pts/0 S+ 17:54 0:00 grep --color=auto mosn

访问 BookInfo 服务

开启 gateway 模式。

  1. $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  2. $ kubectl get gateway // 查看 gateway 是否运行起来
  3. NAME AGE
  4. bookinfo-gateway 24m

设置 GATEWAY_URL 参考文档

  1. $ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
  2. $ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
  3. $ export INGRESS_HOST=$(minikube ip)
  4. $ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

验证 gateway 是否生效,输出 200 表示成功。

  1. $ curl -o /dev/null -s -w "%{http_code}\n" http://$GATEWAY_URL/productpage
  2. 200

观察页面情况

访问 http://$GATEWAY_URL/productpage (注意: $GATEWAY_URL 需要替换成你设置的地址),正常的话通过刷新会看到如下所示 BookInfo 的界面,其中 Book Reviews 有三个版本,刷新后依次会看到(可以查看 samples/bookinfo/platform/kube/bookinfo.yaml 中的配置发现为什么是这三个版本)版本一的界面。

版本一

版本二的界面。

版本二

版本三的界面。

版本三

验证 MOSN 按 version 路由能力

首先为 BookInfo 的 service 创建一系列的 destination rules。

  1. $ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

指定 reviews 服务只访问 v1 版本。

  1. $ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

访问 http://$GATEWAY_URL/productpage 发现 reviews 固定在如下版本一的页面不再变化。

版本一

验证 MOSN 按 weight 路由能力

我们通过下面操作将 v1 和 v3 版本各分配 50% 的流量。

  1. $ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

访问 http://$GATEWAY_URL/productpage 这次 v1 和 v3 各有 1/2 几率出现。

验证 MOSN 按照特定 header 路由能力

BookInfo 系统右上角有一个登陆的入口,登陆以后请求会带上 end-user 这个自定义,值是 user name,Mosn 支持根据这个 header 的值来做路由。比如,我们尝试将 jason 这个用户路由到 v2 版本,其他的路由到 v1 版本(用户名和密码均是:jason,为什么是这个用户可以查看对应的 yaml 文件)。

  1. $ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

访问 http://$GATEWAY_URL/productpage 时:

以 jason 身份登陆,会看到 v2 版本。

登录

以其他身份登录,始终在 v1 版本。

版本一

卸载 BookInfo

可以使用下面的命令来完成应用的删除和清理工作:

删除路由规则,并销毁应用的 Pod。

  1. $ sh samples/bookinfo/platform/kube/cleanup.sh

确认 BookInfo 应用已经关停:

  1. $ kubectl get virtualservices #-- there should be no virtual services
  2. $ kubectl get destinationrules #-- there should be no destination rules
  3. $ kubectl get gateway #-- there should be no gateway
  4. $ kubectl get pods #-- the Bookinfo pods should be deleted

卸载 Istio

执行如下命令,删除 Istio 相关 CRD 以及 pod 等资源:

  1. istioctl manifest generate --set .values.global.proxy.image="mosnio/proxyv2:1.5.2-mosn" --set meshConfig.defaultConfig.binaryPath="/usr/local/bin/mosn" | kubectl delete -f -

确认 Istio 是否成功卸载:

  1. $ kubectl get namespace istio-system

修改于 2021年3月5日: add go-import for proxy-wasm-go-host (847dfb6)