You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过AWS CDK在流水线执行ECS命令并调试首次执行无效问题

ECS执行Drush命令调试方案及问题排查

问题背景

我们通过AWS CDK搭建流水线,利用Lambda执行ECS命令部署Drupal 8网站,CDK中配置了约5条此类部署命令。Lambda代码如下:

'use strict';

const AWS = require('aws-sdk');
const ecs = new AWS.ECS();
const codeDeploy = new AWS.CodeDeploy({ apiVersion: '2014-10-06' });

exports.handler = async (event, context, callback) => {
  console.log('Drush execution lambda invoked');

  const deploymentId = event.DeploymentId;
  const lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;

  try{
    let validationTestResult = 'Failed';

    const clusterName = process.env.CLUSTER_NAME;
    const containerName = process.env.CONTAINER_NAME;

    const taskListParams = {
      cluster: clusterName,
      desiredStatus: 'RUNNING',
    };

    const taskList = await ecs.listTasks(taskListParams).promise();

    const activeTask = taskList.taskArns[0];

    console.log('Active task: ' + activeTask);

    .......................

    const cimParams = {
      command: 'drush cim -y',
      interactive: true,
      task: activeTask,
      cluster: clusterName,
      container: containerName
    };

    await ecs.executeCommand(cimParams, function (err, data) {
      if (err) {
        console.log(err, err.stack, "FAILED on drush cim -y");
      } else {
        validationTestResult = 'Succeeded';
        console.log(data, "Succeeded on drush cim -y");
      }
    }).promise();

    .............................

    // Pass CodeDeploy the prepared validation test results.
    await codeDeploy.putLifecycleEventHookExecutionStatus({
      deploymentId: deploymentId,
      lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
      status: validationTestResult // status can be 'Succeeded' or 'Failed'
    }).promise();

  }catch (e) {
    console.log(e);
    console.log('Drush execution lambda failed');

    await codeDeploy.putLifecycleEventHookExecutionStatus({
      deploymentId: deploymentId,
      lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
      status: 'Failed' // status can be 'Succeeded' or 'Failed'
    }).promise();
  }
};

当前问题:命令执行日志显示成功,但网站无预期变更;第二次运行流水线时变更才生效。手动在ECS容器执行drush cim -y可正常生效,怀疑ECS执行环节存在问题,现有日志不足以定位根因,需明确有效的ECS命令调试方法。


调试与排查方案

一、完善日志采集,获取执行细节

  • 捕获Drush命令的完整输出:修改drush cim -y为drush cim -y -v 2>&1,添加 verbose 参数并将错误输出重定向到标准输出,同时在Lambda中捕获命令执行的完整输出(可通过ECS ExecuteCommand的会话日志,或在命令中将输出写入容器内文件后读取)。
  • 验证目标任务的正确性:当前代码直接取taskArns[0],流水线部署时可能存在新旧任务共存的情况,需确认执行命令的是新部署的任务。可通过筛选任务的启动时间、CodeDeploy关联的目标组标签,或从CodeDeploy事件中获取目标任务ARN,避免误操作旧任务。
  • 补充环境与权限日志:在执行Drush命令前,先执行printenv && pwd && whoami,输出容器的环境变量、工作目录和执行用户,对比手动执行时的环境,排查环境差异问题。

二、排查ECS命令执行的时机与逻辑

  • 确认命令触发时机:检查Lambda是否绑定到CodeDeploy的正确生命周期钩子,确保在新任务启动完成、流量切换前执行命令,避免命令执行在旧任务上,或新任务未完全就绪时执行。
  • 修复Lambda异步逻辑缺陷:当前代码同时使用回调函数和.promise(),会导致validationTestResult的更新逻辑混乱,甚至出现命令实际失败但仍返回成功状态的情况。修改为纯Promise风格:
    try {
      const data = await ecs.executeCommand(cimParams).promise();
      validationTestResult = 'Succeeded';
      console.log(data, "Succeeded on drush cim -y");
    } catch (err) {
      console.log(err, err.stack, "FAILED on drush cim -y");
    }
    

三、验证ECS命令执行的一致性

  • 模拟Lambda执行环境:在本地或测试容器中,使用Lambda角色的权限调用aws ecs execute-command,模拟Lambda的执行流程,对比手动执行和自动化执行的差异。
  • 检查命令执行的权限:确认Lambda角色拥有ecs:ExecuteCommand、ssm:StartSession权限,且容器的SSM Agent版本符合要求,确保命令能正常下发到容器内。

内容的提问来源于stack exchange,提问作者Dynamdilshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:15:35