Service Mesh 的中文译为“服务网格”,是一个用于处理服务和服务之间通信的基础设施层,它负责为构建复杂的云原生应用传递可靠的网络请求,并为服务通信实现了微服务所需的基本组件功能,例如服务发现、负载均衡、监控、流量管理、访问控制等。在实践中,服务网格通常实现为一组和应用程序部署在一起的轻量级的网络代理,但对应用程序来说是透明的。
Service Mesh 部署网络结构图 Service Mesh有四大特点:
- 治理能力独立(Sidecar)
- 应用程序无感知
- 服务通信的基础设施层
- 解耦应用程序的重试/超时、监控、追踪和服务发现
如此一来,Service Mesh将业务模块和服务治理分开。从上图中我们看到,控制面和数据面分离,应用在部署的时候,每个应用附带一个Side Car,这个Side Car是拦截每一个应用对外请求的。同时控制面的服务治理策略下到Side Car中具体的执行,这样的话,即使业务模块升级和服务治理的升级也能互不影响的,还能动态调整服务治理的规则和策略 从Service Mesh的结构和特点,我们可以总结出其对于服务治理的理念:
1、微服务治理与业务逻辑解耦:把大部分SDK能力从应用中剥离出来,并拆解为独立进程,以 sidecar 的模式进行部署。
2、异构系统的统一治理:方便多语言的实施,解锁升级带来的困难。
3、价值:(1)可观察性:服务网格捕获诸如来源、目的地、协议、URL、状态码、延迟、持续时间等线路数据;(2)流量控制:为服务提供智能路由、超时重试、熔断、故障注入、流量镜像等各种控制能力。(3)安全性高:服务的认证、服务间通讯的加密、安全相关策略的强制执行;(4)健壮性:支持故障注入,对于容灾和故障演练等健壮性检验帮助巨大。我们以Service Mesh的杰出代表Istio为例来聊聊最新的服务治理的架构,它对Service Mesh完全支持,架构清晰,拆分数据面、控制面;拥有通信、安全、控制、观察等功能,实现开放,且插件化,多种可选实现。Istio可结合K8S使用,K8S提供服务生命周期的管理,Istio在K8S之上通过服务治理的整体的功能的实现。?
1 Istio 概述
Isito是Service Mesh的产品化落地,是目前最受欢迎的服务网格,功能丰富、成熟度高。Linkerd是世界上第一个服务网格类的产品 官方地址:?https://istio.io
主要有以下特点
- 连接(Connect)
- 流量管理
- 负载均衡
- 灰度发布
- 安全(Secure)
- 认证
- 鉴权
- 控制(Control)
- 限流
- ACL
- 观察(Observe)
- 监控
- 调用链
主要应用于服务治理:
?
2 Isito 架构与组件
image.png
注:此页中图片引用自Istio官网
◆ 性能总结 Istio 负载测试网格包含了 1000 个服务和 2000 个 sidecar,全网 格范围内,QPS 为 70,000。在使用 Istio 1.6.2 运行测试后,我们 得到了如下结果:
• 通过代理的 QPS 有 1000 时,Envoy 使用了 0.5 vCPU 和 50 MB 内存。
• 网格总的 QPS 为 1000 时,istio-telemetry 服务使用了 0.6 vCPU。
• Pilot 使用了 1 vCPU 和 1.5 GB 内存。
• 90% 的情况 Envoy 代理只增加了 6.3 ms 的延迟
注:此页中图片和数据引用自Istio官网
?
3 在 Kubernetes 部署 Istio
可参考官方文档,以部署1.6版本作为演示,部署的demo模式,所有组件都安装
代码语言:javascript复制# wget https://github.com/istio/istio/releases/download/1.6.2/istio-1.6.2-linux-amd64.tar.gz
# tar -zxvf istio-1.6.2-linux-amd64.tar.gz -C /data/
# cd /data/istio-1.6.2/
# mv bin/istioctl /usr/bin
# istioctl profile list
Istio configuration profiles:
default
demo
empty
minimal
preview
remote
# istioctl install --set profile=demo
# kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-75745787f9-jb79g 1/1 Running 0 2d8h
istio-egressgateway-78b89c9f79-f7g58 1/1 Running 0 2d2h
istio-ingressgateway-845967d5c6-4r7dm 1/1 Running 0 2d2h
istio-tracing-7fc897dbb8-gsgfq 1/1 Running 0 2d2h
istiod-b56f454c6-9rd5f 1/1 Running 0 55m
kiali-5645f98f9-5jkjf 1/1 Running 0 2d1h
prometheus-7778b9d84-ncb5r 2/2 Running 0 2d2h
# kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-egressgateway ClusterIP 10.104.251.176 <none> 80/TCP,443/TCP,15443/TCP 71d
istio-ingressgateway NodePort 10.99.33.183 <none> 15020:41020/TCP,80:48035/TCP,443:41862/TCP,15029:44646/TCP,15030:35600/TCP,15031:49406/TCP,15032:41959/TCP,15443:49277/TCP 71d
istio-pilot ClusterIP 10.111.202.110 <none> 15010/TCP,15011/TCP,15012/TCP,8080/TCP,15014/TCP,443/TCP 71d
istiod ClusterIP 10.96.68.5 <none> 15012/TCP,443/TCP 71d
jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 71d
jaeger-collector ClusterIP 10.106.32.219 <none> 14267/TCP,14268/TCP,14250/TCP 71d
jaeger-collector-headless ClusterIP None <none> 14250/TCP 71d
jaeger-query ClusterIP 10.96.35.176 <none> 16686/TCP 71d
kiali ClusterIP 10.101.196.222 <none> 20001/TCP 71d
prometheus ClusterIP 10.98.252.96 <none> 9090/TCP 71d
tracing ClusterIP 10.101.199.222 <none> 80/TCP 71d
zipkin ClusterIP 10.110.255.236 <none> 9411/TCP 71d
卸载:
代码语言:javascript复制istioctl manifest generate --set profile=demo | kubectl delete -f -
?
4 应用演示(以bookinfo项目为例)
?
4.1 Sidercar 注入
代码语言:javascript复制# 手动注入
kubectl apply -f <(istioctl kube-inject -f xxx.yaml)
或者
istioctl kube-inject -f xxx.yaml|kubectl apply -f -
# 自动注入
kubectl label namespace xxx istio-injection=enabled
#项目空间中所有应用进行重启
#需要注意,有状态部署的应用需要手动注入,比如Apollo配置中心的server端
?
4.2 服务网关:Gateway
这里需要使用istio自带的ingressgateway来进行流量管理,因此需要把对应业务的流量从这里面写入,没有使用k8s自带的ingress,使用istio自带的ingress当作服务的边界,便于流量管理
Gateway为网格内服务提供负载均衡器,提供以下功能:
•L4-L6的负载均衡
•对外的mTLS
Gateway根据流入流出方向分为:
•IngressGateway:接收外部访问,并将流量转发到网格内的服务。
•EgressGateway:网格内服务访问外部应用。示例:
代码语言:javascript复制apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- route:
- destination:
host: httpbin
port:
number: 8000
?
4.3 部署 bookinfo 微服务示例
本节将部署一个多语言异构化的微服务示例(Bookinfo),让大家对服务网格有一个清晰的认识。?
4.3.1 Bookinfo - 在线图书商店
Bookinfo 应用分为四个单独的微服务:
• productpage :productpage 微服务会调用 details 和reviews两个微服务,用来生成页面。
• details :这个微服务包含了书籍的信息。
• reviews :这个微服务包含了书籍相关的评论。它还会调用ratings微服务。
• ratings :ratings微服务中包含了由书籍评价组成的评级信息。
reviews 微服务有 3 个版本:
• v1 版本不会调用 ratings 服务。
• v2 版本会调用ratings服务,并使用 5个黑色五角星来显示评分信息。
• v3 版本会调用ratings服务,并使用5个红色五角星 来显示评分信息。一图胜千言,整体架构如下:
?
4.3.2 部署Bookinfo到Istio
将Bookinfo部署到k8s默认命名空间,即default。?
启动边车自动注入
代码语言:javascript复制kubectl label namespace default istio-injection=enabled
?
部署到k8s
代码语言:javascript复制# 进入istio的工作目录
[root@master01 ~]# cd /data/istio-1.6.2/
# 使用kubectl部署到k8s
[root@master01 istio-1.6.2]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
?
获取访问地址
代码语言:javascript复制# 为Bookinfo部署入口网关
[root@master01 istio-1.6.2]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
# 获取网关地址
[root@master01 istio-1.6.2]# export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
[root@master01 istio-1.6.2]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
[root@master01 istio-1.6.2]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
# 获取图书单品页地址
echo http://${GATEWAY_URL}/productpage
备注:生产环境一般使用
istio-ingressgateway
作为联网的唯一出入口。
?
访问
?
5、可视化监控
istio自带了三个监控平台 •监控指标(Grafana) 1、请求错误率 2、请求延时(响应时间) •网格可视化(Kiali) 3、链路调用拓扑图 4、RPS(每秒请求),也有请求错误率 5、请求/响应数据包大小 6、查看pod日志 7、istio配置资源在线编辑 •调用链跟踪(Jaeger) 8、一个服务涉及的调用情况 9、分析数据包中具体请求/响应信息 10、响应时间
代码语言:javascript复制[root@master01 opt]# istioctl dashboard -h
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
Flags:
--address string Address to listen on. Only accepts IP address or localhost as a value. When localhost is supplied, istioctl will try to bind on both 127.0.0.1 and ::1 and will fail if neither of these address are available to bind. (default "localhost")
-h, --help help for dashboard
-p, --port int Local port to listen to
Global Flags:
--context string The name of the kubeconfig context to use
-i, --istioNamespace string Istio system namespace (default "istio-system")
-c, --kubeconfig string Kubernetes configuration file
-n, --namespace string Config namespace
Use "istioctl dashboard [command] --help" for more information about a command.
[root@master01 opt]# kubectl get pod -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-75745787f9-w8md6 1/1 Running 0 25m
istio-egressgateway-794db4db55-hstw6 1/1 Running 0 25m
istio-ingressgateway-799b86d9-x2gkh 1/1 Running 0 25m
istio-tracing-c7b59f68f-fp66x 1/1 Running 0 25m
istiod-55fff4d845-zmdg8 1/1 Running 0 25m
kiali-85dc7cdc48-vmh29 1/1 Running 0 25m
prometheus-8685fb8c59-65qxl 2/2 Running 0 25m
##临时开启可用如下办法
[root@master01 opt]# istioctl dashboard controlz istiod-55fff4d845-zmdg8 -n istio-system --address=10.211.55.16
http://localhost:33673
?
为了可以通过ingressgateway的能够访问三个监控平台,因此需要编写监控monitor-gateway.yaml
代码语言:javascript复制[root@master01 istio-1.6.2]# kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana ClusterIP 10.68.185.28 <none> 3000/TCP 26h
istio-egressgateway ClusterIP 10.68.80.126 <none> 80/TCP,443/TCP,15443/TCP 26h
istio-ingressgateway LoadBalancer 10.68.139.54 <pending> 15021:30792/TCP,80:22516/TCP,443:34994/TCP,31400:21999/TCP,15443:22618/TCP 26h
istiod ClusterIP 10.68.213.107 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP,853/TCP 26h 26h
kiali NodePort 10.68.227.1 <none> 20001:24347/TCP 26h
prometheus ClusterIP 10.68.241.113 <none> 9090/TCP 26h 18m
tracing ClusterIP 10.68.156.89 <none> 80/TCP 26h
zipkin NodePort 10.68.182.176 <none> 9411:24218/TCP 26h
代码语言:javascript复制[root@master01 istio-1.6.2]# cat monitor-gateway.yaml
---
#网格可视化kiala
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: monitor-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: kiali
namespace: istio-system
spec:
hosts:
- "kiali.istio.double.com"
gateways:
- kiala-gateway
http:
- route:
- destination:
host: kiali
port:
number: 20001
---
#监控可视化
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: grafana
namespace: istio-system
spec:
hosts:
- "grafana.istio.double.com"
gateways:
- grafana-gateway
http:
- route:
- destination:
host: grafana
port:
number: 3000
---
#调用链
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: tracing
namespace: istio-system
spec:
hosts:
- "tracing.istio.double.com"
gateways:
- tracing-gateway
http:
- route:
- destination:
host: tracing
port:
number: 80
---
#链路跟踪
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: zipkin
namespace: istio-system
spec:
hosts:
- "zipkin.istio.double.com"
gateways:
- monitor-gateway
http:
- route:
- destination:
host: zipkin
port:
number: 8441
?
部署监控网关入口
代码语言:javascript复制[root@master01 istio-1.6.2]# kubectl apply -f monitor-gateway.yaml
[root@localhost istio-1.6.2]# kubectl get gateway,vs -n istio-system
NAME AGE
gateway.networking.istio.io/grafana-gateway 34s
gateway.networking.istio.io/kiala-gateway 34s
gateway.networking.istio.io/monitor-gateway 34s
gateway.networking.istio.io/traing-gateway 34s
NAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/grafana [grafana-gateway] [grafana.istio.double.com] 34s
virtualservice.networking.istio.io/kiali [kiala-gateway] [kiali.istio.double.com] 34s
virtualservice.networking.istio.io/tracing [tracing-gateway] [tracing.istio.double.com] 34s
virtualservice.networking.istio.io/zipkin [monitor-gateway] [zipkin.istio.double.com] 34s
?
安装nginx,作为lb,负载均衡到ingressgateway的暴露的nodeport端口上,所有的外部流量通过ingressgateway进去istio进行管理
代码语言:javascript复制[root@mysql-cloud-kafka-zk ~]# cat /data/nginx/vhosts/istio.holder.cn.conf
....省略
include /etc/nginx/conf.d/*.conf;
upstream ingressgateway {
server 10.100.132.8:22516;
server 10.100.132.5:22516;
server 10.100.132.6:22516;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://ingressgateway;
proxy_set_header Host $host;
proxy_http_version 1.1;
}
}
绑定域名到本地hosts,即可访问?
6、切换bookinfo的入口流量到ingressgateway
代码语言:javascript复制# 为Bookinfo部署入口网关
[root@master01 istio-1.6.2]# cat samples/bookinfo/networking/bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "bookinfo.istio.double.com"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
[root@master01 istio-1.6.2]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway unchanged
virtualservice.networking.istio.io/bookinfo changed
# 获取网关地址
[root@master01 istio-1.6.2]# kubectl get gateway,vs
NAME AGE
gateway.networking.istio.io/bookinfo-gateway 29h
NAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/bookinfo [bookinfo-gateway] [bookinfo.istio.double.com] 29h
绑定域名,然后访问bookinfo.istio.double.com既可访问,不停地刷新图书单品页,在kiali中会实时地绘制服务网格,如下:
请求响应如下:
基于权重流量的实时控制,如下:
监控指标如下:
对于服务的可观察性,kiali还提供了很多其他的功能,这也是Istio相较于其他服务网格框架的优势,这里就不展示了。