vieyahn2017 / repos

【已经迁移到goto/javaway】
2 stars 1 forks source link

Istio是一个Service Mesh的开源框架,来自Google,是Service Mesh的集大成者。 #39

Closed vieyahn2017 closed 7 months ago

vieyahn2017 commented 4 years ago

https://github.com/istio/istio

vieyahn2017 commented 4 years ago

深度剖析Service Mesh服务网格新生代Istio https://blog.csdn.net/karamos/article/details/80131863

vieyahn2017 commented 4 years ago

在Kubernetes中安装部署Istio(1.0.5)

Istio在服务集群之间建立起了服务网格,从运维层面提供了负载均衡、流量管理、服务间认证、访问控制、指标监控等功能,不需要我们对服务代码进行任何改动。虽然Istio与平台无关,但是将其与Kubernetes结合使用,其优势会更大。参考Istio官方文档,在Kubernetes上安装部署好Istio之后,默认提供了分布式链路跟踪、指标监控可视化、服务依赖动态图展示等平台,功能非常强大,安装方法也很简单,只是安装过程中有一些需要注意的地方,这里做一个记录。安装过程基本参考自官方文档。

  1. 下载Istio发布包 直接运行如下命令下载最新发布包并自动解压,也可以到Istio Release选择指定版本手动下载。

    # curl -L https://git.io/getLatestIstio | sh -
    # cd istio-1.0.5
    # cp bin/istioctl /usr/local/bin/

    Istio包中install目录包含了在Kubernetes中安装所需的yaml文件,samples目录包含了官方文档中介绍的各种示例。

  2. 修改配置 这里不需要对服务间通信使用双向TLS认证,所以选择install/kubernetes/istio-demo.yaml配置文件进行安装,在安装之前还需要对这个文件进行部分修改,请自己对原文件做好备份。istio-demo.yaml文件里面提供了安装Istio需要创建的各种资源,所有资源默认创建在kubernetes的istio-system空间中,能够对建立在其他命名空间中的服务进行管理。

我们需要对istio-demo.yaml文件做如下修改:

如果没有外部LoadBalancer可用,需要将istio-ingressgateway Service的type改成NodePort。虽然这一步不修改也没有关系,但是创建之后这个Service会一直处于Pending状态。 放开外网访问限制。在Istio服务网格中默认会对所有网络请求进行拦截,不支持对外部服务的访问,我们需要配置放开外网访问限制,只拦截内部服务地址。Calico默认使用的服务地址范围为10.96.0.0/12,将其配置到istio-sidecar-injector ConfigMap中的includeOutboundIPRanges选项中,详细方法参考后面问题二。 将Jaeger-query, Prometheus, Grafana, ServiceGraph几个Service配置成NodePort,否则在外部环境中无法访问。另外最好把这几个Service的NodePort设置为固定值,避免与其他服务端口冲突,也更方便访问,不会经常变动。这里配置Jaeger-query使用32762端口,Grafana使用32760端口,Prometheus使用32761端口,ServiceGraph使用32763端口。

  1. 安装 然后运行如下命令创建资源,执行安装。
    # kubectl apply -f install/kubernetes/istio-demo.yaml

如果对配置文件进行了新的修改,重新执行该命令即可更新相关资源。这一步运行之后因为需要下载镜像,可能需要等待几分钟。安装成功之后,可以查看到如下Pods。

# kubectl get pods -n istio-system
NAME                                      READY   STATUS      RESTARTS   AGE
grafana-59b8896965-h24xf                  1/1     Running     0          19h
istio-citadel-856f994c58-jp64r            1/1     Running     0          19h
istio-cleanup-secrets-5dvtn               0/1     Completed   0          19h
istio-egressgateway-5649fcf57-cst7n       1/1     Running     0          19h
istio-galley-7665f65c9c-ttdsn             1/1     Running     0          19h
istio-grafana-post-install-gz64t          0/1     Completed   4          19h
istio-ingressgateway-6755b9bbf6-dw2zv     1/1     Running     0          19h
istio-pilot-698959c67b-qgcqb              2/2     Running     0          19h
istio-policy-6fcb6d655f-xqb8w             2/2     Running     0          19h
istio-security-post-install-mbzds         0/1     Completed   3          19h
istio-sidecar-injector-768c79f7bf-mdd6g   1/1     Running     0          19h
istio-telemetry-664d896cf5-7kcmw          2/2     Running     0          19h
istio-tracing-6b994895fd-8sq4k            1/1     Running     0          19h
prometheus-76b7745b64-t42p9               1/1     Running     0          19h
servicegraph-5c4485945b-fzs9q             1/1     Running     0          19h
  1. 开启sidecar自动注入 Kubernetes 1.9+支持Sidecar的自动注入,不过需要针对命名空间进行开启,默认为关闭状态。我们的服务部署在default空间下,需要对default开启自动注入。
    
    # kubectl get namespace -L istio-injection
    NAME           STATUS   AGE     ISTIO-INJECTION
    default        Active   3d21h
    istio-system   Active   3d19h   disabled
    kube-public    Active   3d21h
    kube-system    Active   3d21h

kubectl label namespace default istio-injection=enabled

namespace/default labeled

kubectl get namespace -L istio-injection

NAME STATUS AGE ISTIO-INJECTION default Active 3d21h enabled istio-system Active 3d19h disabled kube-public Active 3d21h kube-system Active 3d21h

自动注入开启之后对已经启动的Pods并不会起作用,需要将Pods重新创建一下。当自动注入生效之后会发现,在创建应用时每个Pod会包含2个容器,如下所示。
```sh
# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES
nginx-54458cd494-49dcl   2/2     Running   0          6s    192.168.0.40   szx1000317012   <none>           <none>

另外在Pod创建的时候会先启动一个istio-init容器,是用于进行初始化操作的,只有当所有init容器启动并执行完成之后才会启动应用容器,istio-init在执行完成之后就会自动Exited掉。

  1. Dashboard 到这一步Isito就已经基本安装完成了,Istio成功安装之后默认提供了很多非常有用的功能,例如用于调用链跟踪的Jaeger Dashboard,用于展示服务间动态依赖关系的ServiceGraph Dashboard,用于业务指标查询的Prometheus,以及用于业务指标可视化展示的Grafana。地址如下:

Dashboard 访问地址 监控平台Dashboard Grafana http://master-ip:32760 监控平台Prometheus http://master-ip:32761 分布式跟踪Dashboard Jaeger http://master-ip:32762/search 服务依赖关系Dashboard http://master-ip:32763/force/forcegraph.html 对于监控这一块,从Grafana中只能看到业务指标的监控数据,并没有节点和容器的资源使用情况监控。其实Prometheus中已经采集到了资源相关的监控数据,不过还需要我们在Grafana中配置相应的Dashboard进行数据展示。我们下载Kubernetes cluster**ing (via Prometheus) Dashboard的json配置文件,然后导入到Grafana中即可查看到资源使用监控数据。另外Istio并没有引入告警系统,需要我们另外引入。

Istio对服务提供了强大的流量管理能力,可以考虑如何在其之上实现满足于业务需求的灰度发布机制。另外,Istio也提供了一系列如熔断、超时、重试等服务治理机制,还有提供了故障注入能力,可用于实现灵活的测试方案。

  1. 问题 在安装的过程中可能会遇到很多问题,这里列了一下我在安装的时候遇到的问题和解决方法。

问题1:执行kubectl apply -f 命令时报"unable to recognize"错误 修改完配置之后执行kubectl apply -f istio-demo.yaml命令创建资源,但是报如下错误:

unable to recognize "istio-demo.yaml": no matches for kind "Gateway" in version "networking.istio.io/v1alpha3"
unable to recognize "istio-demo.yaml": no matches for kind "attributemanifest" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "attributemanifest" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "stdio" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "logentry" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "logentry" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "rule" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "rule" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "metric" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "metric" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "metric" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "metric" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "metric" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "metric" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "prometheus" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "rule" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "rule" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "kubernetesenv" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "rule" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "rule" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "kubernetes" in version "config.istio.io/v1alpha2"
unable to recognize "istio-demo.yaml": no matches for kind "DestinationRule" in version "networking.istio.io/v1alpha3"
unable to recognize "istio-demo.yaml": no matches for kind "DestinationRule" in version "networking.istio.io/v1alpha3"

解决方法: 该问题不是必现,有时候安装会出现,只需要重新执行一次该命令即可成功创建。

问题2:网格内不能访问外部系统 服务网格内默认是无法访问外部服务的,所有请求都会被sidecar拦截,但是通常系统不可避免地要对外部服务进行调用,此时我们可以通过下面两种方法达到该目的。

解决方法一:为外部调用定义一个ServiceEntry,声明好外部调用的地址和端口。但是该方法需要为每一个外部服务都创建一个ServiceEntry,比较麻烦。

解决方法二:为istio-sidecar-injector配置includeOutboundIPRanges,注明需要拦截的地址范围。因为我们使用的是cslico网络插件,这里配置内部服务地址范围为10.96.0.0/12。

修改istio-demo.yaml文件中的istio-sidecar-injector ConfigMap,内容如下:

......
        - "[[ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges`  "10.96.0.0/12"  ]]"
        - "-x"
        - "[[ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges`  ""  ]]"
        - "-b"
......

这里配置只拦截10.96.0.0/12网段的请求,另外也可以配置exclude地址。如果使用的是其他Network Plugin,在这里配置对应的服务地址即可。如果使用的是minikube,则配置10.0.0.1/24,如果使用的是rancher,则配置10.43.0.1/24。

问题3:分布式追踪Dashboard Jaeger里面找不到服务 当所有服务都重启并且都成功注入sidecar之后,在分布式追踪Dashboard Jaeger里面并没有发现服务。

解决方案: 这里一是需要服务有发出或者收到请求,才会有调用记录,二是在声明Service的时候需要给端口加上名字,这里不加name的话Jaeger是没有记录的。如下:

    ports:
    - protocol: TCP
      port: 80
      name: http

问题4:使用Nginx作为转发路由,请求报426 Upgrade Required错误 当服务启动之后,我运行一个Nginx作为网关进行路由转发,但是请求却报426 Upgrade Required错误,直接调用服务就可以成功调通。

解决方法:因为使用Nginx转发,默认是使用HTTP 1.0协议进行转发的,但是Istio貌似是不支持HTTP 1.0的,只支持HTTP 1.1/2。因此这里需要在Nginx转发的时候进行如下配置,使用HTTP 1.1协议进行转发。

    location / {
        proxy_pass http://service_endpotin;
        proxy_http_version 1.1;
    }
vieyahn2017 commented 4 years ago

istio路由分析

入口消息路由:nodeIP:31380 (kube-proxy) -> KUBE-SVC-xxxx (iptables规则) -> KUBE-SEP-xxxx (iptables规则) -> 172.16.0.38:80 (istio-ingressgateway pod里面的envoy) -> 172.16.0.30:9080 (productpage) 服务间路由:productpage -> envoy 15001 (iptables) -> reviews pod IP 9080 -> VXLAN (如果是跨节点了) -> reviews pod IP 9080 -> envoy 15001(被iptables转发一次)-> reviews (envoy再次转发给9080,reviews才真正收到这个消息) 31380是istio-ingressgateway的http协议的nodePort,9080是bookinfo所有服务统一使用的服务端口,15001是envoy的业务端口,15000是envoy的管理端口。

参照官网指导,安装istio-1.1.11: https://istio.io/docs/setup/kubernetes/install/kubernetes/

以及安装示例程序bookinfo:

https://istio.io/docs/examples/bookinfo/ 安装好之后,可以通过如下url访问bookinfo:

http://nodeIP:31380/productpage 我的环境有2个node节点,由于使用NodePort模式,随便哪个节点的IP,都可以访问。下面,从31380端口开始分析整个路由过程。

一、istio-ingressgateway入口的消息路由 二、服务间消息路由

vieyahn2017 commented 4 years ago

详解如何使用Istio监控基于容器的服务 https://www.cnblogs.com/davidwang456/articles/9311470.html