基于Consul服务发现的istio

由于业务微服务先前的架构大量使用consul来做服务注册与发现,但是istio主流的方案中,业务还是走k8s基于DNS的服务发现。正好看到istio社区也号称能够基于consul;因此,基于consul做了一些POC,主要情况简单介绍一下。

现状与需求

当前业务方新开发的服务运行到k8s上,另外有一些旧服务运行在VM中(VM网络与办公网络三层可达,存在接口被人随意调用的风险)。希望能够降低服务部署的复杂度,同时当存在异常或瓶颈的时候能够快速感知到异常,定位问题。

因此,其服务治理的目标也比较明确:

  1. 网络安全,不允许接口被随意调用;
  2. VM+k8s容器通过一套平台,集中治理;
  3. 流量管控,需要做服务的蓝绿部署和灰度发布;
  4. 可视化,监控。

大体分析一下:

  • 从功能方面来看

    基于istio的宣传,乍一看,以上功能都能够cover住。但是这里面仍存在风险点,比如VM+K8S融合部署、集中管控;基于consul的服务注册等。虽然社区号称istio具备这些能力,但是却未在这些点上深度发力(从发布包中可以看到主流方向还是基于纯k8s方向)。

  • 从服务注册方面来看

    假设使用consul作为服务发现工具,那么就相当于将vm和k8s pod都拉平来对待,似乎是一个方向。另一方面,现有服务已经在使用spring cloud + consul注册的机制,如果继续使用consul的话,现有代码不需要再做修改。

    另外,社区号称istio对consul服务发现的支持还不错,且在其release包中,自带了对应的安装部署的docker-compose文件。

所以,我决定重点POC一把基于consul做服务发现的istio的情况。

系统架构

其架构如上图所示,各个微服务的功能如下:

  • api-server
    与后端的Etcd负责整个istio的配置持久化;
  • registrator
    负责监听主机上的docker daemon,一旦有container创建或者销毁就按照其label将其注册到consul,从而供pilot做发现;
  • pilot
    负责各个envoy的流量管控配置生成与下发;
  • zipkin
    收集各envoy上报的trace信息,并对外展示。

安装部署

涉及istio部署和示例服务bookinfo的部署。

istio部署

部署这块,相对来讲比较简单,其发布包里面自带了基于consul部署的docker-compose.yaml。里面的api-server版本都较旧,也说明了社区未在这方面有所更新,这里重点要说下遇到的对应问题以及其更改方法。

docker-compose.yaml文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
version: '2'
services:
etcd:
......

istio-apiserver:
# 更改为当前最新版本的api-server
image: gcr.io/google_containers/kube-apiserver-amd64:v1.14.1
networks:
istiomesh:
ipv4_address: 172.28.0.13
aliases:
- apiserver
ports:
- "8080:8080"
privileged: true
environment:
- SERVICE_IGNORE=1
command: ["kube-apiserver", "--etcd-servers", "http://etcd:2379", "--service-cluster-ip-range", "10.99.0.0/16", "--insecure-port", "8080", "-v", "2", "--insecure-bind-address", "0.0.0.0"]

consul:
......

registrator:
# 更新版本为master
image: gliderlabs/registrator:master
networks:
istiomesh:
volumes:
- /var/run/docker.sock:/tmp/docker.sock
command: ["-internal", "-retry-attempts=-1", "consul://consul:8500"]

pilot:
......

zipkin:
......

如上文所注释,这里需要修改几个地方:

  1. 由于自带的api-server版本太老,部署的时候会出现一些问题,直接使用最新版本就行了;
  2. registrator的latest版本无法注册协议到consul的service meta中,需要更改为master版本;
  3. 另外,第一次运行由于api-server未能够先ready,pilot会挂掉,只需要重启一次就行了。

应用部署

1
2
3
4
5
6
[root@vm-1 consul]# pwd
/root/istio-1.1.6/samples/bookinfo/platform/consul
[root@vm-1 consul]# ls
bookinfo.sidecars.yaml destination-rule-all.yaml virtual-service-ratings-test-abort.yaml virtual-service-reviews-test-v2.yaml
bookinfo.yaml README.md virtual-service-ratings-test-delay.yaml virtual-service-reviews-v2-v3.yaml
cleanup.sh virtual-service-all-v1.yaml virtual-service-reviews-50-v3.yaml virtual-service-reviews-v3.yaml

相信看到这里,大家都明白为啥k8s是主流方向了。这里示例代码中每一个服务的运行实例都需要再手动部署一个sidecar,想想k8s上自动注入的便捷性,突然感觉回到了解放前。

运行起来之后,可以在consul看到下列服务;当然,consul的UI上面未能够展现出所有的tags信息。

通过简单的访问productpage之后,我们可以在zipkin上看到对应的调用链信息视图。

如果这过程中某些配置不正确,可以查看对应envoy的配置信息,基本就是进入到envoy对应的network namespace去执行curl localhost:15000/help 获取各种配置信息(这块在上一篇中有具体的介绍,这里不再详说)。

关于部署就讲这么多,主要是通过这样一个过程让我们对基于consul服务发现的istio有一个更加直观的认识。下面我们就来吐槽!

待完善的方面

  • 缺少mixer的支持

    mixer一方面提供了policy(虽然这个很影响性能,有点鸡肋),另一方面提供了telemetry的能力。虽然policy我们可以先忽略它,但是telemetry影响到后面的流量拓扑、性能的可视化。在这个用户体验为王的时代,没有这块功能相当于直接把自己扼杀了。

    按理讲让envoy上报attribute到mixer也不是什么难事,最可怕的就是envoy中mixer filter的内置标签耦合了k8s太多的label信息,导致其对于consul情景来讲直接不可用(这只是猜测,有待考证)。

  • 业务转发逻辑重复

    我们来分析一下流量的转发流程:A要发送流量给B服务,假设B有5个实例,基于consul的服务发现,一定是基于业务代码内置的客户端负载均衡逻辑来选择目标服务实例。业务代码通过consul订阅目标服务的实例状态,转发之前通过算法计算一遍目标服务实例IP,总算把报文送出去了,但到了envoy这一层之后,起会直接忽略报文中的目标IP地址,而按照其目标服务的特征和流量控制的规则,从新计算路由。这在高并发下,势必造成大量的资源消耗和浪费。

    k8s基于dns的服务发现就没有这样的烦恼,dns信息都是缓存了的,只要能够将报文送达envoy上,至于下一步怎么路由,那是envoy的事情,业务程序不关心转发。

  • sidecar部署

    在VM上,对于少量的几个服务还好,大不了每个服务手动部署一个sidecar,但是噩梦还没完,当删除业务容器的时候,也要一并删除对应的sidecar。当规模上去了之后,怎么办? 这势必需要一套脚本或者自动化的东西来完成这样繁琐单调的工作。

    另外,还可以在VM上部署一个集中的sicecar,然后VM上的应用使用非容器化部署(由于pilot-agent使用--serviceCluster参数的值来向pilot标识自己与主业务容器的关联关系,这种方式的可行性有待考证)。

  • VM与k8s融合部署

    假设按照我们前面的需求,VM要与k8s一同被istio集中管控怎么办?首先服务发现怎么解决,假设使用consul就意味着k8s上的服务也需要注册到consul上来,当然这块业务代码已经实现。但是注册时可能并未按照istio所需要的label信息来注册到consul,这可能导致consul上的服务无法被pilot标识。

0%