唐睿 阿里云智能基础产品团队 产品专家

阿里云智能中间件和容器团队产品专家,15年企业级分布式架构及业务研发和产品经验,目前主要负责阿里云中间件PaaS领域的产品设计、用户洞察及技术布道等工作。打造更好、更易用、更满足用户需要的阿里云产品。

引言

用户在使用EDAS进行应用变更的时候,一定会接触到发布单功能。发布单以图形化的方式展现了应用部署、启动、停止和扩缩容等操作的具体过程,并能查看发布脚本的执行日志,以及出错信息。对于分批进行的变更,用户可以看到每一批变更的具体信息,对于手动分批的变更,还可以在发布单界面里进行“继续”操作。如果需要中途停止变更,可以使用“终止变更”功能强行中断正在进行的操作,从而减少因误操作而造成的损失。

图1:EDAS发布单界面展示

但发布单到底是如何工作的呢?为什么EDAS控制台上的操作可以影响ECS上的应用进程?这些发布单脚本到底是什么?如果发布单里出现了异常,有哪些排查的方法呢?本文将为您一一进行揭晓。

发布单的工作原理

图2:发布单工作原理图
  • 当用户提交应用变更请求以后,会先经过Gateway进行鉴权,然后传递给EAM服务。
  • EAM服务会将此变更请求生成为一条发布单记录,并存储在Redis缓存中。
  • AgentServer服务中运行有一个定时任务,会定时从Redis缓存中拉取发布单。
  • EAM服务将下发发布单任务到运行在ECS上的StarAgent服务。
  • 发布单在ECS上执行并回传日志数据。

这里用户可能会有疑问,为什么EAM服务将发布单放入Redis缓存之后,AgentServer拉取到的发布单任务又返还给EAM来进行下发,难道不是多此一举吗?

这里其实Redis不仅仅是缓存,而是充当了一个消息队列。消息队列的能力包括异步处理和削峰填谷,当有大量发布单请求进入系统的时候,EAM会先将数据存储在Redis中,此时发布单提交操作就结束了。但是发布单的真正运行是由下游的AgentServer定时拉取后返还给EAM,从而实现了异步执行的效果。另外因为每个发布单的时间长短不一,但通常都是分钟级,这对于请求响应式的在线服务而言太过漫长,会导致线程池被占满,从而影响系统为后续请求提供服务。

引入消息队列以后当有大量请求进入系统的时候会先缓存到队列中,再由系统慢慢消化处理,不至于让系统在高峰期失去服务能力。因此看上去多此一举的设计,在大规模分布式系统中起到了非常重要的作用。

各组件之间的交互时序图如下:

图3:各组件交互时序图

发布单的结构

如图1所示,发布单模型具有一定的结构,从图中大致可以看出发布单有三个层级,如下图所示:

图4:发布单层级图

一个发布单由若干条流水线组成,每条流水线又分为几个阶段,最后一个阶段下面包含一些任务,由此构成了发布单的结构模型。其中Event和Listener是发布单的通知机制,当一个任务结束以后,其通过事件报告自己的完成状态,再由其他组件通过Listener监听该事件进行一些业务逻辑上的后续处理。一个发布单的样例描述文件如下:

图5:发布单样例描述文件

可以看出该发布单有一条流水线(edas-app-deploy)和四个阶段(startPipeline、slbOffline、vipserverOfflineStage和deployApp),而每个阶段下又包含数量不等的任务,比如deployApp阶段包含hsfOffline、preStoreInstance和stopInstance等三个任务。阶段和任务都包含一些描述属性,例如任务之间是串行还是并行执行,每个任务的失败重试次数,以及是否忽略错误等等。

发布单问题排查

  • 排查说明图6:发布单问题排查流程
    • service类型的任务,主要是涉及外部服务的调用,service类型的任务有(括号中是任务对应的名称,在日志中展示的是括号中的名称):
      • Teinge上线/下线(tengineOnline/tengineOffline)
      • Tegine配置更新(updateTengineConfig)
      • SLB上线/下线、SLB设置权重(slbOnline/slbOffline、reopenSLBInstance/muteSLBInstance)
    • agent类型任务,需要通过staragent把命令下发到用户ECS上执行,主要有(括号中是任务对应的名称,在日志中展示的是括号中的名称):
      • 下载/安装Tomcat(pullTomcatPack/)
      • 下载应用程序包(pullWar)
      • 应用实例启动/停止(startInstance/stopInstance)
      • Teigine启动/停止(startTengineInstance/stopTengineInstance)
      • 下载镜像(pullImage)
      • URL/端口健康检查(healthCheckWithURL/healthCheckWithPort)
      • 删除应用实例/Tegine实例数据(deleteInstanceData/deleteTengineInstanceData)
      • HSF服务优雅下线(hsfOffline)
      • 更新Tomcat配置(updateTomcatConfig)
      • 更新命令执行所需的python脚本(updateTaskScript)
  • 基本排查步骤

    (1)当应用实例生命周期变更操作出现问题,首先通过变更列表,进入发布单详情,查看具体执行失败的任务日志,根据错误具体信息,来定位问题。

    (2)Agent类型任务,可以在用户ECS机器上查看/home/admin/edas/logs/tasks/{taskId},用taskId标示(这些日志可以在控制台发布单详情页,具体任务“查看日志”功能中可以看到),也可以查看ECS上的日志/home/admin/edas/script/logs/edas.action.trace;也可以通过查询数据库,查询SQL: select cmd from cmd_record where cid = ‘任务Id’,任务id可以在发布单详情页面具体任务执行日志的最上方查看。

    注意 命令执行手动执行时不要最后的-q、–async等,通常以bash开头。
    (3)如果命令在机器上执行没有失败,则综合分析agent-server、edas-admin、edas-console的日志,定位错误原因。
    (4)service类型的任务,例如Tegine上下线、Tegine状态更新、SLB上下线、SLB权重设置等任务,需要在EDAS服务组件上查看相关日志。
    • Tegine任务命令下发在EDAS-AGENT-SERVER/home/admin/edas/logs/changeorder.log,或者/home/admin/edas/logs/agent-server.log中查询,回调日志在edas-admin中/home/admin/edas/logs/admin.log或者/home/admin/edas/logs/tengine.log中查询,参考tegine流程管控流程来定位问题。
    • SLB日志在EDAS-AGENT-SERVER/home/admin/edas/logs/slb.log,或者/home/admin/edas/logs/agent-server.log中查询。
    • 其他服务类型的日志可以在/home/admin/edas/logs/agent-server.log,或者/home/admin/edas/logs/changeorder.log中查询。
  • 常见问题解决思路
    • 命令通道不通

      这个直接可以通过发布单详情页中任务执行的日志来定位问题:一般任务执行日志有“please check if service is available”字样,可以在机器上执行pkill -9 staragent && /home/staragent/bin/agent.sh start,然后让用户重置应用实例。

    • 普通应用用户ECS目录或文件权限为root,无法操作相关文件

      一般在任务执行日志,或者edas.action.trace中会有显示权限不够的信息,可以在机器上执行chown admin:admin {要修改的目录或文件},然后重试。

    • Tegine启动、停止失败

      大多是一些前置操作失败或者目录权限不正确造成的,通常可以通过重置解决。

    • exit XXX 常见错误原因

      exit 3: 磁盘满(du -h)

      exit 5: 域名解析失败(ping -c 1 $domain 测试)

      exit 8: 下载脚本或WAR包失败,通常为4XX/5XX(curl测试)

    • Tegine上下线、状态更新失败

      查看与tegine管控交互的日志,定位问题,多起是因为Tegine上线的操作失败,造成后续对Tegine的操作失败;可以通过重置解决。

    • SLB上下线失败、权重设置失败

      通过查询EDAS-AGENT-SERVER/home/admin/edas/logs/slb.log,或者/home/admin/edas/logs/agent-server.log日志定位。