1 准备工作

1.1 在k8s部署istio

Istio在k8s集群内的部署很简单,非生产要求的部署,可以直接在https://github.com/istio/istio/releases 下载最新的发布包,压缩包里有供简单部署的yaml文件:

$ for i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i; done
$ kubectl apply -f install/kubernetes/istio-demo.yaml

注意,上面两条指令会把主要的组件都给装上,镜像下载比较费力,内存消耗也比较大。没个十几G内存的同学请慎重。

部署完成后会新增一个命名空间istio-system:

$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-f8467cc6-rbjlg 1/1 Running 0 1m
istio-citadel-78df5b548f-g5cpw 1/1 Running 0 1m
istio-cleanup-secrets-release-1.1-20190308-09-16-8s2mp 0/1 Completed 0 2m
istio-egressgateway-78569df5c4-zwtb5 1/1 Running 0 1m
istio-galley-74d5f764fc-q7nrk 1/1 Running 0 1m
istio-grafana-post-install-release-1.1-20190308-09-16-2p7m5 0/1 Completed 0 2m
istio-ingressgateway-7ddcfd665c-dmtqz 1/1 Running 0 1m
istio-pilot-f479bbf5c-qwr28 2/2 Running 0 1m
istio-policy-6fccc5c868-xhblv 2/2 Running 2 1m
istio-security-post-install-release-1.1-20190308-09-16-bmfs4 0/1 Completed 0 2m
istio-sidecar-injector-78499d85b8-x44m6 1/1 Running 0 1m
istio-telemetry-78b96c6cb6-ldm9q 2/2 Running 2 1m
istio-tracing-69b5f778b7-s2zvw 1/1 Running 0 1m
kiali-99f7467dc-6rvwp 1/1 Running 0 1m
prometheus-67cdb66cbb-9w2hm 1/1 Running 0 1m

1.2 istio自动注入

在介绍istio原理时有提到,istio会在每一个被管理的pod里注入一个sidecar容器envoy。那么istio是如何完成注入的呢,主要有2种方式:

  1. 手动注入:如下命令,在kubectl前先执行istioctl手动注入
$ istioctl kube-inject -f <your-app-spec>.yaml | kubectl apply -f -
  1. 自动注入:运用k8s的admission-control完成自动注入

    • kube-apiserver配置文件的admission-control参数,增加MutatingAdmissionWebhook 以及 ValidatingAdmissionWebhook 两项

    • 给命名空间打上自动注入的标签(下方我们允许istio在default空间自动注入,同时禁用了istio-system空间的自动注入):
$ kubectl label namespace default istio-injection=enabled
$ kubectl get namespace -L istio-injection
NAME STATUS AGE ISTIO-INJECTION
default Active 4d21h enabled
ingress-nginx Active 4d17h
istio-system Active 4d17h disabled
kube-node-lease Active 4d21h
kube-public Active 4d21h
kube-system Active 4d21h

后面的测试,我们以第2种方式自动注入envoy。

注:通过在deployment文件的annotations参数里加上sidecar.istio.io/inject: "false",可以覆盖命名空间的标签,禁止istio对本pod的自动注入

1.3 应用部署要求

Istio原生与k8s能够无缝对接, istio的存在与否对应用程序本身来说,也是透明的。所以应用的部署,主要涉及的是yaml文件的修改完善:

  1. Deployment文件的要求:

    • 应带有app和version标签,这个主要是用来识别不同版本的pod。

    • Deployment应明确列出端口列表,istio会忽略未列出的端口。

    • 下方为data-product的示例,注释部分为需要注意的地方:
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
# 建议pod名称 = 应用名 + 版本号
name: data-product-v4.0
namespace: default
spec:
template:
metadata:
annotations:
sidecar.istio.io/inject: "true"
namespace: default
labels:
# 标签1:应用名称
app: data-product
# 标签2:版本号
version: v4.0
spec:
containers:
- name: data-product
ports:
# 需要Istio管理的端口号列表
- containerPort: 50051
……
  1. Service文件的要求:

    • 需要指定端口的协议类型,否则默认按TCP协议处理:
---
apiVersion: v1
kind: Service
metadata:
name: data-product
namespace: default
annotations:
prometheus.io/scrape: 'true'
prometheus.io/path: /metrics
prometheus.io/port: '8081'
labels:
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "data-product"
spec:
ports:
- name: data-product
port: 50051
# 指定端口的协议类型为grpc
name: grpc
targetPort: 50051
selector:
app: data-product

2 负载均衡

$ kubectl get po -o wide
NAME READY STATUS
business-product-6b954db744-cgn8k 2/2 Running
business-product-6b954db744-dgm4x 2/2 Running
business-product-6b954db744-n5c8p 2/2 Running
business-product-v4.0-747ccffbb4-2p2z8 2/2 Running
business-product-v4.0-747ccffbb4-4bh6z 2/2 Running
business-product-v4.0-747ccffbb4-8kgqs 2/2 Running
business-product-v4.0-747ccffbb4-hz6lb 2/2 Running
business-product-v4.0-747ccffbb4-kgs6p 2/2 Running
business-product-v4.0-747ccffbb4-rmmwg 2/2 Running
business-product-v4.0-747ccffbb4-sspgr 2/2 Running
business-product-v4.0-747ccffbb4-sz7ll 2/2 Running
business-product-v4.0-747ccffbb4-vnd58 2/2 Running
data-product-5bc9f7bb9c-dfchd 2/2 Running
data-product-5bc9f7bb9c-tv8cj 2/2 Running
data-product-5bc9f7bb9c-xzz7s 2/2 Running

这里我们启用了9个business-product的pod,和3个data-product的pod。上表有一个细节,每个pod里有2个容器,除了我们的应用程序容器外,还有一个就是enovy。

当pod被注入了enovy,并且是按1.3节的要求将port暴露给了istio,则Istio会自动接管pod的流量,实现负载均衡。

Business-product作为client与data-product server之间通过grpc通讯,这里我简单修改了下business-product和data-product的逻辑,当收到请求时data-product会将自身和client的ip作为响应,而business-product则会在这个响应的基础上再加上自己的ip。所以我们对business-product发起连续的请求,就能得到下方的一组ip对(其中每一行的第1个ip是client的ip,第2个是server检测到的client ip,第3个是server的ip):

"ip": "172.30.27.8/24 - 127.0.0.1:43094 - 172.30.86.3/24",
"ip": "172.30.95.17/24 - 127.0.0.1:43120 - 172.30.86.3/24",
"ip": "172.30.27.9/24 - 127.0.0.1:43094 - 172.30.86.3/24",
"ip": "172.30.86.9/24 - 127.0.0.1:41662 - 172.30.27.3/24",
"ip": "172.30.95.15/24 - 127.0.0.1:43094 - 172.30.86.3/24",
"ip": "172.30.86.7/24 - 127.0.0.1:41712 - 172.30.27.3/24",
"ip": "172.30.27.11/24 - 127.0.0.1:43872 - 172.30.95.7/24",
"ip": "172.30.86.8/24 - 127.0.0.1:41712 - 172.30.27.3/24",
"ip": "172.30.95.14/24 - 127.0.0.1:43944 - 172.30.95.7/24", "ip": "172.30.27.8/24 - 127.0.0.1:43944 - 172.30.95.7/24",
"ip": "172.30.95.17/24 - 127.0.0.1:43872 - 172.30.95.7/24",
"ip": "172.30.27.9/24 - 127.0.0.1:43944 - 172.30.95.7/24",
"ip": "172.30.86.9/24 - 127.0.0.1:43094 - 172.30.86.3/24",
"ip": "172.30.95.15/24 - 127.0.0.1:43872 - 172.30.95.7/24",
"ip": "172.30.86.7/24 - 127.0.0.1:43120 - 172.30.86.3/24",
"ip": "172.30.27.11/24 - 127.0.0.1:41662 - 172.30.27.3/24",
"ip": "172.30.86.8/24 - 127.0.0.1:43094 - 172.30.86.3/24",
"ip": "172.30.95.14/24 - 127.0.0.1:41712 - 172.30.27.3/24", "ip": "172.30.27.8/24 - 127.0.0.1:41712 - 172.30.27.3/24",
"ip": "172.30.95.17/24 - 127.0.0.1:41712 - 172.30.27.3/24",
"ip": "172.30.27.9/24 - 127.0.0.1:41712 - 172.30.27.3/24",
"ip": "172.30.86.9/24 - 127.0.0.1:43872 - 172.30.95.7/24",
"ip": "172.30.95.15/24 - 127.0.0.1:41662 - 172.30.27.3/24",
"ip": "172.30.86.7/24 - 127.0.0.1:43944 - 172.30.95.7/24",
"ip": "172.30.27.11/24 - 127.0.0.1:43094 - 172.30.86.3/24",
"ip": "172.30.86.8/24 - 127.0.0.1:43872 - 172.30.95.7/24",
"ip": "172.30.95.14/24 - 127.0.0.1:43120 - 172.30.86.3/24",

我们连续发起了27次请求,不出所料,client的9个Pod分别被分配到了3次请求,接下来我们看看server是否负载上了:

• 27次请求中,3个server的pod均被分配了9次,负载是均衡的。

• 进一步分析,同一个client,每次被分配到的server是不同的,这是因为envoy代理在中间拦了一手,这正是负载的实现原理。

• 再进一步分析,server检测到的客户端ip,是127.0.0.1的本地ip,这个连接其实是面向本pod的envoy的。

所以我们可以认为envoy为我们在网格内建立起了一个服务之间的连接池,从而实现了负载均衡。

最后,我们再回过头来对比针对grpc长连接的情况,k8s的负载和istio的负载的差异:

• K8s的负载是在连接发起时实现的,比如我们的例子里有9个客户端,则调用了9次负载算法,次数太少,负载未必是均衡的。

• 基于连接的负载,一旦pod异常退出,连接断开,重新建立起的连接有更大的概率被集中到个别没断开的pod上,这会加剧负载的不均衡性。

• Istio维护的负载是在每次通讯的时候完成的动态调度,不受连接数的限制,在大量通讯的情况下,istio能够保证负载的均衡。

3 流量迁移:金丝雀发布

上一章envoy已经接管了我们的流量,接下来就可以让envoy为我们做更细致的流量管理的动作了。本章我们会通过简单的配置来实现金丝雀发布。

假设我们已经发布了data-product的v3.0版本,现在我们有一个v4.0的版本需要更新上去。版本发布过程中我们期望先将10%的流量导入到v4.0版本,剩余90%的流量还是由v3.0版本来处理。待v4.0版本运行稳定无异常后,我们再将100%的流量迁移到v4.0版本。

3.1 发布应用

回顾1.3章节,我们在发布data-product时,需要deployment的名称区分版本(想想为啥?)。为实现两个版本的平滑过渡、金丝雀发布,我们需要同时发布两个版本的deployment:

$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
business-product 3/3 3 3 5h13m
data-product 3/3 3 3 4h30m
data-product-v4.0 3/3 3 3 4h16m

上表data-product是v3.0版本的(这里我命名不规范),data-product-v4.0是v4.0版本的,各有3个pod在运行。

3.2 创建目标规则:DestinationRule

目标规则(DestinationRule)是用来定义流量应该由哪些pod来接收的。下方的yaml文件我们创建了一个DestinationRule,标识发往data-product的流量,由data-product的v3.0和v4.0两个版本来接收。这个yaml文件的关键是subsets字段的两个labels,这对应着1.3和3.1节的应用版本。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: data-product
spec:
host: data-product
subsets:
- name: v3
labels:
version: v3.0
- name: v4
labels:
version: v4.0

3.3 创建虚拟服务:VirtualService

Service和virtualservice的目标是一致的,都是将流量导向后端的pod。区别是由istio引入的virtualservice可以完成更细致的流量划分。

下方的yaml文件,我们将10%的流量导向了v4版本,90%的流量导向v3版本。这个文件的关键是subset字段,这对应于DestinationRule的subsets;以及weight权重,按百分比划分。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: data-product
spec:
hosts:
- data-product
http:
- route:
- destination:
host: data-product
subset: v3
weight: 90
- destination:
host: data-product
subset: v4
weight: 10

3.4 验证和结语

限于篇幅,验证数据就不贴了。平均每10次请求,会有1次导向v4,另外9次还在v3。

不难理解,运行一段时间觉得v4版本ok了,我们可以将权重配比调整到50%,75%,直到100%的流量都导向v4。之后v3版本的deployment就可以删了。

istio流量管理的更多相关文章

  1. Istio流量管理实现机制深度解析

    https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/TOC 前言 Pilot高层架构 统一的服务模型 ...

  2. Istio流量管理能力介绍

    1      Istio是什么? Istio 1.0版本于8月1号凌晨准点发布,核心特性已支持上生产环境,各大微信公众号.博客纷纷发文转载.那么Istio到底是什么?能解决问题什么? 1. Istio ...

  3. [Istio]流量管理API v1alpha3路由规则

    Istio提供一个API进行流量管理,该API允许用户将请求路由到特定版本的服务,为弹性测试注入延迟和失败,添加断路器等,所有这些功能都不必更改应用程序本身的代码.Istio 1.0中引入新的流量管理 ...

  4. istio流量管理:非侵入式流量治理

    在服务治理中,流量管理是一个广泛的话题,一般情况下,常用的包括: 动态修改服务访问的负载均衡策略,比如根据某个请求特征做会话保持: 同一个服务有多版本管理,将一部分流量切到某个版本上: 对服务进行保护 ...

  5. Istio流量管理实践之(3): 基于Istio实现流量对比分析

    流量镜像 流量镜像,也称为影子流量,流量镜像提供一种尽可能低的风险为生产带来变化的强大功能.镜像会将实时流量的副本发送到镜像服务.镜像流量发生在主服务的关键请求路径之外. 在非生产或者测试环境中,尝试 ...

  6. Istio技术与实践05:如何用istio实现流量管理

    Istio是Google继Kubernetes之后的又一开源力作,主要参与的公司包括Google,IBM,Lyft等,它提供了完整的非侵入式的微服务治理解决方案,解决微服务的管理.网络连接以及安全管理 ...

  7. Istio的流量管理(概念)(istio 系列二)

    Istio的流量管理(概念) 目录 Istio的流量管理(概念) 概述 Virtual services 为什么使用virtual service Virtual services举例 hosts字段 ...

  8. Istio入门实战与架构原理——使用Docker Compose搭建Service Mesh

    本文将介绍如何使用Docker Compose搭建Istio.Istio号称支持多种平台(不仅仅Kubernetes).然而,官网上非基于Kubernetes的教程仿佛不是亲儿子,写得非常随便,不仅缺 ...

  9. 二 Istio设计的核心原则

    Istio架构关键目标 最大化透明度:Istio将自身自动注入到服务间所有的网络路径中.Istio使用sidecar代理来捕获流量,并且在尽可能的地方自动编程网络层,通过代理来路由流量,无需改动应用程 ...

随机推荐

  1. ObjectARX之Mac os开发

    网上关于ObjectARX开发的相关介绍都基于Windows环境.Mac 环境的开发几乎没有,下面介绍Mac环境下ObjectARX的开发. AutoCAD ObjectARX开发必备条件: 1. 安 ...

  2. 201871010128-杨丽霞《面向对象程序设计(Java)》第十一周学习总结

    201871010128-杨丽霞<面向对象程序设计(Java)>第十一周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...

  3. Netty粘包问题(六)

    netty使用tcp/ip协议传输数据,而tcp/ip协议是类似水流一样的数据传输方法.多次访问的时候可能出现粘包的问题,解决这种问题的方式有如下几种. 一.定长数据流 二.特殊结束符 三.

  4. WebSocket协议-基础篇

    本篇文章主要讲述以下几点: WebSocket协议出现的背景 WebSocket与HTTP WebSocket API WebSocket协议出现的背景 我们在上网过程中经常用到的是HTTP和HTTP ...

  5. webapi中获取HttpContext

    public OperationResultDto APILogin() { LoginModel model = new LoginModel(); HttpContextBase context ...

  6. requests--超时设置,代理设置,身份认证

    超时设置 你可以告诉 requests 在经过以 timeout 参数设定的秒数时间之后停止等待响应.基本上所有的接口都应该使用这一参数.如果不使用,你的程序可能会永远失去响应 import requ ...

  7. how to design AWS SQS?

    遇到这么一题system design,怎么做? 几个月以前,有同事提出要用Webapi代替现有的WCF,当时我投的反对票.而且我给了很充分的理由,不仅仅是时间不足,人手不够,更重要的是这个变化太大, ...

  8. Web协议详解与抓包实战:HTTP1协议-如何用Chrome的Network面板分析HTTP报文(1)

    一.Chrome 抓包:Network 面板 1. Network 面板 • 控制器:控制面板的外观与功能 • 过滤器:过滤请求列表中显示的资源 • 按住 Command (Mac)或 Ctrl (W ...

  9. JAVA SE11环境变量配置(Windows)

    附上:03. 安装环境:Windows · IntelliJ IDEA Tutorial 附上:使用调试功能进行 Java debug 附上:Linux(Deepin)下配置java8 - L1412 ...

  10. Knative Serving 进阶: Knative Serving SDK 开发实践

    作者 | 阿里云智能事业群技术专家 牛秋霖(冬岛) 导读:通过前面的一系列文章你已经知道如何基于 kubectl 来操作 Knative 的各种资源.但是如果想要在项目中集成 Knative 仅仅使用 ...