微服务运行指南——For Cattle
站在微服务的角度看容器的基础设施服务可以分为三层:
微服务基础层
微服务构建层
微服务访问层
Rancher的服务发现就是基于rancher-dns来实现,创建的stack&service都会生成相应的DNS记录,用户可以通过相应的规则进行访问,这样在微服务之间就可以无需知晓各自的IP地址,直接用服务名进行连接即可。
微服务基础层主要是为容器提供计算、存储、网络等基础资源。主机计算资源主要是对docker-machine封装来提供相关服务;容器存储通过Convoy组件来接入,目前对NFS协议的存储适配性最佳;容器之间的网络通过rancher-net组件实现,目前支持ipsec overlay,在Rancher1.2版本会支持CNI标准的网络插件。
微服务构建层,除了有微服务本身主体程序,还需要有一些额外的辅助工具来完善对应微服务的架构体系。rancher-dns来实现服务发现机制;rancher-metadata可以灵活动态向微服务所在容器中注入一些配置数据;healthcheck来保证微服务的高可用;同时我们还需要有微服务打包的工具,保证微服务可以在任意环境拉起运行。
微服务访问层,目前服务对外暴露访问主要以DNS绑定或是负载均衡VIP方式。Rancher提供external-dns、external-lb框架可以让高级用户hack自身的场景需求,external-dns除了支持公共的DNS服务(如route53),还支持内部DNS服务器(如bind9),而external-lb目前支持F5设备。除此之外,Rancher内置的负载均衡是基于Haproxy实现的,支持L4-L7。
本次分享,我将会以概念介绍原理讲解并穿插一些实际案例这样的方式进行分享。
Rancher的元数据服务rancher-metadata灵活性非常大,比较复杂的微服务架构可以通过metadata实现一定程度的解耦,尤其是confd+metadata会有意想不到妙用,这部分内容可以参考 http://niusmallnan.github.io/_build/html/_templates/rancher/confd_metadata.html
Rancher的healthcheck基于Haproxy实现,支持TCP/HTTP,当unhealthy触发时按照预先设置的策略执行:
什么也不做
按照scale的容器数量重建
保证至少x个healthy的容器数量
当针对某个service创建healthcheck策略后,service中容器所在的agent节点上会启动Haproxy服务,同时把healthcheck的配置转化为Haproxy的配置。如图中所示添加了backend,其对应的ip就是container的ip。此外还要将Haproxy的stats scket暴露出来,以便读取backend的状态信息。
我们可以在外部程序中与Haproxy sock通信,可以获取相关backend的状态信息,由于我们在Haproxy中设置check机制,所以backend的状态是会自动更新的。
Rancher Agent上运行的host-api组件通过Haproxy sock来读取backend状态信息,同时通过rancher event机制把状态信息push给rancher-server,rancher-server根据之前设置的healthcheck策略,来控制相关的rancher agent执行container recreate操作。
如果微服务本身是自带服务端口(TCP/HTTP),那么healthcheck规则很好设置,只要正常填写表单项就可以。但实际应用中有些微服务并不会有端口暴露,它可能只是一个与DB交互的程序,这时我们会考虑让服务本身不要有大的代码改造,所以就需要用一些小工具来辅助一下。
微服务的访问入口,除了我们熟知的LB方式,还可以通过绑定DNS来实现,尤其是在私有云场景下,内部DNS的使用其实比单纯使用LB暴露IP+Port方式更加简洁,因为这样无需考虑微服务的容器漂移导致的服务IP出现变化。
Rancher提供了一个external-dns框架 https://github.com/rancher/external-dns,它可以实现service的服务地址转换成DNS的记录。
私有云场景中,很多行业用户在内部都使用F5硬件负载均衡来暴露服务访问地址。微服务的改造我们尽量控制在程序架构层面,而原有的网络结构尽量不要改变,那么就会引来一个微服务场景如何整合F5设备的问题。
我们以一个应用场景为例,生产环境系统中有4个微服务暴露端口分别是9070、9071、9072、9073,出于容灾恢复的考虑需要部署两套环境主环境和备环境,每个环境三台主机,所有的数据库层均放在非容器环境中,所有服务最终通过F5来暴露访问。
基于Rancher来实现这种应用场景:创建两个environment分属主环境和备环境,由于是不同的ENV,所以这两个环境是从计算存储网络层面都是隔离的。每个环境中创建一个stack,stack下创建4个service,service加上global=true的label,保证每台host上都运行该service,同时通过portmap把service的服务端口直接暴露在host上,外部的F5设备则将VIP配置到这些HostIP+Port上。
关键的F5设置,我们要考虑最好能够动态设置。Rancher提供了一个external-lb框架 https://github.com/rancher/external-lb来解决此问题,F5的驱动亦位列其中,同样也是通过rancher-metadata组件来获取微服务的IP+Port信息。
浮动IP本是Iaas的产物,而Caas仍处在不断演变的过程中,企业内部的网络结构仍然需要浮动IP的机制。最主要的场景就是防火墙的规则设置,通常其规则都是针对某个IP,而这个IP就意味着无论后端的服务怎么变换,它要求IP是不能变化的,否则就要不停的修改防火墙规则,这是企业运维人员最无法接受的。
本质上我们需要解决微服务相关的容器发生漂移之后,其对外暴露的IP仍然保持不变。
Rancher的合作伙伴睿云智合提出过一个浮动IP的解决方案,是一个很不错的思路。
当然我们也可以利用Cattle自有机制来变通地搞定这个问题。
微服务的访问入口使用内置的rancher-lb方式,可以通过label scheduling方式,让rancher-lb的容器只落在固定主机上,相关的防火墙只要配置固定的主机IP即可。
最后,我们来一起看一下,比较合适的通用的微服务部署结构。
这里面使用sidekick容器来分离主服务的功能,配置文件和日志分别由不同的容器来处理,同时保证整体性,可以完整扩容和克隆。配置文件统一放在 convoy连接的NFS存储中,保证配置文件的一致性。logging容器会把日志统一发送到ELK日志系统中,便于集中查询和管理。保证服务的可用性,healthcheck必不可少。外部则使用内置的Rancher LB来暴露访问。
Q & A
Q:convoy插件的现在有支持ceph或者gluster的catalog么?
A:gluster的catalog 之前有,但是一直有些问题,现在已经被移除了。convoy目前还不支持ceph。
Q:最后一个架构里面,是把日志存到一个volume,然后应用和日志服务,同时挂载的意思么?
A:日志就是通过logging容器发送到ELK中收集起来。
Q:直接用log插件发的么?
A:log driver只能把标准输入输出发送出去,而图中的架构更适合传统的写日志文件形式,把日志文件的内容发送到elk中。
Q:具体的操作是不是日志存在一个sidekick 容易中,让后让logging容器来解析和发送?
A:是这样的。
Q:这样这个volume 需要mount 本地目录上去么?还是就已一个container的形式存在?
A:一个container足矣。
Q:现在convoy是不是暂时没有其他方案把一个集群的本地host的磁盘利用起来?
A:Rancher有一个longhorn是你说的场景,还在迭代中。
原文来源:Rancher Labs