Service Mesh

Service Mesh 的中文译为“服务网格”,是一个用于处理服务和服务之间通信的基础设施层,它负责为构建复杂的云原生应用传递可靠的网络请求,并为服务通信实现了微服务所需的基本组件功能,例如服务发现、负载均衡、监控、流量管理、访问控制等。在实践中,服务网格通常实现为一组和应用程序部署在一起的轻量级的网络代理,但对应用程序来说是透明的。
image.png
Service Mesh 部署网络结构图
Service Mesh有四大特点:

  • 治理能力独立(Sidecar)
  • 应用程序无感知
  • 服务通信的基础设施层
  • 解耦应用程序的重试/超时、监控、追踪和服务发现

image.png
如此一来,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
image.png
主要有以下特点

  • 连接(Connect)

    • 流量管理
      - 负载均衡
      - 灰度发布
  • 安全(Secure)

    • 认证
      - 鉴权
  • 控制(Control)

    • 限流
      - ACL
  • 观察(Observe)

    • 监控
      - 调用链
      主要应用于服务治理:
      image.png

      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 的延迟
image.png

注:此页中图片和数据引用自Istio官网

3 在 Kubernetes 部署 Istio

可参考官方文档,以部署1.6版本作为演示,部署的demo模式,所有组件都安装

  1. # wget https://github.com/istio/istio/releases/download/1.6.2/istio-1.6.2-linux-amd64.tar.gz
  2. # tar -zxvf istio-1.6.2-linux-amd64.tar.gz -C /data/
  3. # cd /data/istio-1.6.2/
  4. # mv bin/istioctl /usr/bin
  5. # istioctl profile list
  6. Istio configuration profiles:
  7. default
  8. demo
  9. empty
  10. minimal
  11. preview
  12. remote
  13. # istioctl install --set profile=demo
  14. # kubectl get pods -n istio-system
  15. NAME READY STATUS RESTARTS AGE
  16. grafana-75745787f9-jb79g 1/1 Running 0 2d8h
  17. istio-egressgateway-78b89c9f79-f7g58 1/1 Running 0 2d2h
  18. istio-ingressgateway-845967d5c6-4r7dm 1/1 Running 0 2d2h
  19. istio-tracing-7fc897dbb8-gsgfq 1/1 Running 0 2d2h
  20. istiod-b56f454c6-9rd5f 1/1 Running 0 55m
  21. kiali-5645f98f9-5jkjf 1/1 Running 0 2d1h
  22. prometheus-7778b9d84-ncb5r 2/2 Running 0 2d2h
  23. # kubectl get svc -n istio-system
  24. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  25. istio-egressgateway ClusterIP 10.104.251.176 <none> 80/TCP,443/TCP,15443/TCP 71d
  26. 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
  27. istio-pilot ClusterIP 10.111.202.110 <none> 15010/TCP,15011/TCP,15012/TCP,8080/TCP,15014/TCP,443/TCP 71d
  28. istiod ClusterIP 10.96.68.5 <none> 15012/TCP,443/TCP 71d
  29. jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 71d
  30. jaeger-collector ClusterIP 10.106.32.219 <none> 14267/TCP,14268/TCP,14250/TCP 71d
  31. jaeger-collector-headless ClusterIP None <none> 14250/TCP 71d
  32. jaeger-query ClusterIP 10.96.35.176 <none> 16686/TCP 71d
  33. kiali ClusterIP 10.101.196.222 <none> 20001/TCP 71d
  34. prometheus ClusterIP 10.98.252.96 <none> 9090/TCP 71d
  35. tracing ClusterIP 10.101.199.222 <none> 80/TCP 71d
  36. zipkin ClusterIP 10.110.255.236 <none> 9411/TCP 71d

卸载:

  1. istioctl manifest generate --set profile=demo | kubectl delete -f -

4 应用演示(以bookinfo项目为例)

4.1 Sidercar 注入

  1. # 手动注入
  2. kubectl apply -f <(istioctl kube-inject -f xxx.yaml)
  3. 或者
  4. istioctl kube-inject -f xxx.yaml|kubectl apply -f -
  5. # 自动注入
  6. kubectl label namespace xxx istio-injection=enabled
  7. #项目空间中所有应用进行重启
  8. #需要注意,有状态部署的应用需要手动注入,比如Apollo配置中心的server端

4.2 服务网关:Gateway

这里需要使用istio自带的ingressgateway来进行流量管理,因此需要把对应业务的流量从这里面写入,没有使用k8s自带的ingress,使用istio自带的ingress当作服务的边界,便于流量管理
image.png
Gateway为网格内服务提供负载均衡器,提供以下功能:
•L4-L6的负载均衡
•对外的mTLS
Gateway根据流入流出方向分为:
•IngressGateway:接收外部访问,并将流量转发到网格内的服务。
•EgressGateway:网格内服务访问外部应用。
示例:

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个红色五角星 来显示评

分信息。
一图胜千言,整体架构如下
image.png

4.3.2 部署Bookinfo到Istio

将Bookinfo部署到k8s默认命名空间,即default。

启动边车自动注入

  1. kubectl label namespace default istio-injection=enabled

部署到k8s

  1. # 进入istio的工作目录
  2. [root@master01 ~]# cd /data/istio-1.6.2/
  3. # 使用kubectl部署到k8s
  4. [root@master01 istio-1.6.2]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
  5. service/details created
  6. serviceaccount/bookinfo-details created
  7. deployment.apps/details-v1 created
  8. service/ratings created
  9. serviceaccount/bookinfo-ratings created
  10. deployment.apps/ratings-v1 created
  11. service/reviews created
  12. serviceaccount/bookinfo-reviews created
  13. deployment.apps/reviews-v1 created
  14. deployment.apps/reviews-v2 created
  15. deployment.apps/reviews-v3 created
  16. service/productpage created
  17. serviceaccount/bookinfo-productpage created
  18. deployment.apps/productpage-v1 created

获取访问地址

  1. # 为Bookinfo部署入口网关
  2. [root@master01 istio-1.6.2]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  3. gateway.networking.istio.io/bookinfo-gateway created
  4. virtualservice.networking.istio.io/bookinfo created
  5. # 获取网关地址
  6. [root@master01 istio-1.6.2]# export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
  7. [root@master01 istio-1.6.2]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
  8. [root@master01 istio-1.6.2]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
  9. # 获取图书单品页地址
  10. echo http://${GATEWAY_URL}/productpage

备注:生产环境一般使用istio-ingressgateway作为联网的唯一出入口。

访问

17.1、微服务治理 Istio 1.6部署和应用 - 图9

5、可视化监控

istio自带了三个监控平台
•监控指标(Grafana)
1、请求错误率
2、请求延时(响应时间)
•网格可视化(Kiali)
3、链路跳用拓扑图
4、RPS(每秒请求),也有请求错误率
5、请求/响应数据包大小
6、查看pod日志
7、istio配置资源在线编辑
•调用链跟踪(Jaeger)
8、一个服务涉及的调用情况
9、分析数据包中具体请求/响应信息
10、响应时间

  1. [root@master01 opt]# istioctl dashboard -h
  2. Access to Istio web UIs
  3. Usage:
  4. istioctl dashboard [flags]
  5. istioctl dashboard [command]
  6. Aliases:
  7. dashboard, dash, d
  8. Available Commands:
  9. controlz Open ControlZ web UI
  10. envoy Open Envoy admin web UI
  11. grafana Open Grafana web UI
  12. jaeger Open Jaeger web UI
  13. kiali Open Kiali web UI
  14. prometheus Open Prometheus web UI
  15. zipkin Open Zipkin web UI
  16. Flags:
  17. --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")
  18. -h, --help help for dashboard
  19. -p, --port int Local port to listen to
  20. Global Flags:
  21. --context string The name of the kubeconfig context to use
  22. -i, --istioNamespace string Istio system namespace (default "istio-system")
  23. -c, --kubeconfig string Kubernetes configuration file
  24. -n, --namespace string Config namespace
  25. Use "istioctl dashboard [command] --help" for more information about a command.
  26. [root@master01 opt]# kubectl get pod -n istio-system
  27. NAME READY STATUS RESTARTS AGE
  28. grafana-75745787f9-w8md6 1/1 Running 0 25m
  29. istio-egressgateway-794db4db55-hstw6 1/1 Running 0 25m
  30. istio-ingressgateway-799b86d9-x2gkh 1/1 Running 0 25m
  31. istio-tracing-c7b59f68f-fp66x 1/1 Running 0 25m
  32. istiod-55fff4d845-zmdg8 1/1 Running 0 25m
  33. kiali-85dc7cdc48-vmh29 1/1 Running 0 25m
  34. prometheus-8685fb8c59-65qxl 2/2 Running 0 25m
  35. ##临时开启可用如下办法
  36. [root@master01 opt]# istioctl dashboard controlz istiod-55fff4d845-zmdg8 -n istio-system --address=10.211.55.16
  37. http://localhost:33673

为了可以通过ingressgateway的能够访问三个监控平台,因此需要编写监控monitor-gateway.yaml

  1. [root@master01 istio-1.6.2]# kubectl get svc -n istio-system
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. grafana ClusterIP 10.68.185.28 <none> 3000/TCP 26h
  4. istio-egressgateway ClusterIP 10.68.80.126 <none> 80/TCP,443/TCP,15443/TCP 26h
  5. istio-ingressgateway LoadBalancer 10.68.139.54 <pending> 15021:30792/TCP,80:22516/TCP,443:34994/TCP,31400:21999/TCP,15443:22618/TCP 26h
  6. istiod ClusterIP 10.68.213.107 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP,853/TCP 26h 26h
  7. kiali NodePort 10.68.227.1 <none> 20001:24347/TCP 26h
  8. prometheus ClusterIP 10.68.241.113 <none> 9090/TCP 26h 18m
  9. tracing ClusterIP 10.68.156.89 <none> 80/TCP 26h
  10. zipkin NodePort 10.68.182.176 <none> 9411:24218/TCP 26h
  1. [root@master01 istio-1.6.2]# cat monitor-gateway.yaml
  2. ---
  3. #网格可视化kiala
  4. apiVersion: networking.istio.io/v1alpha3
  5. kind: Gateway
  6. metadata:
  7. name: monitor-gateway
  8. namespace: istio-system
  9. spec:
  10. selector:
  11. istio: ingressgateway # use istio default controller
  12. servers:
  13. - port:
  14. number: 80
  15. name: http
  16. protocol: HTTP
  17. hosts:
  18. - "*"
  19. ---
  20. apiVersion: networking.istio.io/v1alpha3
  21. kind: VirtualService
  22. metadata:
  23. name: kiali
  24. namespace: istio-system
  25. spec:
  26. hosts:
  27. - "kiali.istio.double.com"
  28. gateways:
  29. - monitor-gateway
  30. http:
  31. - route:
  32. - destination:
  33. host: kiali
  34. port:
  35. number: 20001
  36. ---
  37. #监控可视化
  38. ---
  39. apiVersion: networking.istio.io/v1alpha3
  40. kind: VirtualService
  41. metadata:
  42. name: grafana
  43. namespace: istio-system
  44. spec:
  45. hosts:
  46. - "grafana.istio.double.com"
  47. gateways:
  48. - monitor-gateway
  49. http:
  50. - route:
  51. - destination:
  52. host: grafana
  53. port:
  54. number: 3000
  55. ---
  56. #调用链
  57. ---
  58. apiVersion: networking.istio.io/v1alpha3
  59. kind: VirtualService
  60. metadata:
  61. name: tracing
  62. namespace: istio-system
  63. spec:
  64. hosts:
  65. - "tracing.istio.double.com"
  66. gateways:
  67. - monitor-gateway
  68. http:
  69. - route:
  70. - destination:
  71. host: tracing
  72. port:
  73. number: 80
  74. ---
  75. #链路跟踪
  76. ---
  77. apiVersion: networking.istio.io/v1alpha3
  78. kind: VirtualService
  79. metadata:
  80. name: zipkin
  81. namespace: istio-system
  82. spec:
  83. hosts:
  84. - "zipkin.istio.double.com"
  85. gateways:
  86. - monitor-gateway
  87. http:
  88. - route:
  89. - destination:
  90. host: zipkin
  91. port:
  92. number: 8441

部署监控网关入口

  1. [root@master01 istio-1.6.2]# kubectl apply -f monitor-gateway.yaml
  2. [root@localhost istio-1.6.2]# kubectl get gateway,vs -n istio-system
  3. NAME AGE
  4. gateway.networking.istio.io/grafana-gateway 34s
  5. gateway.networking.istio.io/kiala-gateway 34s
  6. gateway.networking.istio.io/monitor-gateway 34s
  7. gateway.networking.istio.io/traing-gateway 34s
  8. NAME GATEWAYS HOSTS AGE
  9. virtualservice.networking.istio.io/grafana [grafana-gateway] [grafana.istio.double.com] 34s
  10. virtualservice.networking.istio.io/kiali [kiala-gateway] [kiali.istio.double.com] 34s
  11. virtualservice.networking.istio.io/tracing [tracing-gateway] [tracing.istio.double.com] 34s
  12. virtualservice.networking.istio.io/zipkin [monitor-gateway] [zipkin.istio.double.com] 34s

安装nginx,作为lb,负载均衡到ingressgateway的暴露的nodeport端口上,所有的外部流量通过ingressgateway进去istio进行管理

  1. [root@mysql-cloud-kafka-zk ~]# cat /data/nginx/vhosts/istio.holder.cn.conf
  2. ....省略
  3. include /etc/nginx/conf.d/*.conf;
  4. upstream ingressgateway {
  5. server k8s的节点ip+nodeportip;
  6. }
  7. server {
  8. listen 80 default_server;
  9. listen [::]:80 default_server;
  10. server_name _;
  11. root /usr/share/nginx/html;
  12. # Load configuration files for the default server block.
  13. include /etc/nginx/default.d/*.conf;
  14. location / {
  15. proxy_pass http://ingressgateway;
  16. proxy_set_header Host $host;
  17. proxy_http_version 1.1;
  18. }
  19. }

绑定域名到本地hosts,即可访问

6、切换bookinfo的入口流量到ingressgateway

  1. # 为Bookinfo部署入口网关
  2. [root@master01 istio-1.6.2]# cat samples/bookinfo/networking/bookinfo-gateway.yaml
  3. apiVersion: networking.istio.io/v1alpha3
  4. kind: Gateway
  5. metadata:
  6. name: bookinfo-gateway
  7. spec:
  8. selector:
  9. istio: ingressgateway # use istio default controller
  10. servers:
  11. - port:
  12. number: 80
  13. name: http
  14. protocol: HTTP
  15. hosts:
  16. - "*"
  17. ---
  18. apiVersion: networking.istio.io/v1alpha3
  19. kind: VirtualService
  20. metadata:
  21. name: bookinfo
  22. spec:
  23. hosts:
  24. - "bookinfo.istio.double.com"
  25. gateways:
  26. - bookinfo-gateway
  27. http:
  28. - match:
  29. - uri:
  30. exact: /productpage
  31. - uri:
  32. prefix: /static
  33. - uri:
  34. exact: /login
  35. - uri:
  36. exact: /logout
  37. - uri:
  38. prefix: /api/v1/products
  39. route:
  40. - destination:
  41. host: productpage
  42. port:
  43. number: 9080
  44. [root@master01 istio-1.6.2]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  45. gateway.networking.istio.io/bookinfo-gateway unchanged
  46. virtualservice.networking.istio.io/bookinfo changed
  47. # 获取网关地址
  48. [root@master01 istio-1.6.2]# kubectl get gateway,vs
  49. NAME AGE
  50. gateway.networking.istio.io/bookinfo-gateway 29h
  51. NAME GATEWAYS HOSTS AGE
  52. virtualservice.networking.istio.io/bookinfo [bookinfo-gateway] [bookinfo.istio.double.com] 29h

绑定域名,然后访问bookinfo.istio.double.com既可访问,不停地刷新图书单品页,在kiali中会实时地绘制服务网格,如下:
image.png
请求响应如下:
image.png
基于权重流量的实时控制,如下:
17.1、微服务治理 Istio 1.6部署和应用 - 图12
监控指标如下:
image.png
对于服务的可观察性,kiali还提供了很多其他的功能,这也是Istio相较于其他服务网格框架的优势,这里就不展示了。