Istio 介绍
官方解释:An open platform to connect, secure, control and observe services.
翻译过来,就是”连接、安全加固、控制和观察服务的开放平台“。开放平台就是指它本身是开源的,服务对应的是微服务,也可以粗略地理解为单个应用。
- 1、连接(Connect):智能控制服务之间的调用流量,能够实现灰度升级、AB 测试和蓝绿部署等功能
- 2、安全加固(Secure):自动为服务之间的调用提供认证、授权和加密。
- 3、控制(Control):应用用户定义的 policy,保证资源在消费者中公平分配。
- 4、观察(Observe):查看服务运行期间的各种数据,比如日志、监控和 tracing,了解服务的运行情况。
Istio 是 ServiceMesh 的产品化落地,可以通过在现有的服务器新增部署边车代理(sidecar proxy),应用程序不用改代码,或者只需要改很少的代码,就能实现如下基础功能:
- 1、帮助微服务之间建立连接,帮助研发团队更好的管理与监控微服务,并使得系统架构更加安全;
- 2、帮助微服务分层解耦,解耦后的 proxy 层能够更加专注于提供基础架构能力
例如:
- (1)服务发现(discovery);
- (2)负载均衡(load balancing);
- (3)故障恢复(failure recovery);
- (4)服务度量(metrics);
- (5)服务监控(monitoring);
- (6)A/B 测试(A/B testing);
- (7)灰度发布;
- (8)限流限速(rate limiting);
- (9)访问控制(access control);
- (10)身份认证(end-to-end authentication)。
服务注册和发现
RPC:RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务。
负载均衡
把前端的请求分发到后台多个服务器。
故障恢复
出现故障具备自恢复的能力。
服务度量
对于 HTTP,HTTP/2 和 GRPC 流量,Istio 生成以下指标:
- 1、请求计数(istio_requests_total):这是一个用于累加每个由 Istio 代理所处理请求的 COUNTER 指标。
- 2、请求持续时间(istio_request_duration_seconds):这是一个用于测量请求的持续时间的 DISTRIBUTION 指标。
- 3、请求大小(istio_request_bytes):这是一个用于测量 HTTP 请求 body 大小的 DISTRIBUTION 指标。
- 4、响应大小(istio_response_bytes):这是一个用于测量 HTTP 响应 body 大小的 DISTRIBUTION 指标。
对于 TCP 流量,Istio 生成以下指标:
- 1、Tcp 发送字节数(istio_tcp_sent_bytes_total):这是一个用于测量在 TCP 连接下响应期间发送的总字节数的 COUNTER 指标。
- 2、Tcp 接收字节数(istio_tcp_received_bytes_total):这是一个用于测量在 TCP 连接下请求期间接收的总字节数的 COUNTER 指标。
- 3、Tcp 打开连接数(istio_tcp_connections_opened_total):这是一个用于累加每个打开连接的 COUNTER 指标。
- 4、Tcp 关闭连接数 (istio_tcp_connections_closed_total) : 这是一个用于累加每个关闭连接的 COUNTER 指标。
灰度发布
灰度发布也叫金丝雀发布,起源是,矿井工人发现,金丝雀对瓦斯气体很敏感,矿工会在下井之前,先放一只金丝雀到井中,如果金丝雀不叫了,就代表瓦斯浓度高。
在灰度发布开始后,先启动一个新版本应用,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,启动的这个新版本应用,就是我们的金丝雀。如果没有问题,那么可以将少量的用户流量导入到新版本上,然后再对新版本做运行状态观察,收集各种运行时数据,如果此时对新旧版本做各种数据对比,就是所谓的 A/B 测试。
当确认新版本运行良好后,再逐步将更多的流量导入到新版本上,在此期间,还可以不断地调整新旧两个版本的运行的服务器副本数量,以使得新版本能够承受越来越大的流量压力。直到将 100%的流量都切换到新版本上,最后关闭剩下的老版本服务,完成灰度发布。
如果在灰度发布过程中(灰度期)发现了新版本有问题,就应该立即将流量切回老版本上,这样,就会将负面影响控制在最小范围内。
Istio 核心特性
1、流控(traffic management)
断路器(circuit breakers)、超时、重试、多路由规则、AB 测试、灰度发布、按照百分比分配流量等。
2、安全(security)
加密、身份认证、服务到服务的权限控制、K8S 里容器到容器的权限控制等。
3、可观察(observability)
追踪、监控、数据收集,通过控制后台全面了解上行下行流量,服务链路情况,服务运行情况,系统性能情况,国内微服务架构体系,这一块做得比较缺乏。
4、平台无关系(platform support)
K8s,物理机,自己的虚机都没问题。
5、集成与定制(integration and customization)
可定制化扩展功能。
Istio 架构
istio 服务网格从逻辑上分为数据平面和控制平面。
1、数据平面由一组以 Sidecar(边车)方式部署的智能代理(Envoy+Polit-agent)组成。这些代理承载并控制微服务之间的所有网络通信,管理入口和出口流量,类似于一线员工。 Sidecar 一般和业务容器绑定在一起(在 Kubernets 中以自动注入的方式注入到到业务 pod 中),来劫持业务应用容器的流量,并接受控制面组件的控制,同时会向控制面输出日志、跟踪及监控数据,Envoy 和 pilot-agent 打在同一个镜像中,即 sidecar Proxy。
2、control plane 控制平面负责管理和配置代理来路由流量。 istio1.5+中使用了一个全新的部署模式,重建了控制平面,将原有的多个组件整合为一个单体结构istiod,这个组件是控制平面的核心,管理 Istio 的所有功能,主要包括 Pilot、Mixer、Citadel 等服务组件。
istiod 是新版本中最大的变化,以一个单体组件替代了原有的架构,降低了复杂度和维护难度,但原有的多组件并不是被完全移除,而是在重构后以模块的形式整合在一起组成了 istiod。
结合下图我们来理解 Istio 的各组件的功能及相互之间的协作方式。
1.自动注入:在创建应用程序时自动注入 Sidecar 代理 Envoy 程序。在 Kubernetes 中创建 Pod 时,Kube-apiserver 调用控制面组件的 Sidecar-Injector 服务,自动修改应用程序的描述信息并注入Sidecar。在真正创建 Pod 时,在创建业务容器的 Pod 中同时创建 Sidecar 容器。
2.流量拦截:在 Pod 初始化时设置 iptables 规则,基于配置的 iptables 规则拦截业务容器的 Inbound 流量和 Outbound 流量到 Sidecar 上。而应用程序感知不到 Sidecar 的存在,还以原本的方式进行互相访问。上图中,流出 frontend 服务的流量会被frontend 服务侧的 Envoy 拦截,而当流量到达 forecast 容器时,Inbound 流量被 forecast 服务侧的 Envoy 拦截。
3.服务发现:服务发起方的 Envoy 调用控制面组件 Pilot 的服务发现接口获取目标服务的实例列表。上图中,frontend 服务侧的 Envoy 通过 Pilot 的服务发现接口得到 forecast 服务各个实例的地址。
4.负载均衡:服务发起方的 Envoy 根据配置的负载均衡策略选择服务实例,并连接对应的实例地址。上图中,数据面的各个 Envoy 从 Pilot 中获取 forecast 服务的负载均衡配置,并执行负载均衡动作。
5.流量治理:Envoy 从 Pilot 中获取配置的流量规则,在拦截到 Inbound(入境) 流量和 Outbound 流量时执行治理逻辑。上图中, frontend 服务侧的 Envoy 从 Pilot 中获取流量治理规则,并根据该流量治理规则将不同特征的流量分发到 forecast 服务的 v1 或 v2 版本。
6.访问安全:在服务间访问时通过双方的 Envoy 进行双向认证和通道加密,并基于服务的身份进行授权管理。上图中,Pilot 下发安全相关配置,在 frontend 服务和 forecast 服务的 Envoy 上自动加载证书和密钥来实现双向认证,其中的证书和密钥由另一个管理面组件 Citadel 维护。
7.服务监测:在服务间通信时,通信双方的 Envoy 都会连接管理面组件 Mixer 上报访问数据,并通过 Mixer 将数据转发给对应的监控后端。上图中,frontend 服务对 forecast 服务的访问监控指标、日志和调用链都可以通过这种方式收集到对应的监控后端。
8.策略执行:在进行服务访问时,通过 Mixer 连接后端服务来控制服务间的访问,判断对访问是放行还是拒绝。上图中,Mixer 后端可以对接一个限流服务对从 frontend 服务到 forecast 服务的访问进行速率控制等操作。
9.外部访问:在网格的入口处有一个 Envoy 扮演入口网关的角色。上图中,外部服务通过 Gateway 访问入口服务 frontend,对 frontend 服务的负载均衡和一些流量治理策略都在这个 Gateway 上执行。
sidecar 和 proxy 相生相伴,就像汽车与车轮。未来,sidecar 和 proxy 就指微服务进程解耦成两个进程之后,提供基础能力的那个代理进程。
istio组件
Istio 服务组件有很多,从上面的流程中基本能看出每个组件如何协作的,下面具体讲解每个组件的具体用途和功能。
[root@k8smaster ~]# kubectl get svc -n istio-system | awk '{print $1}'
istio-egressgateway
istio-ingressgateway
istiod
Pilot
Pilot 是 Istio 的主要控制组件,下发指令控制客户端。在整个系统中,Pilot 完成以下任务:
- 1、从 Kubernetes 或者其他平台的注册中心获取服务信息,完成服务发现过程。
- 2、读取 Istio 的各项控制配置,在进行转换之后,将其发给数据面进行实施。
Pilot 将配置内容下发给数据面的 Envoy,Envoy 根据 Pilot 指令,将路由、服务、监听、集群等定义信息转换为本地配置,完成控制行为的落地。
- 1)Pilot 为 Envoy 提供服务发现
- 2)提供流量管理功能(例如,A/B 测试、金丝雀发布等)以及弹性功能(超时、重试、熔断器等);
- 3)生成 envoy 配置
- 4)启动 envoy
- 5)监控并管理 envoy 的运行状况,比如 envoy 出错时 pilot-agent 负责重启 envoy,或者 envoy 配置变更后 reload envoy
Envoy
Envoy 是用 C++ 开发的高性能代理,用于协调服务网格中所有服务的入站和出站流量。
Envoy 有许多强大的功能,例如:
- 动态服务发现
- 负载均衡
- TLS 终端
- HTTP/2 与 gRPC 代理
- 断路器
- 健康检查
- 流量拆分
- 灰度发布
- 故障注入
Istio 中 Envoy 与服务什么关系?
Envoy 和 Service A 同属于一个 Pod,共享网络和命名空间,Envoy 代理进出 Pod A 的流量,并将流量按照外部请求的规则作用于 Service A 中。
Pilot-agent 是什么?
Envoy 不直接跟 k8s 交互,通过 pilot-agent 管理的 Pilot-agent 进程根据 K8S APIserver 中的配置信息生成 Envoy 的配置文件,并负责启动 Envoy 进程。
Envoy 由 Pilot-agent 进程启动,启动后,Envoy 读取 Pilot-agent 为它生成的配置文件,然后根据该文件的配置获取到 Pilot 的地址,通过数据面从 pilot 拉取动态配置信息,包括路由(route),监听器(listener),服务集群(cluster)和服务端点(endpoint)。
Citadel
负责处理系统上不同服务之间的 TLS 通信。 Citadel 充当证书颁发机构(CA),并生成证书以允许在数据平面中进行安全的 mTLS 通信。
Citadel 是 Istio 的核心安全组件,提供了自动生成、分发、轮换与撤销密钥和证书功能。Citadel 一直监听 Kube- apiserver,以 Secret 的形式为每个服务都生成证书密钥,并在 Pod 创建时做一个卷挂载到 Pod 上,代理容器使用这些文件来做服务身份认证,进而代理两端服务实现双向 TLS 认证、通道加密、访问授权等安全功能。如图所示,frontend 服务对 forecast 服务的访问用到了 HTTP 方式,通过配置即可对服务增加认证功能,双方的 Envoy 会建立双向认证的 TLS 通道,从而在服务间启用双向认证的 HTTPS。
Galley
Galley 是 istio 的配置验证、提取、处理和分发的组件。Galley 是提供配置管理的服务。实现原理是通过 k8s 提供的 ValidatingWebhook 对配置进行验证。
Galley 使 Istio 可以与 Kubernetes 之外的其他环境一起工作,因为它可以将不同的配置数据转换为 Istio 可以理解的通用格式。
Ingressgateway
Ingressgateway 就是入口处的 Gateway,从网格外访问网格内的服务就是通过这个 Gateway 进行的。istio-ingressgateway 是一个 Loadbalancer 类型的 Service,不同于其他服务组件只有一两个端口,istio-ingressgateway 开放了一组端口,这些就是网格内服务的外部访问端口。如下图所示,网格入口网关 istio-ingressgateway 的负载和网格内的 Sidecar 是同样的执行流程,也和网格内的其他 Sidecar 一样从 Pilot 处接收流量规则并执行。
Sidecar-injector
Sidecar-injector 是负责自动注入的组件,只要开启了自动注 入,在 Pod 创建时就会自动调用 istio-sidecar-injector 向 Pod 中注入 Sidecar 容器。
在 Kubernetes 环境下,根据自动注入配置,Kube-apiserver 在拦截到 Pod 创建的请求时,会调用自动注入服务 istio-sidecar-injector 生成 Sidecar 容器的描述并将其插入原 Pod 的定义中,这样,在创建的 Pod 内除了包括业务容器,还包括 Sidecar 容器,这个注入过程对用户透明。
其他组件
除了以“istio”为前缀的 Istio 自有组件,在集群中一般还安装 Jaeger-agent、Jaeger-collector、Jaeger-query、Kiali、Prometheus、Grafana、 Tracing、Zipkin 等组件,这些组件提供了 Istio 的调用链、监控等功能,可以选择安装来完成完整的服务监控管理功能。
实战k8s安装istio
准备安装 Istio 是要的压缩包。
- 官网下载地址:https://github.com/istio/istio/
把压缩包上传到 k8s的控制节点手动解压:
[root@k8smaster ~]# tar zxvf istio-1.10.1-linux-amd64.tar.gz
切换到 istio 包所在目录下。samples/目录下,有示例应用程序,bin/目录下,包含 istioctl 的客户端文件。istioctl 工具用于手动注入 Envoy sidecar 代理。
[root@k8smaster ~]# cd istio-1.10.1
[root@k8smaster istio-1.10.1]# ls
bin LICENSE manifests manifest.yaml README.md samples tools
将 istioctl 客户端路径增加到 path 环境变量中,macOS或 Linux 系统的增加方式如下:
[root@k8smaster istio-1.10.1]# export PATH=$PWD/bin:$PATH
把 istioctl 这个可执行文件拷贝到/usr/bin/目录。
[root@k8smaster istio-1.10.1]# cd /root/istio-1.10.1/bin/
[root@k8smaster bin]# cp -ar istioctl /usr/bin/
安装 istio 需要的镜像默认从官网拉取,但是官网的镜像我们拉取会有问题,可以联系我微信下载镜像,然后上传到自己 k8s 集群的各个节点,通过 docker load -i 手动解压镜像。
[root@k8snode1 ~]# mkdir istio [root@k8snode1 ~]# mkdir bookinfo [root@k8snode1 ~]# cd bookinfo/
上传六个bookinfo到这个目录。
[root@k8snode1 bookinfo]# docker load -i examples-bookinfo-details.tar.gz
[root@k8snode1 bookinfo]# docker load -i examples-bookinfo-reviews-v1.tar.gz
[root@k8snode1 bookinfo]# docker load -i examples-bookinfo-productpage.tar.gz
[root@k8snode1 bookinfo]# docker load -i examples-bookinfo-reviews-v2.tar.gz
[root@k8snode1 bookinfo]# docker load -i examples-bookinfo-ratings.tar.gz
[root@k8snode1 bookinfo]# docker load -i examples-bookinfo-reviews-v3.tar.gz
[root@k8snode1 bookinfo]# cd
[root@k8snode1 ~]# cd istio/
[root@k8snode1 istio]# docker load -i istio-1-10-1.tar.gz
[root@k8snode1 istio]# docker load -i engress-proxyv2-1-10-1.tar.gz
[root@k8snode1 istio]# docker load -i httpbin.tar.gz
安装,在 k8s 的控制节点操作
[root@k8smaster istio-1.10.1]# istioctl install --set profile=demo -y
看到如下,说明 istio 初始化完成:
- ✔ Istio core installed
- ✔ Istiod installed
- ✔ Egress gateways installed
- ✔ Ingress gateways installed
- ✔ Installation complete
卸载 istio 集群,暂时不执行,记住这个命令即可。
istioctl manifest generate --set profile=demo | kubectl delete -f -
通过 Istio 实现灰度发布
什么是灰度发布?
灰度发布也叫金丝雀发布 ,是指通过控制流量的比例,实现新老版本的逐步更替。
比如对于服务 A 有 version1、 version2 两个版本 , 当前两个版本同时部署,但是 version1 比例 90% ,version2 比例 10% ,看运行效果,如果效果好逐步调整流量占比 80~20 ,70~30 ·····10~90 ,0,100 ,最终 version1 版本下线。
灰度发布的特点:
- 1)新老板共存
- 2)可以实时根据反馈动态调整占比
- 3)理论上不存在服务完全宕机的情况。
- 4)适合于服务的平滑升级与动态更新。
使用 istio 进行灰度发布
[root@k8snode1 ~]# docker load -i canary-v2.tar.gz
[root@k8snode1 ~]# docker load -i canary-v1.tar.gz
[root@k8smaster ~]# mkdir istio-canary
[root@k8smaster ~]# cd istio-canary/
[root@k8smaster istio-canary]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
labels:
app: v1
spec:
replicas: 1
selector:
matchLabels:
app: v1
apply: canary
template:
metadata:
labels:
app: v1
apply: canary
spec:
containers:
- name: nginx
image: xianchao/canary:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv2
labels:
app: v2
spec:
replicas: 1
selector:
matchLabels:
app: v2
apply: canary
template:
metadata:
labels:
app: v2
apply: canary
spec:
containers:
- name: nginx
image: xianchao/canary:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
[root@k8smaster istio-canary]# kubectl apply -f deployment.yaml
[root@k8smaster istio-canary]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
appv1 1/1 1 1 2m4s
appv2 1/1 1 1 2m4s
创建 service
[root@k8smaster istio-canary]# vim service.yaml
apiVersion: v1
kind: Service
metadata:
name: canary
labels:
apply: canary
spec:
selector:
apply: canary
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@k8smaster istio-canary]# kubectl apply -f service.yaml
[root@k8smaster istio-canary]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
canary ClusterIP 10.104.100.198 <none> 80/TCP 16s
创建 gateway
[root@k8smaster istio-canary]# vim gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: canary-gateway
spec:
selector:
istio: ingressgateway
servers:
port:
number: 80
name: http
protocol: HTTP
hosts:"*"
[root@k8smaster istio-canary]# kubectl apply -f gateway.yaml
[root@k8smaster istio-canary]# kubectl get gateway
NAME AGE
canary-gateway 15s
创建 virtualservice(虚拟服务)
[root@k8smaster istio-canary]# vim virtual.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: canary
spec:
hosts:
"*"
gateways:
canary-gateway
http:
route:
- destination:
host: canary.default.svc.cluster.local
subset: v1 #v1的全局量域名权重90
weight: 90
- destination:
host: canary.default.svc.cluster.local
subset: v2 #v2的全局量域名权重10
weight: 10
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule #目标规则
metadata:
name: canary
spec:
host: canary.default.svc.cluster.local #全局量域名
subsets:
- name: v1
labels:
app: v1 name: v2
labels:
app: v2
[root@k8smaster istio-canary]# kubectl apply -f virtual.yaml
[root@k8smaster istio-canary]# kubectl get virtualservice
NAME GATEWAYS HOSTS AGE
canary ["canary-gateway"] ["*"] 2m22s
[root@k8smaster istio-canary]# kubectl get DestinationRule
NAME HOST AGE
canary canary.default.svc.cluster.local 2m54s
[root@k8smaster istio-canary]# vim /etc/hosts
192.168.11.129 productpage.paopao.cn
#添加一个域名解析,下面验证的时候域名也可以
验证金丝雀发布效果:
[root@k8smaster istio-canary]# for i in seq 1 100
; do curl productpage.paopao.cn;done > 1.txt
或者
[root@k8smaster istio-canary]# for i in seq 1 100
; do curl 192.168.40.180:30871;done > 1.txt #请求100次
打开 1.txt 可以看到结果有 90 次出现 v1,10 次出现 canary-v2,符合我们预先设计的流量走向。
参考链接:https://blog.csdn.net/qq_4540 0861/category_12056337.html