Kubernetes Handbook
  • Kubernetes 中文指南/云原生应用架构实践手册
  • 前言
    • 序言
  • 云原生
    • 云原生(Cloud Native)的定义
    • 云原生的设计哲学
    • Play with Kubernetes
    • 快速部署一个云原生本地实验环境
    • 使用Rancher在阿里云上部署Kubenretes集群
    • Kubernetes与云原生应用概览
    • 云原生应用之路——从Kubernetes到Cloud Native
    • 云原生编程语言
      • 云原生编程语言Ballerina
      • 云原生编程语言Pulumi
    • 云原生的未来
  • 概念与原理
    • Kubernetes架构
      • 设计理念
      • Etcd解析
      • 开放接口
        • CRI - Container Runtime Interface(容器运行时接口)
        • CNI - Container Network Interface(容器网络接口)
        • CSI - Container Storage Interface(容器存储接口)
    • Kubernetes中的网络
      • Kubernetes中的网络解析——以flannel为例
      • Kubernetes中的网络解析——以calico为例
      • 具备API感知的网络和安全性管理开源软件Cilium
        • Cilium架构设计与概念解析
    • 资源对象与基本概念解析
    • Pod状态与生命周期管理
      • Pod概览
      • Pod解析
      • Init容器
      • Pause容器
      • Pod安全策略
      • Pod的生命周期
      • Pod Hook
      • Pod Preset
      • Pod中断与PDB(Pod中断预算)
    • 集群资源管理
      • Node
      • Namespace
      • Label
      • Annotation
      • Taint和Toleration(污点和容忍)
      • 垃圾收集
    • 控制器
      • Deployment
      • StatefulSet
      • DaemonSet
      • ReplicationController和ReplicaSet
      • Job
      • CronJob
      • Horizontal Pod Autoscaling
        • 自定义指标HPA
      • 准入控制器(Admission Controller)
    • 服务发现
      • Service
      • Ingress
        • Traefik Ingress Controller
    • 身份与权限控制
      • ServiceAccount
      • RBAC——基于角色的访问控制
      • NetworkPolicy
    • 存储
      • Secret
      • ConfigMap
        • ConfigMap的热更新
      • Volume
      • Persistent Volume(持久化卷)
      • Storage Class
      • 本地持久化存储
    • 集群扩展
      • 使用自定义资源扩展API
      • 使用CRD扩展Kubernetes API
      • Aggregated API Server
      • APIService
      • Service Catalog
    • 资源调度
      • QoS(服务质量等级)
  • 用户指南
    • 用户指南
    • 资源对象配置
      • 配置Pod的liveness和readiness探针
      • 配置Pod的Service Account
      • Secret配置
      • 管理namespace中的资源配额
    • 命令使用
      • Docker用户过渡到kubectl命令行指南
      • kubectl命令概览
      • kubectl命令技巧大全
      • 使用etcdctl访问kubernetes数据
    • 集群安全性管理
      • 管理集群中的TLS
      • kubelet的认证授权
      • TLS bootstrap
      • 创建用户认证授权的kubeconfig文件
      • IP伪装代理
      • 使用kubeconfig或token进行用户身份认证
      • Kubernetes中的用户与身份认证授权
      • Kubernetes集群安全性配置最佳实践
    • 访问Kubernetes集群
      • 访问集群
      • 使用kubeconfig文件配置跨集群认证
      • 通过端口转发访问集群中的应用程序
      • 使用service访问群集中的应用程序
      • 从外部访问Kubernetes中的Pod
      • Cabin - Kubernetes手机客户端
      • Kubernetic - Kubernetes桌面客户端
      • Kubernator - 更底层的Kubernetes UI
    • 在Kubernetes中开发部署应用
      • 适用于kubernetes的应用开发部署流程
      • 迁移传统应用到Kubernetes中——以Hadoop YARN为例
      • 使用StatefulSet部署用状态应用
  • 最佳实践
    • 最佳实践概览
    • 在CentOS上部署Kubernetes集群
      • 创建TLS证书和秘钥
      • 创建kubeconfig文件
      • 创建高可用etcd集群
      • 安装kubectl命令行工具
      • 部署master节点
      • 安装flannel网络插件
      • 部署node节点
      • 安装kubedns插件
      • 安装dashboard插件
      • 安装heapster插件
      • 安装EFK插件
    • 生产级的Kubernetes简化管理工具kubeadm
      • 使用kubeadm在Ubuntu Server 16.04上快速构建测试集群
    • 服务发现与负载均衡
      • 安装Traefik ingress
      • 分布式负载测试
      • 网络和集群性能测试
      • 边缘节点配置
      • 安装Nginx ingress
      • 安装配置DNS
        • 安装配置Kube-dns
        • 安装配置CoreDNS
    • 运维管理
      • Master节点高可用
      • 服务滚动升级
      • 应用日志收集
      • 配置最佳实践
      • 集群及应用监控
      • 数据持久化问题
      • 管理容器的计算资源
      • 集群联邦
    • 存储管理
      • GlusterFS
        • 使用GlusterFS做持久化存储
        • 使用Heketi作为Kubernetes的持久存储GlusterFS的external provisioner
        • 在OpenShift中使用GlusterFS做持久化存储
      • GlusterD-2.0
      • Ceph
        • 用Helm托管安装Ceph集群并提供后端存储
        • 使用Ceph做持久化存储
        • 使用rbd-provisioner提供rbd持久化存储
      • OpenEBS
        • 使用OpenEBS做持久化存储
      • Rook
      • NFS
        • 利用NFS动态提供Kubernetes后端存储卷
    • 集群与应用监控
      • Heapster
        • 使用Heapster获取集群和对象的metric数据
      • Prometheus
        • 使用Prometheus监控kubernetes集群
        • Prometheus查询语言PromQL使用说明
      • 使用Vistio监控Istio服务网格中的流量
    • 分布式跟踪
      • OpenTracing
    • 服务编排管理
      • 使用Helm管理Kubernetes应用
      • 构建私有Chart仓库
    • 持续集成与发布
      • 使用Jenkins进行持续集成与发布
      • 使用Drone进行持续集成与发布
    • 更新与升级
      • 手动升级Kubernetes集群
      • 升级dashboard
  • 领域应用
    • 领域应用概览
    • 微服务架构
      • 微服务中的服务发现
      • 使用Java构建微服务并发布到Kubernetes平台
        • Spring Boot快速开始指南
    • Service Mesh 服务网格
      • 企业级服务网格架构
        • Service Mesh基础
        • Service Mesh技术对比
        • 采纳和演进
        • 定制和集成
        • 总结
      • Istio
        • 安装并试用Istio service mesh
        • 配置请求的路由规则
        • 安装和拓展Istio service mesh
        • 集成虚拟机
        • Istio中sidecar的注入规范及示例
        • 如何参与Istio社区及注意事项
        • Istio教程
        • Istio免费学习资源汇总
        • 深入理解Istio Service Mesh中的Envoy Sidecar注入与流量劫持
        • 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由转发
      • Linkerd
        • Linkerd 使用指南
      • Conduit
        • Condiut概览
        • 安装Conduit
      • Envoy
        • Envoy的架构与基本术语
        • Envoy作为前端代理
        • Envoy mesh教程
      • SOFAMesh
        • SOFAMesh中的Dubbo on x-protocol
      • MOSN
        • 使用 MOSN 构建 SOFAMesh
    • 大数据
      • Spark standalone on Kubernetes
      • 运行支持Kubernetes原生调度的Spark程序
    • Serverless架构
      • 理解Serverless
      • FaaS-函数即服务
        • OpenFaaS快速入门指南
    • 边缘计算
    • 人工智能
  • 开发指南
    • 开发指南概览
    • SIG和工作组
    • 开发环境搭建
      • 本地分布式开发环境搭建(使用Vagrant和Virtualbox)
    • 单元测试和集成测试
    • client-go示例
    • Operator
      • operator-sdk
    • kubebuilder
    • 高级开发指南
    • 社区贡献
    • Minikube
  • CNCF(云原生计算基金会)
    • CNCF - 云原生计算基金会简介
    • CNCF章程
    • CNCF特别兴趣小组(SIG)说明
    • 开源项目加入CNCF Sandbox的要求
    • CNCF中的项目治理
    • CNCF Ambassador
  • 附录
    • 附录说明
    • Kubernetes中的应用故障排查
    • Kubernetes相关资讯和情报链接
    • Docker最佳实践
    • 使用技巧
    • 问题记录
    • Kubernetes版本更新日志
      • Kubernetes1.7更新日志
      • Kubernetes1.8更新日志
      • Kubernetes1.9更新日志
      • Kubernetes1.10更新日志
      • Kubernetes1.11更新日志
      • Kubernetes1.12更新日志
      • Kubernetes1.13更新日志
      • Kubernetes1.14更新日志
      • Kubernetes1.15更新日志
    • Kubernetes及云原生年度总结及展望
      • Kubernetes与云原生2017年年终总结及2018年展望
      • Kubernetes与云原生2018年年中总结及2019年展望
    • CNCF年度报告解读
      • CNCF 2018年年度报告解读
    • Kubernetes认证服务提供商(KCSP)说明
    • 认证Kubernetes管理员(CKA)说明
Powered by GitBook
On this page
  • 准备环境
  • 安装 Kubernetes
  • 安装 Istio
  • 部署示例应用
  • 本地运行
  • 构建镜像
  • 部署到 Kubernetes
  • 增加 Ingress 配置
  • Istio 使用示例
  • 构建 recommendation:v2
  • 修改 Istio RouteRules
  • 故障注入
  • 增加延迟
  • 重试
  • 超时
  • 基于 user-agent 的智能路由(金丝雀发布)
  • 镜像流量
  • 访问控制
  • 负载均衡
  • 速率限制
  • 断路器
  • Pool Ejection
  • Egress
  • 参考

Was this helpful?

  1. 领域应用
  2. Service Mesh 服务网格
  3. Istio

Istio教程

Previous如何参与Istio社区及注意事项NextIstio免费学习资源汇总

Last updated 5 years ago

Was this helpful?

注意:本文档已失效,请浏览 。本书中的 Service Mesh 章节已不再维护,请转到 中浏览。

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

本文中的代码和 YAML 文件见 。

注意:本教程基于 Istio 0.7.1,2018年8月1日,Isito 1.0 发布,本教程已过时。

准备环境

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

  • 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

安装 Kubernetes

git clone https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster.git
cd kubernetes-vagrant-centos-cluster
vagrant up

安装 Istio

kubectl apply -f addon/istio/

运行示例

kubectl apply -n default -f <(istioctl kube-inject -f yaml/istio-bookinfo/bookinfo.yaml)

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

172.17.8.102 grafana.istio.jimmysong.io
172.17.8.102 servicegraph.istio.jimmysong.io
172.17.8.102 zipkin.istio.jimmysong.io

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

Service

URL

grafana

servicegraph

zipkin

部署示例应用

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

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

customer → preference → recommendation

customer 和 preference 微服务的 pom.xml 文件中都引入了 OpenTracing 和 Jeager 的依赖。

<dependency>
    <groupId>io.opentracing.contrib</groupId>
    <artifactId>opentracing-spring-cloud-starter</artifactId>
    <version>0.1.7</version>
</dependency>
<dependency>
    <groupId>com.uber.jaeger</groupId>
    <artifactId>jaeger-tracerresolver</artifactId>
    <version>0.25.0</version>
</dependency>

本地运行

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

启动 Jaeger

使用 docker 来运行 jagger。

docker run -d \
  --rm \
  -p5775:5775/udp \
  -p6831:6831/udp \
  -p6832:6832/udp \
  -p16686:16686 \
  -p14268:14268 \
  jaegertracing/all-in-one:1.3

Customer

cd customer/java/springboot
JAEGER_SERVICE_NAME=customer mvn \
  spring-boot:run \
  -Drun.arguments="--spring.config.location=src/main/resources/application-local.properties"

Preference

cd preference/java/springboot
JAEGER_SERVICE_NAME=preference mvn \
  spring-boot:run \
  -Drun.arguments="--spring.config.location=src/main/resources/application-local.properties"

Recommendation

cd recommendation/java/vertx
mvn vertx:run
customer => preference => recommendation v1 from 'unknown': 1

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

Jaeger

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

构建镜像

Customer

构建 Customer 镜像。

cd customer/java/springboot
mvn clean package
docker build -t jimmysong/istio-tutorial-customer:v1 .
docker push jimmysong/istio-tutorial-customer:v1

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

Preference

构建 Preference 镜像。

cd preference/java/springboot
mvn clean package
docker build -t jimmysong/istio-tutorial-preference:v1 .
docker push jimmysong/istio-tutorial-preference:v1

Recommendation

构建 Recommendation 镜像。

cd recommendation/java/vertx
mvn clean package
docker build -t jimmysong/istio-tutorial-recommendation:v1 .
docker push jimmysong/istio-tutorial-recommendation:v1

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

$ docker images | grep istio-tutorial
REPOSITORY                                TAG                 IMAGE ID            CREATED             SIZE
jimmysong/istio-tutorial-recommendation   v1                  d31dd858c300        51 seconds ago      443MB
jimmysong/istio-tutorial-preference       v1                  e5f0be361477        6 minutes ago       459MB
jimmysong/istio-tutorial-customer         v1                  d9601692673e        13 minutes ago      459MB

部署到 Kubernetes

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

# create new namespace
kubectl create ns istio-tutorial

# deploy recommendation
kubectl apply -f <(istioctl kube-inject -f recommendation/kubernetes/Deployment.yml) -n istio-tutorial
kubectl apply -f recommendation/kubernetes/Service.yml

# deploy preferrence
kubectl apply -f <(istioctl kube-inject -f preference/kubernetes/Deployment.yml) -n istio-tutorial
kubectl apply -f preference/kubernetes/Service.yml

# deploy customer
kubectl apply -f <(istioctl kube-inject -f customer/kubernetes/Deployment.yml) -n istio-tutorial
kubectl apply -f customer/kubernetes/Service.yml

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

查看 Pod 启动状态:

kubectl get pod -w -n istio-tutorial

增加 Ingress 配置

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

kubectl apply -f ingress/ingress.yaml

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

172.17.8.102 customer.istio-tutorial.jimmysong.io
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 1

批量访问该地址。

./bin/poll_customer.sh

Istio 使用示例

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

构建 recommendation:v2

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

修改 recommendation/java/vertx/src/main/java/com/redhat/developer/demos/recommendation/RecommendationVerticle.java 程序中代码。

将 private static final String RESPONSE_STRING_FORMAT = "recommendation v1 from '%s': %d\n"; 修改为 private static final String RESPONSE_STRING_FORMAT = "recommendation v2 from '%s': %d\n";

并构建 recommendation:v2 镜像。

cd recommendation/java/vertx
mvn clean package
docker build -t jimmysong/istio-tutorial-recommendation:v2 .
docker push jimmysong/istio-tutorial-recommendation:v2

将应用部署到 kubernetes。

# deploy recommendation
kubectl apply -f <(istioctl kube-inject -f recommendation/kubernetes/Deployment-v2.yml) -n istio-tutorial

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

$ bin/poll_customer.sh
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 1
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3581
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 2
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3582
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 3
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3583
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 4

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

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

kubectl scale --replicas=2 deployment/recommendation-v2 -n istio-tutorial
kubectl get pod -w -n istio-tutorial

观察 recommendation-v2 Pod 达到两个之后再访问 customer 服务。

$ bin/poll_customer.sh
customer => preference => recommendation v2 from '77b9f6cc68-j9fgj': 1
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 71
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3651
customer => preference => recommendation v2 from '77b9f6cc68-j9fgj': 2
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 72
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3652
customer => preference => recommendation v2 from '77b9f6cc68-j9fgj': 3
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 73
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3653

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

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

kubectl scale --replicas=1 deployment/recommendation-v2

修改 Istio RouteRules

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

将所有流量打给 v2

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

istioctl create -f istiofiles/route-rule-recommendation-v2.yml -n istio-tutorial

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

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

istioctl delete routerule recommendation-default

切分流量

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

istioctl create -f istiofiles/route-rule-recommendation-v1_and_v2.yml -n istio-tutorial

执行bin/poll_customer.sh 观察访问情况。

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

apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: recommendation-v1-v2
spec:
  destination:
    namespace: istio-tutorial
    name: recommendation
  precedence: 5
  route:
  - labels:
      version: v1
    weight: 90
  - labels:
      version: v2
    weight: 10

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

istioctl delete routerule recommendation-v1-v2 -n istio-tutorial

故障注入

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

注入 HTTP 503 错误

istioctl create -f istiofiles/route-rule-recommendation-503.yml -n istio-tutorial

有 50% 的几率报 503 错误。

$ bin/poll_customer.sh
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 135
customer => 503 preference => 503 fault filter abort
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3860
customer => 503 preference => 503 fault filter abort
customer => 503 preference => 503 fault filter abort
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 136
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3861
customer => 503 preference => 503 fault filter abort
customer => 503 preference => 503 fault filter abort
customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 137
customer => 503 preference => 503 fault filter abort

清理 RouteRule。

istioctl delete routerule recommendation-503 -n istio-tutorial

增加延迟

增加服务的访问延迟。

istioctl create -f istiofiles/route-rule-recommendation-delay.yml -n istio-tutorial

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

清理 RouteRule。

istioctl delete routerule recommendation-delay -n istio-tutorial

重试

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

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

istioctl create -f istiofiles/route-rule-recommendation-v2_503.yml -n istio-tutorial
istioctl create -f istiofiles/route-rule-recommendation-v2_retry.yml -n istio-tutorial

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

清理 RouteRules。

istioctl delete routerule recommendation-v2-retry -n istio-tutorial
istioctl delete routerule recommendation-v2-503 -n istio-tutorial

超时

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

取消注释 recommendation/java/vertx/src/main/java/com/redhat/developer/demos/recommendation/RecommendationVerticle.java 中的下面一行,增加超时时间为 3 秒。

router.get("/").handler(this::timeout);

重新生成镜像。

cd recommendation/java/vertx
mvn clean package
docker build -t jimmysong/istio-tutorial-recommendation:v2 .
docker push jimmysong/istio-tutorial-recommendation:v2

重新部署到 kubernetes。

kubectl delete -f recommendation/kubernetes/Deployment-v2.yml

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

kubectl apply -f <(istioctl kube-inject -f recommendation/kubernetes/Deployment-v2.yml) -n istio-tutorial

启用超时 RouteRules。

istioctl create -f istiofiles/route-rule-recommendation-timeout.yml -n istio-tutorial

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

$ bin/poll_customer.sh
customer => 503 preference => 504 upstream request timeout
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 4002
customer => 503 preference => 504 upstream request timeout
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 4003
customer => 503 preference => 504 upstream request timeout
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 4004

清理 RouteRules。

istioctl delete routerule recommendation-timeout -n istio-tutorial

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

我的 user-agent 是:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36

将所有的流量打到 v1。

istioctl create -f istiofiles/route-rule-recommendation-v1.yml -n istio-tutorial

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

istioctl create -f istiofiles/route-rule-safari-recommendation-v2.yml -n istio-tutorial

或者使用 curl 访问。

curl -A Safari http://customer.istio-tutorial.jimmysong.io/
curl -A Firefox http://customer.istio-tutorial.jimmysong.io/

观察返回的结果。

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

istioctl create -f istiofiles/route-rule-mobile-recommendation-v2.yml -n istio-tutorial

curl -A "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4(KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5" http://customer.istio-tutorial.jimmysong.io/

观察输出的结果。

清理 RouteRules。

istioctl delete routerule recommendation-mobile -n istio-tutorial
istioctl delete routerule recommendation-safari -n istio-tutorial
istioctl delete routerule recommendation-default -n istio-tutorial

镜像流量

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

注:可以使用 istioctl get routerule 获取 RouteRule。

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

istioctl create -f istiofiles/route-rule-recommendation-v1-mirror-v2.yml -n istio-tutorial
bin/poll_customer.sh

查看 recommendation-v2 的日志。

kubectl logs -f `oc get pods|grep recommendation-v2|awk '{ print $1 }'` -c recommendation

访问控制

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

白名单

istioctl create -f istiofiles/acl-whitelist.yml -n istio-tutorial

此时访问 customer 服务。

$ bin/poll_customer.sh
customer => 404 NOT_FOUND:preferencewhitelist.listchecker.istio-tutorial:customer is not whitelisted

重置环境。

istioctl delete -f istiofiles/acl-whitelist.yml -n istio-tutorial

黑名单

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

istioctl create -f istiofiles/acl-blacklist.yml -n istio-tutorial

此时访问 customer 服务。

$ bin/poll_customer.sh
customer => 403 PERMISSION_DENIED:denycustomerhandler.denier.istio-tutorial:Not allowed

重置环境。

istioctl delete -f istiofiles/acl-blacklist.yml -n istio-tutorial

负载均衡

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

增加 v1 的实例数。

kubectl scale deployment recommendation-v1 --replicas=2 -n istio-tutorial

持续访问 customer 服务。

bin/poll_customer.sh

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

应用负载均衡策略。

istioctl create -f istiofiles/recommendation_lb_policy_app.yml -n istio-tutorial

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

istioctl delete -f istiofiles/recommendation_lb_policy_app.yml -n istio-tutorial
kubectl scale deployment recommendation-v1 --replicas=1 -n istio-tutorial

速率限制

暂时不可用

断路器

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

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

istioctl create -f istiofiles/route-rule-recommendation-v1_and_v2_50_50.yml -n istio-tutorial

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

$ siege -r 2 -c 20 -v customer.istio-tutorial.jimmysong.io
New configuration template added to /Users/jimmysong/.siege
Run siege -C to view the current settings in that file
** SIEGE 4.0.4
** Preparing 20 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200     0.10 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.12 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.13 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.13 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.13 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.17 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.12 secs:      74 bytes ==> GET  /
HTTP/1.1 200     3.14 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.15 secs:      74 bytes ==> GET  /
HTTP/1.1 200     3.15 secs:      74 bytes ==> GET  /
HTTP/1.1 200     3.17 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.17 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.20 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.20 secs:      74 bytes ==> GET  /
HTTP/1.1 200     0.05 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.12 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.15 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.25 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.26 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.14 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.58 secs:      74 bytes ==> GET  /
HTTP/1.1 200     6.15 secs:      74 bytes ==> GET  /
HTTP/1.1 200     6.16 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.03 secs:      74 bytes ==> GET  /
HTTP/1.1 200     6.06 secs:      75 bytes ==> GET  /
HTTP/1.1 200     6.04 secs:      75 bytes ==> GET  /
HTTP/1.1 200     3.11 secs:      74 bytes ==> GET  /
HTTP/1.1 200     3.09 secs:      75 bytes ==> GET  /
HTTP/1.1 200     6.15 secs:      74 bytes ==> GET  /
HTTP/1.1 200     6.71 secs:      74 bytes ==> GET  /
HTTP/1.1 200     3.52 secs:      75 bytes ==> GET  /
^C
Lifting the server siege...
Transactions:                  31 hits
Availability:              100.00 %
Elapsed time:                7.99 secs
Data transferred:            0.00 MB
Response time:                2.99 secs
Transaction rate:            3.88 trans/sec
Throughput:                0.00 MB/sec
Concurrency:               11.60
Successful transactions:          31
Failed transactions:               0
Longest transaction:            6.71
Shortest transaction:            0.05

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

我们启用下断路器。

istioctl create -f istiofiles/recommendation_cb_policy_version_v2.yml -n istio-tutorial

重新测试一下。

$ siege -r 2 -c 20 -v customer.istio-tutorial.jimmysong.io
** SIEGE 4.0.4
** Preparing 20 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200     0.07 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.07 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.07 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.12 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.12 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.16 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.16 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.21 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.21 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.24 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.24 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.14 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.29 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.13 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.18 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.13 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.11 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.39 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.24 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.44 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.43 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.44 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.40 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.47 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.42 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.42 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.06 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.07 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.15 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.12 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.57 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.18 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.52 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.65 secs:      92 bytes ==> GET  /
HTTP/1.1 503     0.42 secs:      92 bytes ==> GET  /
HTTP/1.1 200     0.09 secs:      75 bytes ==> GET  /
HTTP/1.1 200     0.43 secs:      75 bytes ==> GET  /
HTTP/1.1 503     0.04 secs:      92 bytes ==> GET  /
HTTP/1.1 200     4.15 secs:      74 bytes ==> GET  /
HTTP/1.1 200     0.01 secs:      75 bytes ==> GET  /

Transactions:                  19 hits
Availability:               47.50 %
Elapsed time:                4.16 secs
Data transferred:            0.00 MB
Response time:                0.72 secs
Transaction rate:            4.57 trans/sec
Throughput:                0.00 MB/sec
Concurrency:                3.31
Successful transactions:          19
Failed transactions:              21
Longest transaction:            4.15
Shortest transaction:            0.01

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

清理配置。

istioctl delete routerule recommendation-v1-v2 -n istio-tutorial
istioctl delete -f istiofiles/recommendation_cb_policy_version_v2.yml -n istio-tutorial

Pool Ejection

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

将 v1 和 v2 的流量均分。

istioctl create -f istiofiles/route-rule-recommendation-v1_and_v2_50_50.yml -n istio-tutorial

增加 v2 的实例个数。

kubectl scale deployment recommendation-v2 --replicas=2 -n istio-tutorial
kubectl get pods -w

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

现在到 v2 的容器中操作。

$ kubectl exec recommendation-v2-785465d9cd-225ms -c recommendation /bin/bash
$ curl localhost:8080/misbehave
Following requests to '/' will return a 503

增加 Pool Ejection 配置。

istioctl create -f istiofiles/recommendation_cb_policy_pool_ejection.yml -n istio-tutorial

此时再访问 customer 服务。

$ bin/poll_customer.sh
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10505
customer => preference => recommendation v2 from '785465d9cd-225ms': 2407
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10506
customer => preference => recommendation v2 from '785465d9cd-225ms': 2408
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10507
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10508
customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10509
customer => 503 preference => 503 recommendation misbehavior from '785465d9cd-ldc6j'
customer => preference => recommendation v2 from '785465d9cd-225ms': 2409
customer => preference => recommendation v2 from '785465d9cd-225ms': 2410

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

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

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

istioctl replace -f istiofiles/route-rule-recommendation-v1_and_v2_retry.yml -n istio-tutorial

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

清理配置。

kubectl scale deployment recommendation-v2 --replicas=1 -n istio-tutorial
istioctl delete routerule recommendation-v1-v2 -n istio-tutorial
istioctl delete -f istiofiles/recommendation_cb_policy_pool_ejection.yml -n istio-tutorial

Egress

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

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

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

构建示例镜像 egresshttpbin。

cd egress/egresshttpbin/
mvn clean package
docker build -t jimmysong/istio-tutorial-egresshttpbin:v1 .
docker push jimmysong/istio-tutorial-egresshttpbin:v1

部署到 Kubernetes。

kubectl apply -f <(istioctl kube-inject -f egress/egresshttpbin/src/main/kubernetes/Deployment.yml) -n istio-toturial
kubectl create -f egress/egresshttpbin/src/main/kubernetes/Service.yml

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

构建示例镜像 egressgithub。

cd egress/egressgithub
mvn clean package
docker build -t jimmysong/istio-tutorial-egressgithub:v1 .
docker push jimmysong/istio-tutorial-egressgithub:v1

部署到 Kubernetes。

kubectl apply -f <(istioctl kube-inject -f egress/egressgithub/src/main/kubernetes/Deployment.yml) -n istio-tutorial
kubectl create -f egress/egressgithub/src/main/kubernetes/Service.yml

增加 Egress 配置。

istioctl create -f istiofiles/egress_httpbin.yml -n istio-tutorial

到 egresshttpbin 容器中测试。

kubectl exec -it $(oc get pods -o jsonpath="{.items[*].metadata.name}" -l app=egresshttpbin,version=v1) -c egresshttpbin /bin/bash

curl localhost:8080

curl httpbin.org/user-agent

curl httpbin.org/headers

exit
cat <<EOF | istioctl create -f -
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
  name: jimmysong-egress-rule
  namespace: istio-tutorial
spec:
  destination:
    service: jimmysong.io
  ports:
    - port: 443
      protocol: https
EOF

增加 Egress 配置。

istioctl create -f istiofiles/egress_github.yml -n istio-tutorial

到 egressgithub 容器中测试。

kubectl exec -it $(oc get pods -o jsonpath="{.items[*].metadata.name}" -l app=egressgithub,version=v1) -c egressgithub /bin/bash

curl http://jimmysong:443

exit

清理环境。

istioctl delete egressrule httpbin-egress-rule jimmysong-egress-rule github-egress-rule -n istio-tutorial

参考

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

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

,

详细信息请参阅

customer 和 preference 微服务是基于 Spring Boot 构建的,recommendation 微服务是基于 构建的。

Jaeger UI 地址

服务访问地址:

服务访问地址:

服务访问地址:

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

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

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

现在访问 将看到如下输出:

访问 查看服务的分布式追踪和依赖关系。

访问 查看服务间的关系图和 QPS。

访问 查看 Service Mesh 的监控信息。

User-agent 是一个字符串,其中包含了浏览器的信息,访问 获取你的 user-agent。

谁用 Safari 或者 Chrome(Chrome 浏览器的 user-agent 中也包含 Safari 字段)访问 在经过 3 秒钟(我们在前面重新编译 v2 镜像,设置了 3 秒超时时间)后将看到访问 v2 的输出。

增加对 的 egress 配置。

Istio 官方文档
istio-handbook
redhat-developer-demos/istio-tutorial
kubernetes-vagrant-centos-cluster
https://github.com/rootsongjc/istio-tutorial
kubetail
siege
kubernetes-vagrant-centos-cluster
kubernetes-vagrant-centos-cluster
https://istio.io/docs/guides/bookinfo.html
vert.x
http://localhost:16686
http://localhost:8280
http://localhost:8180
http://localhost:8080
http://localhost:8280
http://localhost:16686
fabric8/java-jboss-openjdk8-jdk
run-java.sh
http://customer.istio-tutorial.jimmysong.io
http://servicegraph.istio.jimmysong.io/dotviz
http://servicegraph.istio.jimmysong.io/dotviz
http://grafana.istio.jimmysong.io
https://www.whoishostingthis.com/tools/user-agent
http://customer.istio-tutorial.jimmysong.io/
jimmysong.io
https://github.com/redhat-developer-demos/istio-tutorial
Book - Introducing Istio Service Mesh for Microservices
http://grafana.istio.jimmysong.io
http://servicegraph.istio.jimmysong.io/dotviz
http://servicegraph.istio.jimmysong.io/graph
http://zipkin.istio.jimmysong.io
Jaeger query UI
分布式追踪
依赖关系
服务关系图和QPS
Grafana 监控