二十四 服务网格
(一) 为什么出现服务网格
1.应用架构演变历程
2.微服务带来的问题
3.云原生时代为何要抛弃SpringCloud
4.云原生服务网格应运而生
5.什么是Service Mesh
Service Mesh是专用的基础设施层,轻量级高性能网络代理。提供安全的、快速的、可靠地服务间通讯,与实际应用部署一起,但对应用透明。应用作为服务的发起方,只需要用最简单的方式将请求发送给本地的服务网格代理,然后网格代理会进行后续操作,如服务发现,负载均衡,最后将请求转发给目标服务。当有大量服务相互调用时,它们之间的服务调用关系就会形成网格。
服务网格呈现出一个完整的支撑态势,将所有的服务”架”在网格之上。
6.服务网格功能介绍
A:负载均衡
B:服务发现
C:熔断降级
D:动态路由
E:故障注入
F:错误重试
G:安全通信
H:语言无关
7.服务网格产品有哪些?
A:Linkerd
B:Envoy
C:Istio
D:Conduit
E:Kuma
(****二) 服务网格Istio基础
1.Istio架构解析
2.Istio控制平面和数据平面
3.东西流量管理-VirtualService
4.VirtualService配置解析
5.细粒度流控DestinationRule
6.DestinationRule配置解析
7.南北流向管理GateWay
8.Istio网关Gateway配置解析
(三) 服务网格Istio安装
1.Istio安装注意事项
https://istio.io/latest/docs/setup/install/
Install with Istioctl
Install with Helm
Istio Operator Install(推荐)
https://github.com/istio/istio/releases
2.Istio版本选择及Istio平台安装
Support status of Istio releases
https://istio.io/latest/docs/releases/supported-releases/
使用Operator部署Istio
下载istio官方的部署包网址:https://github.com/istio/istio/releases/tag/1.13.2
# wget https://github.com/istio/istio/releases/download/1.13.2/istio-1.13.2-linux-amd64.tar.gz
或者
# curl -L https://istio.io/downloadIstio | sh -
解压安装包并加入环境变量中
# tar xvf istio-1.13.2-linux-amd64.tar.gz
# cd istio-1.13.2
# mv istio-1.13.2/bin/istioctl /usr/local/bin
# istioctl version
安装Istio的Operator,使用istioctl一键部署:
# istioctl operator init
此命令运行 operator 在 istio-operator 命名空间中创建以下资源:
l operator 自定义资源定义(CRD)
l operator 控制器的 deployment 对象: deployment/istio-operator
l 一个用来访问 operator 指标的服务
l Istio operator 运行必须的 RBAC 规则
# kubectl create ns istio-system
# kubectl apply -f - <<EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
name: istio-controlplane
spec:
profile: default
EOF
profile预定义配置: https://istio.io/v1.13/zh/docs/setup/additional-setup/config-profiles/
profile自定义配置: https://istio.io/v1.13/zh/docs/reference/config/istio.operator.v1alpha1/
不同配置的区别
获取清单配置
# istioctl manifest generate > default.yaml
# istioctl manifest generate --set profile=demo > demo.yaml
只获取IstioOperator配置
# istioctl profile dump default > default.yaml
# istioctl profile dump demo > demo.yaml
总体来看主要是demo配置中多了egressgateway
- configMap-->istio
demo配置中多出如下内容:accessLogFile: /dev/stdout # 将日志输出到控制台,默认配置是禁用的。` - deployment-->istio-egressgateway
demo配置中多了istio-egressgateway组件 - hpa-->istiod、ingressgateway
default配置有两个hpa相关的配置.可以到istio-system命名空间下找到istio-ingressgateway、istiod
查看安装结果
# kubectl get pod -n istio-system
# kubectl get istiooperators -n istio-system istio-controlplane
配置自动注入
# kubectl label namespace default istio-injection=enabled
3.图形化界面Kiali和链路追踪Jeager安装
部署jaeger
# kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.13/samples/addons/jaeger.yaml
部署kiali
安装
# kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.13/samples/addons/kiali.yaml
由于部署顺序问题,可能会导致创建失败,再运行一次上面命令即可。
检查部署状态
# kubectl rollout status deployment/kiali -n istio-system
接入prometheus、grafana、jaeger
修改configmap
# kubectl edit -n istio-system cm kiali
内容如下:
external_services:
custom_dashboards:
enabled: true
prometheus:
url: http://prometheus-k8s.monitoring:9090
grafana:
enabled: true
in_cluster_url: "http://grafana.monitoring:3000"
url: "http://192.168.2.10:30462"
tracing:
enabled: true
in_cluster_url: "http://tracing.istio-system/jaeger"
url: "http://192.168.2.10:32344/jaeger"
重启pod
# kubectl rollout -n istio-system restart deployment kiali
grafana-istio仪表盘
Istio Control Plane Dashboard: 7645
Istio Mesh Dashboard: 7639
Istio Performance Dashboard: 12153
Istio Service Dashboard: 7636
Istio Wasa Extension Dashboard: 13277
Istio Workload Dashboard: 7630
4.Prometheus和Grafana安装
部署Prometheus
# kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.13/samples/addons/prometheus.yaml
部署Grafana
# kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.13/samples/addons/grafana.yaml
5.Bookinfo项目介绍
项目介绍
Bookinfo是Istio官方提供的一个微服务风格的书店应用,作为实验对象,用于演示Istio的各种特性。(显然,在做Istio实验前,还要自己先写一个微服务应用,学习路径就太不友好了。)
系统架构
Bookinfo包含4个独立的微服务:
Ratings (评分服务)
Details(详情服务)
Reviews (评论服务,依赖Ratings,同时提供评论和评分)
Productpage(产品页面,展示产品详情,评论和评分)
其中Reviews有3个版本:
v1只提供评论
v2同时提供评论和评分,评分以黑色星星展现
v3同时提供评论和评分,评分以红色星星展现
依赖关系如下图所示:
6.服务网格测试项目部署
安装步骤
istio的安装包自带了bookinfo的部署脚本,以下命令均在istio-1.13.0目录下执行。
创建bookinfo命名空间
# kubectl create ns bookinfo
对bookinfo namespace使用自动注入sidecar功能
# kubectl create ns bookinfo
# kubectl label namespace bookinfo istio-injection=enabled
部署Bookinfo
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
部署内容包括4个service,以及6个deployment(Reviews每个版本各有一个deployment)
检查service和pod状态,确认启动成功。
尝试在ratings pod中调用productpage,确认应用运行正常。
# kubectl exec -it \
$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') \
-c ratings \
-- curl productpage:9080/productpage | grep -o "<title>.*</title>"
预期输出为<title>Simple Bookstore App</title>
源码分析
对Bookinfo的源码分析,主要关注点在于,开发人员需要做什么特定的调整,才可以把应用部署到Istio,并自动获得Istio的各种特性。
部署脚本
部署脚本即samples/bookinfo/platform/kube/bookinfo.yaml,可以看到里面定义的均为标准Kubernetes Deployment和Service对象,并不需要为Istio做特殊定制(前提是为当前namespace启动了sidecar自动注入)。
服务间通讯
Bookinfo的服务间通过HTTP通讯。以Reviews调用Ratings为例,Reviews通过GET ratings(.default.svc.cluster.local):9080/ratings/{productId}访问Ratings,得到某个特定产品的评分。
其中domain部分通过环境变量SERVICE_DOMAIN传入(若为空,则认为与调用者在同一namespace下)。
这就是kubernetes服务发现的方式,在代码层面,并不需要为Istio做额外的事情。
Tracing
在4个微服务中能发现类似的代码:
从访问本服务的HTTP Request中获得以下header,如果需要调用其他服务,那么在请求中,也把这些header加上。
incomming_headers = [
'x-request-id',
'x-b3-traceid',
'x-b3-spanid',
'x-b3-parentspanid',
'x-b3-sampled',
'x-b3-flags',
'x-ot-span-context'
]
request = Net::HTTP::Get.new(uri.request_uri)
incomming_headers.each { |header, value| request[header] = value }
response = http.request(request)
这是为了对接OpenTracing,是属于需要特殊的部分(但这部分特定代码是为了使用OpenTracing,不管是否部署到Istio,如果服务需要通过OpenTracing监控,那么这部分代码就必须实现)。
结论,开发人员并不需要为对接Istio做特殊的定制开发,Istio确实做到了它的目标,提供强大的服务治理功能的同时,对应用开发人员透明。
7.Istio IngresssGateway发布服务原理
8.使用域名发布网格内服务
9.使用Kiali进行服务健康监测及流量监测
(四) 服务网格Istio流量管理实践
1.什么是灰度发布、金丝雀发布
当应用上线以后,运维面临的一大挑战是如何能够在不影响已上线业务的情况下进行升级。做过产品的同学都清楚,不管在发布前做过多么完备的自动化和人工测试,在发布后都会出现或多或少的故障。根据墨菲定律,可能会出错的版本发布一定会出错。
“ANYTHING THAN CAN GO WRONG WILL GO WRONG” –MURPHY’S LAW
因此我们不能寄希望于在线下测试时发现所有潜在故障。在无法百分百避免版本升级故障的情况下,需要通过一种方式进行可控的版本发布,把故障影响控制在可以接受的范围内,并可以快速回退。
可以通过灰度发布(又名金丝雀发布)来实现业务从老版本到新版本的平滑过渡,并避免升级过程中出现的问题对用户造成的影响。
“金丝雀发布”的来源于矿工们用金丝雀对矿井进行空气测试的做法。以前矿工挖煤的时候,矿工下矿井前会先把金丝雀放进去,或者挖煤的时候一直带着金丝雀。金丝雀对甲烷和一氧化碳浓度比较敏感,会先报警。所以大家都用“金丝雀”来搞最先的测试。
滚动发布 一刀切
灰度发布 10% 90%----->50% 50%----->90% 10% ----->100% 0%
灰度发布(金丝雀发布)的流程如下:
准备和生产环境隔离的“金丝雀”服务器。
将新版本的服务部署到“金丝雀”服务器上。
对“金丝雀”服务器上的服务进行自动化和人工测试。
测试通过后,将“金丝雀”服务器连接到生产环境,将少量生产流量导入到“金丝雀”服务器中。
如果在线测试出现问题,则通过把生产流量从“金丝雀”服务器中重新路由到老版本的服务的方式进行回退,修复问题后重新进行发布。
如果在线测试顺利,则逐渐把生产流量按一定策略逐渐导入到新版本服务器中。
待新版本服务稳定运行后,删除老版本服务。
2.Istio实现灰度发布流程
A:使用DR划分Subnet
B:使用VS将流量导向旧版本
C:部署新版本
D:使用VS切换流量
3.Istio灰度发布新旧版本上线实践
因为本试验并不需要安装全部3个版本的reviews服务,因此如果已经安装了该应用,先采用下面的命令卸载。
# samples/bookinfo/kube/cleanup.sh
部署V1版本的服务
首先只部署V1版本的Bookinfo应用程序。由于示例中的yaml文件中包含了3个版本的reviews服务,我们先将V2和V3版本的Deployment从yaml文件/samples/bookinfo/kube/bookinfo.yaml中删除。
从Bookinfo.yaml中删除这部分内容:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v2
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v2
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v2:0.2.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v3
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v3
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v3:0.2.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
部署V1版本的Bookinfo程序。
# kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/kube/bookinfo.yaml)
通过kubectl命令行确认pod部署,可以看到只有V1版本的服务。
# kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-3688945616-nhkqk 2/2 Running 0 2m
productpage-v1-2055622944-m3fql 2/2 Running 0 2m
ratings-v1-233971408-0f3s9 2/2 Running 0 2m
reviews-v1-1360980140-0zs9z 2/2 Running 0 2m
在浏览器中打开应用程序页面,地址为istio-ingress的External IP。由于V1版本的reviews服务并不会调用rating服务,因此可以看到Product 页面显示的是不带星级的评价信息。
http://10.12.25.116/productpage
此时系统中微服务的部署情况如下图所示(下面的示意图均忽略和本例关系不大的details和ratings服务):
部署V2版本的reviews服务
在部署V2版本的reviews服务前,需要先创建一条缺省路由规则route-rule-default-reviews.yaml,将所有生产流量都导向V1版本,避免对线上用户的影响。
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-default
spec:
destination:
name: reviews
precedence: 1
route:
- labels:
version: v1
启用该路由规则。
# istioctl create -f route-rule-default-reviews.yaml -n default
创建一个V2版本的部署文件bookinfo-reviews-v2.yaml,内容如下
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v2
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v2
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v2:0.2.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
部署V2版本的reviews服务。
# kubectl apply -f <(istioctl kube-inject -f bookinfo-reviews-v2.yaml)
此时系统中部署了V1和V2两个版本的reviews服务,但所有的业务流量都被规则reviews-default导向了V1,如下图所示:
将测试流量导入到V2版本的reviews服务
在进行模拟测试时,由于测试环境和生产环境的网络,服务器,操作系统等环境存在差异,很难完全模拟生产环境进行测试。为了减少环境因素的对测试结果的影响,我们希望能在生产环境中进行上线前的测试,但如果没有很好的隔离措施,可能会导致测试影响已上线的业务,对企业造成损失。
通过采用Istio的路由规则,可以在类生产环境中进行测试,又完全隔离了线上用户的生产流量和测试流量,最小化模拟测试对已上线业务的影响。如下图所示:
创建一条规则,将用户名为 test-user 的流量导入到V2
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-test-user
spec:
destination:
name: reviews
precedence: 2
match:
request:
headers:
cookie:
regex: "^(.*?;)?(user=test-user)(;.*)?$"
route:
- labels:
version: v2
注意:precedence属性用于设置规则的优先级,在同时存在多条规则的情况下,优先级高的规则将先执行。这条规则的precedence设置为2,以确保其在缺省规则之前运行,将test-user用户的请求导流到V2版本reviews服务中。
启用该规则。
# istioctl create -f route-rule-test-reviews-v2.yaml -n default
以test-user用户登录,可以看到V2版本带星级的评价页面。
注销test-user,只能看到V1版本不带星级的评价页面。如下图所示:
将部分生产流量导入到V2版本的reviews服务
在线上模拟测试完成后,如果系统测试情况良好,可以通过规则将一部分用户流量导入到V2版本的服务中,进行小规模的“金丝雀”测试。
修改规则route-rule-default-reviews.yaml,将50%的流量导入V2版本。
备注:本例只是描述原理,因此为简单起见,将50%流量导入V2版本,在实际操作中,更可能是先导入较少流量,然后根据监控的新版本运行情况将流量逐渐导入,如采用5%,10%,20%,50% …的比例逐渐导入。
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-default
spec:
destination:
name: reviews
precedence: 1
route:
- labels:
version: v1
weight: 50
- labels:
version: v2
weight: 50
# istioctl replace -f route-rule-default-reviews.yaml -n default
此时系统部署如下图所示:
将所有生产流量导入到到V2版本的reviews服务
如果新版本的服务运行正常,则可以将所有流量导入到V2版本。
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-default
spec:
destination:
name: reviews
precedence: 1
route:
- labels:
version: v2
weight: 100
# istioctl replace -f route-rule-default-reviews.yaml -n default
系统部署如下图所示:
此时不管以任何用户登录,都只能看到V2版本带星级的评价页面,如下图所示:
备注:如果灰度发布的过程中新版本的服务出现问题,则可以通过修改路由规则,将流量重新导入到V1版本的服务中,将V2版本故障修复后再进行测试。
删除V1版本的reviews服务
待V2版本上线稳定运行后,删除V1版本的reviews服务和测试规则。
# kubectl delete pod reviews-v1-1360980140-0zs9z
# istioctl delete -f route-rule-test-reviews-v2.yaml -n default
4.图形化管理灰度流量
5.什么是AB测试
6.AB测试实践—vs配置
https://istio.io/latest/docs/reference/config/networking/virtual-service/#VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- match:
- headers: #匹配请求头
end-user: #匹配请求头的key为end-user
exact: Jason #value为json
uri:
prefix: "/ratings/v2/"
ignoreUriCase: true
route:
- destination:
host: ratings.prod.svc.cluster.local
7.AB测试实践—基于请求头的流量分发
https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- headers:
request:
set:
test: "true"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
weight: 25
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
headers:
response:
remove:
- foo
weight: 75
8.新旧地址替换—Redirect实践
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRedirect
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- match:
- uri:
exact: /v1/getProductRatings
redirect:
uri: /v1/bookRatings
authority: newratings.default.svc.cluster.local
...
9.前后端分离—Rewrite实践
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRewrite
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- match:
- uri:
prefix: /ratings
rewrite:
uri: /v1/bookRatings
route:
- destination:
host: ratings.prod.svc.cluster.local
subset: v1
10.负载均衡策略调整
负载均衡算法(load balancing algorithm),定义了几种基本的流量分发方式,在Istio中共有4种标准负载均衡算法。
•Round_Robin: 轮询算法,顾名思义请求将会依次发给每一个实例,来共同分担所有的请求。
•Random: 随机算法,将所有的请求随机分发给健康的实例
•Least_Conn: 最小连接数,在所有健康的实例中任选两个,将请求发给连接数较小的那一个实例。
•Passthrough: 将连接转发到调用者请求的原始IP地址,而不进行任何形式的负载平衡,目前不推荐使用
https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bookinfo-ratings
spec:
host: ratings.prod.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
11.并发数链接限制
https://istio.io/latest/docs/reference/config/networking/destination-rule/#ConnectionPoolSettings
部署压测工具:fortio,用于对容器业务进行压力测试
# kubectl -n bookinfo apply -f samples/httpbin/sample-client/fortio-deploy.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bookinfo-redis
spec:
host: myredissrv.prod.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 30ms
tcpKeepalive:
time: 7200s
interval: 75s
12.服务保护熔断降级实践
https://istio.io/latest/docs/reference/config/networking/destination-rule/#OutlierDetection
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-cb-policy
spec:
host: reviews.prod.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http2MaxRequests: 1000
maxRequestsPerConnection: 10
outlierDetection:
consecutive5xxErrors: 7
interval: 5m
baseEjectionTime: 15m
13.为什么需要故障注入及延迟故障实践
部署故障测试工具debug-tools
# kuberctl run -ti -n bookinfo debug-tools –image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPFaultInjection-Delay
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- match:
- sourceLabels:
env: prod
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
fault:
delay:
percentage:
value: 0.1
fixedDelay: 5s
14.故障注入实践—abort中断
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPFaultInjection-Abort
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- route:
- destination:
host: ratings.prod.svc.cluster.local
subset: v1
fault:
abort:
percentage:
value: 0.1
httpStatus: 400