Istio Service Mesh 教程——一文了解 Istio 全部功能,示例见 GitHub

本文是 Istio 管理 Java 微服务的案例教程,使用的所有工具和软件全部基于开源方案,替换了 redhat-developer-demos/istio-tutorial 中的 minishift 环境,使用 kubernetes-vagrant-centos-cluster 替代,沿用了原有的微服务示例,使用 Zipkin 做分布式追踪而不是 Jaeger。

本文中的代码和 YAML 文件见 https://github.com/rootsongjc/istio-tutorial。

准备环境

在进行本教程前需要先准备以下工具和环境。

8G 以上内存

Vagrant 2.0+

Virtualbox 5.0 +

提前下载 kubernetes1.9.1 的 release 压缩包

docker 1.12+

kubectl 1.9.1+

maven 3.5.2+

istioctl 0.7.1

git

curl、gzip、tar

kubetail

siege

安装 Kubernetes

请参考 kubernetes-vagrant-centos-cluster 在本地启动拥有三个节点的 kubernetes 集群。

安装 Istio

在 kubernetes-vagrant-centos-cluster 中的包含 Istio 0.7.1 的安装 YAML 文件,运行下面的命令安装 Istio。

运行示例

在您自己的本地主机的文件中增加如下配置项。

我们可以通过下面的URL地址访问以上的服务。

详细信息请参阅 https://istio.io/docs/guides/bookinfo.html

部署示例应用

在打包成镜像部署到 kubernetes 集群上运行之前,我们先在本地运行所有示例。

本教程中三个服务之间的依赖关系如下:

和 微服务是基于 Spring Boot 构建的, 微服务是基于 vert.x 构建的。

和 微服务的 文件中都引入了 OpenTracing 和 Jeager 的依赖。

本地运行

我们首先在本地确定所有的微服务都可以正常运行,然后再打包镜像在 kubernetes 集群上运行。

启动 Jaeger

使用 docker 来运行 jagger。

Jaeger UI 地址 http://localhost:16686

Customer

服务访问地址: http://localhost:8280

Preference

服务访问地址:http://localhost:8180

Recommendation

服务访问地址:http://localhost:8080

所有服务都启动之后,此时访问 http://localhost:8280 将会看到如下输出。

每访问一次最后的数字就会加 1。

Jaeger

此时访问 http://localhost:16686 将看到 Jaeger query UI,所有应用将 metrics 发送到 Jeager 中。

可以在 Jaeger UI 中搜索 和 service 的 trace 并查看每次请求的 tracing。

Jaeger query UI

构建镜像

在本地运行测试无误之后就可以构建镜像了。本教程中的容器镜像都是在 fabric8/java-jboss-openjdk8-jdk 的基础上构建的。只要将 Java 应用构建出 Jar 包然后放到 目录下基础镜像就可以自动帮我们运行,所以我们看到着几个应用的 文件中都没有执行入口,真正的执行入口是 run-java.sh。

Customer

构建 Customer 镜像。

第一次构建和上传需要花费一点时间,下一次构建就会很快。

Preference

构建 Preference 镜像。

Recommendation

构建 Recommendation 镜像。

现在三个 docker 镜像都构建完成了,我们检查一下。

部署到 Kubernetes

使用下面的命令将以上服务部署到 kubernetes。

注意:和 应用启动速度比较慢,我们将 livenessProb 配置中的 设置为20秒。

查看 Pod 启动状态:

增加 Ingress 配置

为了在 kubernetes 集群外部访问 customer 服务,我们需要增加 ingress 配置。

修改本地的 文件,增加一条配置。

批量访问该地址。

分布式追踪

依赖关系

服务关系图和QPS

Grafana 监控

Istio 使用示例

为了试用 Istio 中的各种功能,我们需要为应用构建多个版本,我们为 recommendation 构建 v2 版本的镜像,看看如何使用 Istio 控制微服务的流量。

构建 recommendation:v2

我们将构建新版的 服务的镜像,并观察 对不同版本的 服务的访问频率。

修改 程序中代码。

将 修改为

并构建 镜像。

将应用部署到 kubernetes。

现在再访问 服务,将看到如下输出:

我们可以看到 v1 和 v2 版本的 服务会被间隔访问到。

我们再将 v2 版本的 实例数设置成 2 个。

观察 Pod 达到两个之后再访问 服务。

观察输出中 v1 和 v2 版本 的访问频率。

将 服务的实例数恢复为 1。

修改 Istio RouteRules

以下所有路有规则都是针对 服务,并在 repo 的根目录下执行。

将所有流量打给 v2

下面将演示如何动态的划分不同版本服务间的流量,将所有的流量都打到 。

现在再访问 服务将看到所有的流量都会打到 。

删除 RouteRules 后再访问 服务将看到又恢复了 v1 和 v2 版本的 服务的间隔访问。

切分流量

将 90% 的流量给 v1,10% 的流量给 v2。

执行 观察访问情况。

要想动态切分流量只要修改 RouteRules 中的 配置即可。

因为 RouteRule 有优先级,为了继续后面的实验,在验证完成后删除该 RouteRule。

故障注入

有时候我们为了增强系统的健壮性,需要对系统做混沌工程,故意注入故障,并保障服务可以自动处理这些故障。

注入 HTTP 503 错误

有 50% 的几率报 503 错误。

清理 RouteRule。

增加延迟

增加服务的访问延迟。

会有 50% 的几率访问 服务有 7 秒的延迟。百分比和延迟时间可以在 RouteRule 中配置。

清理 RouteRule。

重试

让服务不是直接失败,而是增加重试机制。

我们下面将同时应用两条 RouteRule,让访问 服务时有 50% 的几率出现 503 错误,并在出现错误的时候尝试访问 v2 版本,超时时间为 2 秒。

执行 我们看到一开始有些 503 错误,然后所有的流量都流向了 v2。

清理 RouteRules。

超时

设置超时时间,只有服务访问超时才认定服务访问失败。

取消注释 中的下面一行,增加超时时间为 3 秒。

重新生成镜像。

重新部署到 kubernetes。

因为我们重新构建的镜像使用了同样的名字和 tag,而之前在 中配置的镜像拉取策略是 ,这样的话即使我们构建了新的镜像也无法应用到集群上,因此将镜像拉取策略改成 确保每次启动 Pod 的时候都会拉取镜像。

启用超时 RouteRules。

访问 服务将看到如下输出:

清理 RouteRules。

基于 user-agent 的智能路由(金丝雀发布)

User-agent 是一个字符串,其中包含了浏览器的信息,访问 https://www.whoishostingthis.com/tools/user-agent 获取你的 user-agent。

我的 user-agent 是:

将所有的流量打到 v1。

将使用 Safari 浏览器访问的流量打到 v2。

或者使用 curl 访问。

观察返回的结果。

将移动端用户的流量导到 v2。

观察输出的结果。

清理 RouteRules。

镜像流量

确保当前至少运行了两个版本的 服务,并且没有 RouteRule。

注:可以使用 获取 RouteRule。

设置流量镜像,将所有 v1 的流量都被镜像到 v2。

查看 recommendation-v2 的日志。

访问控制

Istio 可以设置服务访问的黑白名单,如果没有权限的话会返回 HTTP 404 Not Found。

白名单

此时访问 服务。

重置环境。

黑名单

设置黑名单,所有位于黑名单中的流量将获得 403 Forbidden 返回码。

此时访问 服务。

重置环境。

负载均衡

Kubernetes 中默认的负载均衡策略是 round-robin,当然我们可以使用 Istio 把它修改成 random。

增加 v1 的实例数。

持续访问 服务。

保持前台输出,观察流量的行为。

应用负载均衡策略。

观察一段时间流量的行为后,重置环境。

速率限制

暂时不可用

断路器

当达到最大连接数和最大挂起请求数时快速失败。

将流量在 v1 和 v2 之间均分。

未开启断路器的时候启动负载测试。

所有的请求都成功了,但是性能很差,因为 v2 版本设置了 3 秒的超时时间。

我们启用下断路器。

重新测试一下。

我们可以看到在启用了断路器后各项性能都有提高。

清理配置。

Pool Ejection

所谓的 Pool Ejection 就是当某些实例出现错误(如返回 5xx 错误码)临时将该实例弹出一段时间后(窗口期,可配置),然后再将其加入到负载均衡池中。我们的例子中配置的窗口期是 15 秒。

将 v1 和 v2 的流量均分。

增加 v2 的实例个数。

等待所有的 Pod 的状态都启动完成。

现在到 v2 的容器中操作。

增加 Pool Ejection 配置。

此时再访问 服务。

我们看到窗口期生效了,当出现 503 错误后至少 15 秒后才会出现第二次。

即使有了负载均衡池弹出策略对于系统的弹性来说依然还不够,如果你的服务有多个可用实例,可以将断路器重试Pool Ejection等策略组合起来使用。

例如在以上的 Pool Ejection 的基础上增加重试策略。

现在再访问 服务就看不到 503 错误了。

清理配置。

Egress

Egress 是用来配置 Istio serivce mesh 中的服务对外部服务的访问策略。

具体配置请参考 控制 Egress 流量。

以下示例还有问题,无法正常工作。

构建示例镜像 egresshttpbin。

部署到 Kubernetes。

为了在 kubernetes 集群外部访问到该服务,修改增加 ingress 配置并修改本地的 文件,我们在前面已经完成了,此处不再赘述。

构建示例镜像 egressgithub。

部署到 Kubernetes。

增加 Egress 配置。

到 egresshttpbin 容器中测试。

增加对 jimmysong.io 的 egress 配置。

增加 Egress 配置。

到 egressgithub 容器中测试。

清理环境。

参考

https://github.com/redhat-developer-demos/istio-tutorial

Book - Introducing Istio Service Mesh for Microservices

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180419G094NQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券