微服务治理 Istio 1.6部署和应用

2020-11-03 14:38:55 浏览数 (1)

Service Mesh

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相较于其他服务网格框架的优势,这里就不展示了。

0 人点赞