踩坑小结喜马拉雅FM测试环境的Dock

随着容器技术的流行,作为线上应用Docker的铺垫,喜马拉雅FM从年开始推进测试环境的Docker化。本文重点介绍笔者在Docker化的过程中如何进行技术选型、环境搭建,和实践中碰到的一些问题及其解决方案。

为什么要Docker化?

1.标准化

配置标准化,以部署Tomcat为例,实际物理环境中,通常一台物理机部署多个Tomcat,这就存在Tomcat的端口及目录管理问题。理想状态下:一个项目一个主机Tomcat,Tomcat永远位于/usr/local/tomcat(或其他你喜欢的位置)下,对外端口是,debug端口是。

部署标准化,现在云平台越来越流行,同时,也不会立即丢弃物理环境,因此必然存在着同时向云环境和物理环境部署的问题。这就需要一系列工具,能够屏蔽物理环境和云环境的差异,Docker在其中扮演重要角色。

.API化

通过API接口操作项目的部署(CPU、内存分配、机器分配、实例数管理等),而不是原来物理机环境的的手工命令行操作。

3.自动化

调度系统可以根据API进行一些策略性的反应,比如自动扩容缩容。

上述工作,原有的技术手段不是不可以做,可是太麻烦,可用性和扩展性都不够好。

Docker化的四个小目标

1.业务之间不互相干扰

一个项目/war一虚拟机/容器

Ip-pert-task

.容器之间、容器与物理机之间可以互通

3.容器编排:健康检查、容器调度等

4.使用方式:通过yaml/json来描述任务,通过API部署

网段

对外抽象

基本环境:物理环境

19..0.0/16

一台台互联互通的物理机,大部分要手工

目标:容器环境

17.xx.0.0/16

Marathon标准化的API,大部分操作(deploy、scal等)可以自动化

总结一下,基于n台物理机搭建容器环境,整个工作的主线:

一个项目一个主机==物理机资源不够==虚拟化==轻量级虚拟化==Docker==针对Docker容器带来的网络、存储等问题==集群编排==对CI/CD的影响。

虚拟化网络的两种思路

Overlay

隧道,通常用到一个专门的解封包工具。

路由,每个物理机充当一个路由器,对外,将容器数据路由到目标机器上;对内,将收到的数据路由到目标容器中。

通常需要额外的维护物理机以及物理机上容器IP(段)的映射关系。

Underlay

不准确的说,容器的网卡暴露在物理网络中,直接收发,通常由外部设备(交换机)负责网络的连通性。

经过对比,我们采用了MacVLAN,主要是因为:

简单

效率高

可将容器“当成”虚拟机用,容器之间互通就行,不需要支持复杂的网络伸缩、隔离、安全等策略。

IP分配问题

对于物理机、KVM等虚拟机来说,它的生命周期很长,IP一经分配便几乎不变,因此通常由人工通过命令或Web界面手动分配。而对于Docker容器来说,尤其是测试环境,容器的创建和销毁非常频繁,这就涉及到频繁的IP分配和释放。因此,IP分配必须是自动的,并且有一个IP资源池来管理IP。

在Docker网络中,CNM(ContainerNetworkManagement)模块通过IPAM(IPaddressmanagement)driver管理IP地址的分配。我们基于TalkingData/Shrike改写了自己的IPAM插件,fix了在多实例部署模式(一个Dockerhost部署一个IPAM,以防止单实例模式出现问题时,整个系统不可用的问题)下的重复存取问题。

Docker之外的编排工具

Docker解决了单机的虚拟化,但当一个新部署任务到达,由集群中的哪一个Docker执行呢?因此,Docker之外,需要一个编排工具,实现集群的资源管理和任务调度。

编排工具

优缺点

Swarm/Swarmmode

Docker原生,但目前更多是一个Docker任务分发工具;换句话说,作为Docker分发工具是够用的,但作为集群资源管理和任务调度工具是勉强的。

Kubernetes

Kubernetes提供的Pod、Service、replicaController概念简(固)化了一些问题,但使用起来也相对复杂。

Mesos+Marathon(本文采用)

在Docker管理和分布式资源管理之间,找到了一个比较好的平衡点。

这些工具均采用Master/Slave架构,假设我们将物理机分为Master和Slave,这些工具在Slave上运行一个Agent(任务执行和数据上报),在Master上运行一个Manager(任务分发和数据汇总)。从功能上说,任务分发和容器资源汇总,这些工具可以满足要求。它们的根本区别就是:发展历程的不同。

从一个Docker/容器化调度工具,扩展成一个分布式集群管理工具

从一个分布式资源管理工具,增加支持Docker的Feature

到目前为止,根据喜马拉雅FM测试环境的实践,发现有以下特点:

对编排的需求很弱,基本都是单个微服务项目的部署。微服务项目的协同、服务发现等由公司的服务治理框架负责。

基础服务,比如MySQL、Hadoop等暂不上Docker环境。

需要查询编排工具的API接口,同时有一个良好的Web界面,对编排工具的数据汇总、资源管理能力有一定要求。

因此我们决定使用Marathon+Mesos方案。在后面实践的过程中,因为网络和编排工具的选择,IP变化的问题带来很大的困扰,我们甚至专门开发了几个小工具,参见下文。

image的组织

Docker的厉害之处,不在于发明了一系列新技术,而在于整合了一系列老技术,广为人知的阿里、腾讯等大厂在Cgroups、Namespace等基础上搞了一套自己的容器工具。对于阿里,使用Docker初衷是Docker镜像化,也就是其带来的应用环境标准化,而不是容器化。

Docker镜像的实践主要涉及到以下三个问题:

1.搭建私有imagerepository

.对layer进行组织

3.镜像的分发较慢

预分发,但这不解决根本,只适用部分场景

对layer进行压缩,京东目前采用该方案

4.镜像化带来容器重启

因为镜像是一体的,哪怕只有一点更改,镜像的发布都必须销毁之前的容器,然后按照新镜像创建新容器。耗时是一方面,对以下场景也很不友好:

只是更新一个文件,项目、容器均需要重启

因为加载缓存等原因,项目、容器启动比较耗时

对于具体的场景,可以有具体的办法规避。对于通用的解决方案,阿里通过改写Docker,对镜像支持HotFix标识,deploy这类镜像,不再创建新容器,而是更新容器。

我们要对镜像的layer进行组织,以最大化的复用layer。

镜像名

功能

Alpine

baseimage

Alpine+

一些基本的命令

JDK6/7/8、SSH

新增JDK

Tomcat6/Tomcat7/Tomcat8

新增Tomcat

因为只是在测试环境使用,镜像较慢的矛盾还不是太突出。这里有一个技术之外的问题。阿里对于dockerimagefeature的改造,实现了如下优化:

可以减少容器的重启次数,进而减少IP的分配和释放。

影响到容器的编排策略,即deploy新的任务不再是选择一个机器运行容器,而是找到原来的容器应用变更。

对Docker的各种特性的认识,一则认为天经地义,二则逆来顺受。出现问题,要么想办法规避,要么在外围造个轮子去解决(还是规避)。

CI

Jenkins如何跟Marathon结合,现成的方案很多。关键是提供几套不同的模板,方便不同业务的使用。

容器变化带来四大问题

使用Docker后,容器在物理机之间自由漂移,物理机的角色弱化成了:单纯的提供计算资源。但带来的问题是,影响了许多系统的正常运行。

1.IP变化

许多系统的正常运行依赖IP,但IP不稳定带来一系列的问题。而解决IP的变化问题主要有以下方案:

新增组件屏蔽IP变化

提供DNS服务(有缓存和多实例问题)

不要改变IP

既然重启后,IP会改变,就减少容器重启

服务与IP绑定(这个方案非常不优雅)

对于Web服务,IP的变化导致要经常更改Nginx配置,为此,我们专门改写了一个Nginx插件来解决这个问题。

对于RPC服务,技术团队有独立开发的服务治理系统,实现服务注册和发现。但该系统有审核机制,对于跨语言调用,因为rpc客户端不通用,仍有很多不便。

.文件存储

有许多项目会将业务数据存储在文件中,这就意味着项目deploy进而容器重启之后,要能找到并访问这些文件。在Docker环境下主要有以下两种方案:

Dockervolumn+clusterfs

Dockervolumeplugin

我们当下主要采用第一种,将clusterfsmount到每台Dockerhost的特定目录(例如/data),打通container/data==dockerhost/data==clusterfs/data,任意容器即可共享访问/data目录下的数据。

3.日志采集与查看

为了日志持久化存储,技术将容器的日志目录映射到了物理机上。but,一个项目的日志分散在多个物理机中。

原有的日志采集报警系统,负责日志采集、汇总、报警。因此容器化后,并不会有什么影响。但该系统只采集错误日志,导致开发人员要查看日志以调试程序时,比较麻烦。

最初,提供了一个WebConsole来访问容器,操作步骤为:login==findcontainer==inputconsole==op。

但依然过于繁琐,并且WebConsole的性能也不理想。而直接为每个容器配置sshserver,又会对safeshutdown等产生不良影响。因此:

登陆测试环境,90%是为了查看日志。

和开发约定项目的日志目录,并将其映射到物理机下。

间接配置SSH。每个物理机启动一个固定IP的SSHContainer,并映射日志目录。

使用Go语言实现了一个essh工具,essh-imarathon_app_name即可访问对应的SSHContainer实例并查看日志。

当然,日志的问题,也可以通过elk解决。

其他问题

1.Baseimage的影响

时区、TomcatPermGensize、编码等参数值的修正。

baseimage为了尽可能精简,使用了alpine。它的一些文件缺失,导致一些Java代码无法执行。比如,当去掉/etc/hosts中ip和容器主机名的映射后,加上/etc/sysconfig/network的缺失,导致Java代码InetAddress.getLocalHost()执行失败。

.Safeshutdown,部分服务退出时要保存状态数据

3.支持sshd,以方便大家查看日志文件

使用supervisord(管理SSH和Tomcat),需要通过supervisord传导。SIGTERM信号给Tomcat,以确保Tomcat可以safeshutdown。该方法经常发生supervisord让Tomcat退出,但自己不退出的情况。

每台机器启动跟一个专门的容器,映射一些必要的volume,以供大家查看日志等文件。

4.Marathon多机房主备问题

5.容器的漂移对日志采集、分析系统的影响

6.对容器提供DNS服务,以使其可以正确解析外部服务的hostname

7.如何更好的推广与应用的问题

todo

1.日志采集,简化日志搜索

.一个集中式的DC

当下,项目部署的各个阶段分散在不同的组件中。呈现出来的使用方式,不是面向用户的。

Jenkins负责代码的编译和Marathonjob的触发

Marathon负责任务调度、销毁和回滚等

Portainer负责容器数据的界面化以及WebConsole

这样带来的问题是:

对于运维人员来说,一些操作不能固化下来,比如回滚等,手工操作易出错。

对于用户来说,容易想当然的通过portainer进行增删改容器的操作,进而引起系统的不一致。

因为是现成系统,很难加入技术自己的逻辑,这使得配置上经常出现一些语义冲突的情况。

作者:李乾坤

编辑:陶家龙、孙淑娟本文选自Docker(),原文有删减

李乾坤

喜马拉雅FMJava开发工程师

李乾坤,喜马拉雅FMJava开发工程师。年开始接触Docker,年东南大学硕士毕业,随即加入喜马拉雅FM,从事后台开发,年参与测试环境Docker化,目前负责平台支持业务的维护与开发。

赞赏

长按







































北京中科医院假
迪赛胸腺肽肠溶片价格



转载请注明:http://www.guyukameng.com/http/8443.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了