经验总结:如何避免日志的重复采集问题?
- 日志服务agent需要在配置文件 “ilogtail_config.json” 中增加配置参数 “check_point_filename”,指定checkpoint文件生成的绝对路径,并且将此路径挂载至宿主机目录下,确保容器在重启时不会丢失checkpoint文件,不会出现重复采集问题。
服务注册
etcd是一个具备高可用性和强一致性的键值存储仓库,它使用类似于文件系统的树形结构,数据全部以“/”开头。etcd的数据分为两种类型:key和directories,其中key下存储单独的字符串值,directories下则存放key的集合或者其他子目录。
在五阿哥环境中,每个向etcd注册的应用服务,它们的根目录都以 “/${APP_NAME}_${ENVIRONMENT}” 命名。根目录下存储每个应用实例的Key信息,它们都以 “${IP}-${PORT}” 的方式命名。
下图是使用上述约定,存储在etcd上某应用实例的数据结构:
可以看到我是使用get方法向etcd发送请求的,请求的是部署在预发环境(PRE)的搜索服务(search);在它的根目录“/search_PRE”下,仅存储了一个应用实例的信息,这个实例的key是“172.18.100.31-86”;对应的value是“172.18.100.31:86‘’,整个注册过程是这样的:
- 通过代码为容器应用程序生成随机端口,和宿主机正在使用的端口进行比对,确保端口没有冲突后写入程序配置文件;
- 把通过python和etcd模块编写的服务注册工具集成在脚本中,将IP地址和上一步获取的随机端口以参数的方式传递给服务注册工具;
- 待应用程序完全启动后,由服务注册工具以约定好的数据结构将应用实例的写入etcd集群,完成服务注册工作;
- 容器定时向etcd发送心跳,报告存活并刷新ttl时间;
- 容器脚本捕获rancher发送至应用实例的singnal terminal信号,在接收到信号后向etcd发送delete请求删除实例的数据。
注:在ttl基础上增加主动清除功能,在服务正常释放时,可以立刻清除etcd上注册信息,不必等待ttl时间。
经验总结:容器在重启或者意外销毁时,让我们一起看一下这个过程中容器和注册中心都做了什么事情?
- 应用在注册是携带key 和value时携带了ttl超时属性,就是考虑到当服务集群中的实例宕机后,它在etcd中注册的信息也随之失效,若不予清除,失效的信息将会成为垃圾数据被一直保存,而且配置管理工具还会把它当做正常数据读取出来,写入web server的配置文件中。要保证存储在etcd中的数据始终有效,就需要让etcd主动释放无效的实例信息,来看一下注册中心刷新的机制,代码直接奉上:
服务发现
confd是一个轻量级的配置管理工具,支持etcd作为后端数据源,通过读取数据源数据,保证本地配置文件为最新;不仅如此 ,它还可以在配置文件更新后,检查配置文件语法有效性,以重新加载应用程序使配置生效。这里需要说明的是,confd虽然支持rancher作为数据源,但考虑易用性和扩展性等原因,最终我们还是选择了etcd。
和大多数部署方式一样,我们把confd部署在web server所在的ECS上,便于confd在监测到数据变化后及时更新配置文件和重启程序。confd的相关配置文件和模板文件部署在默认路径/etc/confd下,目录结构如下:
/etc/confd/
conf.d
confd.toml
templates
confd.toml是confd的主配置文件,使用TOML格式编写,因为etcd是集群部署,有多个节点,将interval、nodes等选项写到了这个配置文件里。
cond.d目录存放web server的模板配置源文件,也使用TOML格式编写。该文件用于指定应用模板配置文件路径(src)、应用配置文件路径(dest)、数据源的key信息(keys)等。
templates目录存放web server下每个应用的模板配置文件。它使用Go支持的text/template语言格式进行编写。在confd从etcd中读取到最新应用注册信息后,通过下面的语句写入模板配置文件中:
{{range getvs "/${APP_NAME}/*"}}
server {{.}};
{{end}}
通过supervisor管理confd进程。confd在运行后会每隔5秒对etcd进行轮询,当某个应用服务的K/V更新后,confd会读取该应用存储在etcd中的数据,写入到模板配置文件中,生成这个应用配置文件,最后由confd将配置文件写入到目标路径下,重新加载nginx程序使配置生效。
结语
以上是五阿哥运维技术团队针对Docker容器云平台建设实践,目前已经将权限开放给开发同学,实现云上和云下实例使用一套平台进行管理,业务实例按需弹性扩容和缩容,规范化的项目管理和发布流程,实例和业务可按需进行扩容和缩容,实现7*24小时“一站式”的持续交付,开发同学更聚焦于自己的业务开发,提高了公司的研发过程的效能。
接下来我们还会不断优化和适配各种业务场景,逐渐完善容器云平台,同时会将容器云平台各种功能,总结的经验和教训不断分享给大家,给大家在工作中一些参考,避免走重复的“弯路”。
Q & A
Q:你们的监控是怎么做的呢?
A:利用zabbix 自动注册(AutoRegistration),Grafana通过调用zabbix的API接口进行监控指标的统一展示。
Q:您说的网络Host模式是在Rancher中指定容器的网络模式吗?现在Rancher有桥接、托管之类的,
A:rancher网络模式中的host模式。
Q:CICD是已经集成进来还是单独模块?
A:已经集成,在统一一个平台展示,调用jenkies的接口。
Q:请问有用scaleio作为docker后端存储么?或者说,有用分布式存储用做容器的存储空间吗?
A:暂时未使用分布式存储,目前都跑在aliyun ecs和VMware的虚拟机上。
Q:rancher使用了host模式后,外部如何访问容器啊?我之前容器启动不指定网络,然后由pipework指定网络的。
A:网络共享主机网卡,通过应用的服务注册和发现即可对外提供服务。
Q:日志用什么软件展示内容的?
A:用ELK。
Q:Zabbix怎么监控到容器内的计算资源?
A:基于docker的python模块,编写的监控脚本。来实现容器内计算资源的监控。
Q:现在是否有应用APM的监控?
A:有用,性能监控基于阿里的”鹰眼”,结合自己开发来做的。
——
Q:就是rancher可以对容器的应用可以监控是吧?结合鹰眼和自己开发是么?
A:基础计算资源监控和网站应用性能监控是分开的。
Q:jenkins默认的用户名密码是什么?
A:私信我我再告诉你:P
Q:私有云和阿里云之间的联通走的是公网还是专线接入走的内网?
A:内网专线方式
Q:jenkins 那块用了什么插件呢?
A:Git Plugin,Status Monitor Plugin,pipeline plugin 用户认证等插件。
Q:使用host模式rancher的haproxy配置,是不是需要指定多条具体到每个容器?
A:未用haproxy,使用的是nginx。
Q:请问是用容器云平台统一管理私有云和阿里云上的虚拟机上的容器吗,用这种方式实现灾备?
A:公有云和私有云主机和容器都可以进行管理,支持业务的快速扩容和缩容。
Q:应用程序产生的日志怎么收集?
A:容器中部署agent把应用日志统一投递到日志平台。
——
Q:容器中部署agent,那岂不是容器变得很重?
A:是重,但会标准。见解不同,实现就好。
Q:服务注册是jenkins集成的最后一步吗?
A:不是,在容器启动后自动向etcd集群进行注册。
Q:请问在实际企业容器云部署过程中,是不是开发代码都commit到一个新的镜像中,持久化数据都单独用容器数据卷的方式,映射到宿主机上进行管理的呢?
A:应用分有状态和无状态,区别对待。
Q:git持续集成, 开发到测试是否是合并到测试分支, 然后出发执行jenkies作业, 测试通过,再把代码再合并到生产分支上吗? 这块您们是怎么做的?
A:开发到测试,发布的分支仍然是开发分支,发布预发和线上是release分支,测试通过后合并至master。
Q:java应用的弹性具体如何做到的?
A:session共享和应用优雅上、下线。
Q:nginx的话,配置是在容器里面配,还是配置好了做成镜像?
A:镜像,配置文件挂载。
Q:请问数据库也是部署在容器云上吗,还是独立的数据库平台?
A:数据库独立部署
Q:采用host网络是否主要考虑是方便服务注册?
A:方便服务注册和发现,还有性能。
Q:rancher中的容器的内存分配多少合适,比如一个用户管理的微服务跑在3个实力的容器中,我怎么测试来给每个实力分配多少内存合适的值?
A:应用可能是CPU密集型/内存密集型/IO密集型,不同的应用根据不同的实际情况进行配置。
Q:有集群的权限管理么?比如集群中a部分只给a业务使用,b集群给b业务使用?
A:有的,类似于pool。
本文为授权转载文章,任何人未经原授权方同意,不得复制、转载、摘编等任何方式进行使用,e-works不承担由此而产生的任何法律责任! 如有异议请及时告之,以便进行及时处理。联系方式:editor@e-works.net.cn tel:027-87592219/20/21。