#amazon-web-services #jenkins #gradle #aws-lambda
#amazon-веб-сервисы #дженкинс #gradle #aws-lambda
Вопрос:
У нас есть несколько функций lambda, и я автоматизировал развертывание кода с помощью плагина gradle-aws-plugin-reboot.
Он отлично работает со всеми лямбда-функциями, кроме одной. В этом конкретном случае я получаю эту ошибку:
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. В редких случаях даже развертывание этого лямбда-кода завершается успешно. Тем не менее, нет случаев сбоя какого-либо из других.
Я знаю о новой функции лямбда-состояний и о том, что она потенциально может привести к этой ошибке. Однако, поскольку все остальные лямбда-выражения работают, используя один и тот же код как в 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
}
Как уже упоминалось, это практически идентично во всех лямбдах, кроме свойств, очевидно. Свойства также не могут быть проблемой, поскольку они одинаковы в моей локальной среде и в jenkins.
Выполнение развертывания в файле jenkins довольно неинтересно. Сначала он загружает jar в S3 для архивирования, затем выполняет задачу gradle для развертывания lambda. Просто чтобы быть уверенным, я попробовал без загрузки 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'
}
}
Я потратил часы, просматривая все конфигурации разных лямбд, сравнивая их, ища различия, которые могут быть источником проблемы, но у меня почти нет идей, где проблема может быть обнаружена к настоящему времени. У кого-нибудь есть какие-либо догадки?
Ответ №1:
Я понял это. Вам лучше ничего не держать во рту, потому что это смешно!
По сути, у меня не было никаких вариантов, и я остановился на последнем заметном различии между этим развертыванием и теми, которые работали: размер файла развертываемого jar. Сбой, безусловно, был самым маленьким. Поэтому я раздул его примерно на 60%, чтобы сделать его сопоставимым со всем остальным … и это исправило!
Это звучит нелепо. Вот моя гипотеза о том, что происходит: если загрузка занимает слишком мало времени, лямбде каким-то образом требуется больше времени для изменения своего состояния. Я не уверен, почему это может быть, вы ожидаете, что состояние изменится, когда все будет сделано, а не займет больше времени, если все будет сделано быстрее, верно? Может быть, есть минимальное время для сохранения состояния? Я бы не знал. Однако есть одна вещь, подтверждающая эту гипотезу: развертывание с моего локального компьютера всегда работало. Эта загрузка, естественно, займет больше времени, чем требуется Дженкинсу внутри aws vpc. Итак, эта гипотеза, как бы нелепо это ни звучало, соответствует всем фактам, которые у меня есть.
Возможно, кто-то, лучше разбирающийся в механизмах lambda-internal, может добавить к этому комментарий, объясняющий, как это может произойти…
Комментарии:
1. мне действительно трудно в это поверить, но мы также видим эту проблему. возможно, это не совпадение.
2. мы добавили проверки статуса после каждой команды AWS.
3. @tripod Это, безусловно, было бы правильным способом сделать это, но, к сожалению, у меня сейчас нет времени обновлять плагин, о котором я ничего не знаю…
Ответ №2:
в моем случае это решается после того, как я добавил aws:states:opt-out
в описание моей лямбды, как описано здесь: https://aws.amazon.com/de/blogs/compute/coming-soon-expansion-of-aws-lambda-states-to-all-functions /
Комментарии:
1. Я удивлен, что это все еще работает. Я почти уверен, что в какой-то момент отказ от использования больше не будет вариантом.