初识 Istio - 服务网格管理工具
What is a service mesh(服务网格)?
微服务在国内流行已经多年了,大多数公司选择了基于容器化技术( Docker )以及容器编排管理平台 ( Kubernetes )落地微服务 ,然而这仅仅是个开始,微服务的发展没有停滞。
相信在调研微服务开发框架的过程中,会发现成熟的框架如 Spring Cloud ,Dubbo,Microprofile,它们都提供了诸如服务发现、负载均衡、故障恢复、度量和监控等方面的解决方案,但是都不同程度的产生了很多业务无关的代码。运维层面,在 Kubernetes 平台上要实现一些常见需求很不容易,例如 A/B 测试、金丝雀发布、速率限制、访问控制和端到端认证等。
2016 年开发 Linkerd 的 Buoyant 公司提出,要在开发和运维中间增加一层基础设施,提供对网络流量的洞察和操作控制的能力,包括服务注册发现、负载均衡、故障恢复、监控、权限控制等等,而这层基础设施就称作服务网格。
What is Istio?
Istio 是谷歌对于服务网格的实现,支持 Kubernetes,Consul,VMs等多种环境,并作为透明的一层接入到现有的微服务应用程序里,提供了如下功能:
- 为 HTTP、gRPC、WebSocket 和 TCP 流量自动负载均衡。
- 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。
- 可插拔的策略层和配置 API,支持访问控制、速率限制和配额。
- 集群内(包括集群的入口和出口)所有流量的自动化度量、日志记录和追踪。
- 在具有强大的基于身份验证和授权的集群中实现安全的服务间通信。
How istio work?
Istio 的架构图如下,istio 服务网格,分为控制面和数据面,所有流量都从 istio 的 ingress 进,从 egress出,以 Kubernetes 为例,上图的两个 Service 对应 Kubernetes 中的 Pod,istio 使用 sidecar 模式,给每个 Pod 加了一层代理,实际请求通通路由到代理,满足条件才路由给 Pod,至于控制面很简单,就是把路由规则同步给各个代理,并且完成一些管理,安全,遥测工作。可以发现网格中 Kubernetes 的网络完全被 istio 接管了,每个 Pod 和其代理构成了一个个对外零信任的高内聚的小格子。

插一句,Docker 提倡每个进程一个容器,Kubernetes 提倡每个容器一个 Pod,istio 又提倡给每个 Pod 一个格子,最小单元变的越来越大了,每个格子外面还会接着套么?
探秘 Istio 流量管理
流量管理无疑是 Istio 的核心,流量管理的核心又是 sidecar 代理,正是通过一个个 sidecar 代理,istio 能清晰的知道流量从哪来到哪去,从而很方便的实现,日志收集,遥测,追踪,监控,限流等功能。下面让我们一起近距离体验一下 Istio 的流量管理功能。
安装
参照 官方教程 安装 Isito demo profile,如下所示 Istio 相关的服务全装到了 istio-system 的 namespace。其中 istiod 是 istio 的核心服务,Pilot(服务发现),Galley(配置管理),Citadel(证书管理)等服务被统一成了 istiod,istiod 中 跑着 discovery 进程,用于监听 Kubernetes 的 ApiServer 并且实时把配置跟新到各个 sidecar 代理中。istio-ingressgateway 以及 istio-egressgateway 是 demo 模式下默认安装,运行中 Pilot 的客户端,接受配置实时跟新规则,envoy 是类似 ngnix 的轻量级代理工具。istio-ingressgateway 和Kubernetes 平台中的 nginx-ingress 组建起相同作用,作为平台外部请求进入网格的入口。其他 grafana,jaeger,kiali,prometheus为 istio 集成的可观察性相关的组件。
chenling@ChendeMacBook-Pro ~ % kubectl get pod -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-767c5487d6-j5l92 1/1 Running 0 5d5h
istio-egressgateway-55856f9f8f-s78md 1/1 Running 0 5d21h
istio-ingressgateway-85fbcc77b8-8rsfk 1/1 Running 0 5d21h
istiod-6dc785c4b9-z8v9v 1/1 Running 0 5d21h
jaeger-566c547fb9-zbhn7 1/1 Running 0 5d5h
kiali-89fd7f87b-r64dw 1/1 Running 0 5d21h
prometheus-788c945c9c-xn8mz 2/2 Running 0 5d5h
chenling@ChendeMacBook-Pro ~ % kubectl exec -it istiod-6dc785c4b9-z8v9v -n istio-system -- ps -ef
UID PID PPID C STIME TTY TIME CMD
istio-p+ 1 0 3 Sep27 ? 00:28:28 /usr/local/bin/pilot-discovery d
istio-p+ 34 0 0 00:41 pts/0 00:00:00 sh
istio-p+ 112 0 0 08:04 pts/1 00:00:00 ps -ef
chenling@ChendeMacBook-Pro ~ % kubectl exec -it istio-ingressgateway-85fbcc77b8-8rsfk -n istio-system -- ps -ef
UID PID PPID C STIME TTY TIME CMD
istio-p+ 1 0 0 Sep27 ? 00:01:38 /usr/local/bin/pilot-agent proxy
istio-p+ 14 1 1 Sep27 ? 00:08:48 /usr/local/bin/envoy -c etc/isti
istio-p+ 65 0 0 08:04 pts/0 00:00:00 ps -ef
注入
通过给 default namespace 打如下标签,pod 创建时会自动注入 sidecar
$ kubectl label namespace default istio-injection=enabled
当我们通过 Kubernetes 的客户端工具给 ApiServer 发送指令时,平台的 Scheduler 调度服务,会监听创建请求,并找到合适的机器,把相关信息传给 ApiServer 并把原数据写入 etcd,Isito 的 Pilot 采用类似机制监听ApiServer ,当 namespace 被打上自动注入标签,就会修改创建 pod 的原数据,增加 sidecar 代理容器到 pod 中,并且监听到 Istio 自定义的资源变动,通知到相关的 sidecar。

当然也可以手动注入 sidecar,手动注入会启动新的 pod
istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml
书写 deployment 资源文件,注入完成之后如下所示,为啥 Pod 中有 2 个容器?
chenling@ChendeMacBook-Pro ~ % kubectl get pod
NAME READY STATUS RESTARTS AGE
client-6b495f748b-tgt97 2/2 Running 2 23h
hello-bc8bb7cd6-pvvkv 2/2 Running 0 24h
hello-new-5b7cbf7df4-ksxtg 2/2 Running 0 24h
默认容器是我们声明的,运行着一个 httpd 服务
chenling@ChendeMacBook-Pro ~ % kubectl exec -it hello-bc8bb7cd6-pvvkv -- ps -ef
Defaulting container name to hello.
Use 'kubectl describe pod/hello-bc8bb7cd6-pvvkv -n default' to see all of the containers in this pod.
PID USER TIME COMMAND
1 root 0:00 httpd -f -p 8080 -h /var/www
435 root 0:00 ps -ef
查看 pod 中另外一个容器,可以发现和 istio-gateway 一样,其实运行着一个 envoy 代理服务,通过 pilot-agent 接受控制面信息。
chenling@ChendeMacBook-Pro ~ % kubectl exec -it hello-bc8bb7cd6-pvvkv -c istio-proxy -- ps -ef
UID PID PPID C STIME TTY TIME CMD
istio-p+ 1 0 0 Sep27 ? 00:01:50 /usr/local/bin/pilot-agent proxy
istio-p+ 15 1 1 Sep27 ? 00:05:24 /usr/local/bin/envoy -c etc/isti
istio-p+ 140 0 0 08:13 pts/0 00:00:00 ps -ef
注入流程
下面我们看看注入过程,首先被注入的pod中增加了名为 istio-init 的 initContainer,如下日志显示初始化过程,通过在容器 iptables nat 表中增加规则,把所有非 Istio 的入站流量重定向到 15006 端口,所有非 Istio 的出站流量定向到 15001 端口
chenling@ChendeMacBook-Pro ~ % kubectl logs --tail=32 hello-bc8bb7cd6-pvvkv -c istio-init
iptables-save
# Generated by iptables-save v1.6.1 on Sun Sep 27 07:20:03 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:ISTIO_INBOUND - [0:0]
:ISTIO_IN_REDIRECT - [0:0]
:ISTIO_OUTPUT - [0:0]
:ISTIO_REDIRECT - [0:0]
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
COMMIT
# Completed on Sun Sep 27 07:20:03 2020
如下所示 ,15006 和 15001 端口都是 envoy 提供
chenling@ChendeMacBook-Pro ~ % kubectl exec -it hello-bc8bb7cd6-pvvkv -c istio-proxy -- netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:15021 0.0.0.0:* LISTEN 15/envoy
tcp 0 0 0.0.0.0:15090 0.0.0.0:* LISTEN 15/envoy
tcp 0 0 127.0.0.1:15000 0.0.0.0:* LISTEN 15/envoy
tcp 0 0 0.0.0.0:15001 0.0.0.0:* LISTEN 15/envoy
tcp 0 0 0.0.0.0:15006 0.0.0.0:* LISTEN 15/envoy
tcp6 0 0 :::15020 :::* LISTEN 1/pilot-agent
tcp6 0 0 :::8080 :::* LISTEN -
综上所述,istio流量管理的实现大致如下
- 通过自动注入,给 pod 增加 iptables,把所有进出流量指向 envoy
- 控制面的 pilot 监控 istio 自定义资源变化,把规则发送给各个 sidecar
- sidecar 中的 pilot-agent 接受 pilot 的信息,热更新 envoy 代理规则,无需重启 pod即可改变流量路径
配置
实践一下配置网格行为
- 配置名为 xingren-gateway 的 Istio Gateway 接受所有 host为 xingren.upup 的外部流量
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: xingren-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- xingren.upup
- 配置 VirtualService 接受所有来自 ingren-gateway,host 为 xingren.upup 或者 hello 的流量
- 如果 http header 中 version 字段为 new,流量转到 new 子集,并且设置了 5 秒的超时时间,并且以 10% 的比例,注入一个10秒的请求延迟,已验证服务的容错能力
- 如果 http header 中 version 字段不存在,或者不是 new,则 70% 流量转到 latest 子集, 30% 流量转到 new 子集
- 配置可复用的 DestinationRule,定义了 latest 子集和 new 子集,按照 version 标签匹配到 Kubernetes hello 服务下的真实pod,同时设置了并发请求不能大于1的熔断规则
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: hello-virtualservice
spec:
hosts:
- hello
- xingren.upup
gateways:
- xingren-gateway
http:
- match:
- headers:
version:
exact: new
route:
- destination:
host: hello
subset: new
fault:
delay:
percentage:
value: 10
fixedDelay: 10s
timeout: 5s
- route:
- destination:
host: hello
subset: latest
weight: 70
- destination:
host: hello
subset: new
weight: 30
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: hello-destinationrule
spec:
host: hello
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
tcp:
maxConnections: 1
subsets:
- name: latest
labels:
version: latest
- name: new
labels:
version: new
当然 istio 的功能远远不止这些,详见 官网案例
可视化
可以通过如下命令观察服务网格,当然也可以通过网关暴露出去
chenling@ChendeMacBook-Pro ~ % istioctl dashboard --help
Access to Istio web UIs
Usage:
istioctl dashboard [flags]
istioctl dashboard [command]
Aliases:
dashboard, dash, d
Available Commands:
controlz Open ControlZ web UI
envoy Open Envoy admin web UI
grafana Open Grafana web UI
jaeger Open Jaeger web UI
kiali Open Kiali web UI
prometheus Open Prometheus web UI
zipkin Open Zipkin web UI
向服务中注入一些流量
chenling@ChendeMacBook-Pro ~ % for i in `seq 1000`; do wget -q -O - http://xingren.upup; sleep 0.2;done
Hello World(new)
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World(new)
Hello World
Hello World
Hello World
Hello World(new)
Hello World
Hello World
Hello World
Hello World(new)
Hello World
...
观察 istio 的可视化界面 kiali,可以看到流量从外部通过 hello 虚拟服务进入 pod,并且权重 大致 7比3

总结
Istio 出色的完成了服务网格该有的功能,且有很强的可扩展性,可以方便的整合 prometheus,jaeger 等工具,随着迭代易用性也有所提高。虽然 Istio 还没有被大规模用于生产环境 ,并且有质疑其占用了过多的资源,总的来说利大于弊,经实验,没有被 Istio 注入的 pod 访问被注入的资源,不会受到任何影响,会直接透传给真实pod,所以还是可以小范围尝鲜 Istio 的。
初识 Istio - 服务网格管理工具的更多相关文章
- Istio最佳实践:在K8s上通过Istio服务网格进行灰度发布
Istio是什么? Istio是Google继Kubernetes之后的又一开源力作,主要参与的公司包括Google,IBM,Lyft等公司.它提供了完整的非侵入式的微服务治理解决方案,包含微服务的管 ...
- 【译文连载】 理解Istio服务网格(第一章 概述)
书籍英文版下载链接为 https://developers.redhat.com/books/introducing-istio-service-mesh-microservices/,作者 Burr ...
- 【译文连载】 理解Istio服务网格(第六章 可观测性)
全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 本文目录 第6章 可观测性 6.1 分布式调用链跟踪(tracing) 6.1.1 基本概念 6.1.2 Ja ...
- 【译文连载】 理解Istio服务网格(第七章 安全)
全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 第六章 可观测性 本文目录 第7章 安全 7.1 身份认证 7.1.1 Kubernetes上的Istio的身份 ...
- Istio(十一):向istio服务网格中引入虚拟机
目录 一.模块概览 二.系统环境 三.虚拟机负载 3.1 虚拟机负载 3.2 单网络架构 3.3 多网络架构 3.4 Istio 中如何表示虚拟机工作负载? 四.实战:向istio Mesh中引入虚拟 ...
- 【译文连载】 理解Istio服务网格(第三章 流控)
第3章 流控.............................................................................................. ...
- 【译文连载】 理解Istio服务网格(第二章 安装)
全书目录 第一章 概述 本文目录 1.命令行工具安装 2. Kubernetes/OpenShift安装 3. Istio安装 4.示例Java微服务安装 4.1 源码概览 4.2 编译和部署cust ...
- 华为云Istio服务网格,让应用治理智能化、可视化
- Service Mesh服务网格新生代--Istio(转)
万字解读:Service Mesh服务网格新生代--Istio 官网地址:https://preliminary.istio.io/zh/docs/concepts/security/ Servic ...
随机推荐
- Spring Boot 通过CORS实现跨域
同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由 Netscape 提出的一个著名的安全策略,它是浏览器最核心也 ...
- Linq 下的扩展方法太少了,您期待的 MoreLinq 来啦
一:背景 1. 讲故事 前几天看同事在用 linq 给内存中的两个 model 做左连接,用过的朋友都知道,你一定少不了一个叫做 DefaultIfEmpty 函数,这玩意吧,本来很流畅的 from. ...
- 软件开发流变史:从瀑布开发到敏捷开发再到DevOps
作为在20世纪70年代.80年代盛极一时的软件开发模型,瀑布模型通过制定计划.需求分析.软件设计.程序编写.软件测试.运行维护等6个流程将整个软件生命周期衔接起来.这6个流程有着严格的先后次序之分,只 ...
- 一位北漂12年IT工程师的年终总结
Hi,我叫李振良,来自河南周口农村的一个普通家庭,如今来北京已经12年了,我是那种没有大学背景.没有聪明头脑.没有人脉的奋斗青年,但我又是那种不甘于现状,一直想做最好的那个人! 2019年已悄然离去, ...
- 2020年1月31日 安装Python的BeautifulSoap库记录
C:\Users\ufo>pip install beautifulsoup4 Collecting beautifulsoup4 WARNING: Retrying (Retry(total= ...
- if __name__ == ‘__main__‘
if __name__ == '__main__': def_test() 作为程序的入口,当函数被调用时会从此处开始运行 如被导入的模块内没写 if __name__ == '__main__',则 ...
- 浏览器调试的必知必会,零基础足够详细-第一节console面板、移动端调试
前言 本文已经发布视频点击查看 开发过程中,浏览器的调试非常重要,可以说是必备的技巧,本文我就会分享一些自己掌握的技巧,欢迎补充 我们默认使用Chrome浏览器,但是你使用新edge浏览器也是可以的 ...
- Java面试炼金系列 (1) | 关于String类的常见面试题剖析
Java面试炼金系列 (1) | 关于String类的常见面试题剖析 文章以及源代码已被收录到:https://github.com/mio4/Java-Gold 0x0 基础知识 1. '==' 运 ...
- Java反序列漏洞
序列化:WriteObject 反序列化:readObject() Jd-gui.exe 最简单的打开java文件方式 Intellij idea 编辑工具 演示案例: WebGoat_Javaweb ...
- NOIP2017 Day1 T1 小凯的疑惑
题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的.现在小凯想知道在无法准确支付的物品中,最贵的价 ...