AWS lambda ResourceConflictException 部署

AWS lambda ResourceConflictException on deployment

我们有几个 lambda 函数,我已经使用 gradle-aws-plugin-reboot 插件自动部署代码。

它在 除了一个 lambda 函数之外的所有函数上都非常有效。在那个特定的那个上,我收到了这个错误:

com.amazonaws.services.lambda.model.ResourceConflictException: The operation cannot be performed at this time. An update is in progress for resource: arn:aws:lambda:*redacted*:the-lambda-that-fails (Service: AWSLambda; Status Code: 409; Error Code: ResourceConflictException; Request ID: 8fef505a-587c-4e77-a257-182d6eecadd0; Proxy: null)

不过,该错误还有一个警告:它只发生在 Jenkins 上。 运行 我本地机器上的部署任务有效。我可以 通过快速连续地发送垃圾邮件部署在本地重现该问题,在这种情况下,每秒都会失败。考虑到错误消息,这是可以理解的。

有趣的是,尽管它因相同的错误而失败,但它不会像 jenkins 那样在同一点失败。当我在本地执行此操作时,它在部署环境时失败,在 jenkins 上它 always 在部署代码时失败。不过,我不确定插件先执行哪一个。 此外,它并不完全 always 在 jenkins 上失败。很少有这种 lambda 部署成功的情况。不过,没有任何其他失败的实例。

我知道新的 lambda states feature,它可能会产生此错误。但是,由于所有其他 lambda 都可以工作,它们在 build.gradle 和 jenkinsfile 中都使用相同的代码,所以这似乎不太可能是我的问题。

gradle 中的部署任务如下所示:

   register<jp.classmethod.aws.reboot.gradle.lambda.AWSLambdaMigrateFunctionTask>("deploy") {

        // Create the environment variables from the gradle property configuration.
        // users and passwords should be stored in the system properties file, not the projects!
        val (environmentProperties, function) = if (branch == "master") {
            val webcamServicePutterProd: String by project
            val webcamServicePutterProdPwd: String by project
            mapLambdaProperties("deployProd_", webcamServicePutterProd, webcamServicePutterProdPwd) to
                    "lambda-function-name-prod"
        } else {
            val webcamServicePutterDev: String by project
            val webcamServicePutterDevPwd: String by project
            mapLambdaProperties("deployDev_", webcamServicePutterDev, webcamServicePutterDevPwd) to
                    "lambda-function-name-dev"
        }

        val jarFile = File("build/libs").walk().first { it.name.endsWith("-all.jar") }
        functionName = function
        zipFile = jarFile
        handler = "webcam.yellow.sqs.lambda.WebcamWorker::handleRequest"
        publish = true
        environment = environmentProperties
    }

如前所述,除了属性外,这在所有 lambda 中几乎是相同的。不过,属性也不是真正的问题,因为它们在我的本地环境和 jenkins 上是相同的。

jenkinsfile 中的部署执行非常不引人注目。它首先将 jar 上传到 S3 进行存档,然后执行部署 lambda 的 gradle 任务。可以肯定的是,我尝试不使用 S3 上传以防万一可能有一些模糊的连接,但这也没有帮助。

        stage('Deploy artifact') {
            when {
                equals expected: 'true', actual: deployArtifact
            }
            steps {
            // archive build on S3
                withAWS() {
                    s3Upload(
                            workingDir: 'build/libs/',
                            includePathPattern: '*-all.jar',
                            bucket: 'yellow-artifacts',
                            path: "webcam-worker-lambda/${artifactFolder}/"
                    )
                }

                // deploy build to lambda
                sh './gradlew deploy'
            }
        }

我花了几个小时检查不同 lambda 的所有配置,比较它们,寻找可能是问题根源的差异,但我几乎不知道问题可能在哪里目前为止。有人有预感吗?

我明白了。你最好不要把任何东西含在嘴里,因为这很搞笑

基本上没有任何选择,我锁定了此部署与有效部署之间的最后一个明显区别:正在部署的 jar 的文件大小。失败的是迄今为止最小的。所以我将它膨胀了大约 60% 以使其与其他所有东西相媲美......然后修复了它!

这听起来很荒谬。这是我对正在发生的事情的假设: 如果上传时间太短,lambda 不知何故需要更长的时间来改变它的状态。我不确定为什么会这样,您会希望状态在事情 完成 时发生变化,如果事情完成得更快,则不会花费更长的时间,对吗?也许状态存在的最短时间?我不知道。 不过,有一件事可以支持这一假设:从我的本地计算机进行的部署始终有效。该上传自然会比 jenkins 从 aws vpc 内部需要的时间更长。所以这个假设,听起来很可笑,符合我手头的所有事实。

也许对 lambda 内部机制有更好理解的人可以对此添加评论,解释这是如何发生的...

在我的例子中,我在我的 Lambda 的描述中添加了 aws:states:opt-out 后就解决了,如下所述:https://aws.amazon.com/de/blogs/compute/coming-soon-expansion-of-aws-lambda-states-to-all-functions/