Terraform+GitLab CI/CD更新AWS Lambda代码失败求助
我通过Terraform结合GitLab CI/CD更新AWS Lambda函数,CI/CD流水线显示执行成功,AWS控制台里Lambda的「最后修改时间」也正确,但实际代码没有变化。以下是相关配置:
.gitlab-ci.yml
image: name: hashicorp/terraform:light entrypoint: - "\/usr\/bin\/env" - "PATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin" #-------------------- Stages ------------------ stages: - import - validate - plan - apply install_dependencies: image: node:18.19.0 stage: package script: - cd lambdas/notifications - npm ci --cache --prefer-offline - cd ../maintenance - npm ci --cache --prefer-offline cache: key: $CI_COMMIT_REF_SLUG paths: - lambdas/notifications/node_modules/ - lambdas/maintenance/node_modules/ tags: - $CDP_K8S_LARGE # DOCKER BUILD build-dev-docker: extends: .kaniko-package stage: package variables: KANIKO_BUILD_ARGS: "--build-arg ENVIRONMENT=development --single-snapshot" EXTRA_DOCKER_TAG: "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_PIPELINE_IID" artifacts: paths: - lambdas/notifications/lambda_batch.zip - lambdas/maintenance/lambda_maintenance.zip only: refs: - develop environment: name: dev tags: - $CDP_K8S_LARGE # TERRAFORM STAGES import: stage: import before_script: - !reference [default, before_script] - source "$CI_PROJECT_DIR/before_script.sh" script: - terraform import aws_lambda_function.dev-notifications dev-notifications - terraform import aws_lambda_function.dev-maintenance dev-maintenance artifacts: paths: - terraform.tfstate validate: stage: validate before_script: - !reference [default, before_script] - source "$CI_PROJECT_DIR/before_script.sh" script: - terraform validate artifacts: paths: - terraform.tfstate plan: stage: plan before_script: - !reference [default, before_script] - source "$CI_PROJECT_DIR/before_script.sh" script: - terraform plan -out "planfile" dependencies: - build-dev-docker - validate artifacts: paths: - planfile - terraform.tfstate apply: stage: apply before_script: - !reference [default, before_script] - source "$CI_PROJECT_DIR/before_script.sh" script: - terraform show -json - terraform apply -input=false "planfile" dependencies: - build-dev-docker - plan artifacts: paths: - terraform.tfstate
main.tf
provider "aws" { region = "us-west-2" } resource "aws_lambda_function" "dev-notifications" { function_name = "dev-notifications" role = var.iam_role_arn handler = "index.handler" runtime = "nodejs20.x" filename = "${var.PROJECT_DIR}/lambdas/notifications/lambda_batch.zip" source_code_hash = filebase64sha256("${var.PROJECT_DIR}/lambdas/notifications/lambda_batch.zip") tags = { Application = "dev" Ou = "dev" } } output "notif_output" { value = aws_lambda_function.dev-notifications.function_name } resource "aws_lambda_function" "dev-maintenance" { function_name = "dev-maintenance" role = var.iam_role_arn handler = "index.handler" runtime = "nodejs20.x" filename = "${var.PROJECT_DIR}/lambdas/maintenance/lambda_maintenance.zip" source_code_hash = filebase64sha256("${var.PROJECT_DIR}/lambdas/maintenance/lambda_maintenance.zip") tags = { Application = "dev" Ou = "dev" } } output "maintenance_output" { value = aws_lambda_function.dev-maintenance.function_name }
Dockerfile
FROM node:18-alpine WORKDIR /dir COPY . /dir # Install TypeScript globally RUN npm install -g typescript WORKDIR /dir/lambdas/notifications RUN npm ci && npm run all WORKDIR /dir/lambdas/maintenance RUN npm ci && npm run all CMD ["npm", "run", "start"]
npm run all实际执行:npm run build && del -f lambda_batch.zip && npm run zip(两个Lambda仅压缩包名称不同)
排查方向
artifacts配置缩进错误:
build-dev-docker中的artifacts被错误嵌套在variables块内,导致生成的压缩包无法作为产物传递到后续Terraform阶段。需要把artifacts和variables同级放置:build-dev-docker: extends: .kaniko-package stage: package variables: KANIKO_BUILD_ARGS: "--build-arg ENVIRONMENT=development --single-snapshot" EXTRA_DOCKER_TAG: "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_PIPELINE_IID" artifacts: paths: - lambdas/notifications/lambda_batch.zip - lambdas/maintenance/lambda_maintenance.zip # ... 其他配置Docker构建的压缩包未导出:
当前Dockerfile仅在容器内部生成压缩包,但Kaniko默认不会将容器内的文件同步到GitLab Runner工作目录。需要调整Kaniko配置,或者在Dockerfile中通过多阶段构建,将压缩包复制到外部:# 构建阶段 FROM node:18-alpine AS builder WORKDIR /dir COPY . /dir RUN npm install -g typescript WORKDIR /dir/lambdas/notifications RUN npm ci && npm run all WORKDIR /dir/lambdas/maintenance RUN npm ci && npm run all # 导出阶段 FROM scratch COPY --from=builder /dir/lambdas/notifications/lambda_batch.zip / COPY --from=builder /dir/lambdas/maintenance/lambda_maintenance.zip /同时在Kaniko配置中调整产物导出路径,确保压缩包进入流水线工作目录。
Terraform哈希值未更新:
检查var.PROJECT_DIR的实际值,确保filebase64sha256能正确读取到压缩包。如果路径错误,哈希值始终不变,Terraform会判定代码无变更。可以在plan阶段添加echo ${var.PROJECT_DIR}命令验证路径。不必要的import操作:
每次流水线执行terraform import会覆盖tfstate,干扰Terraform的变更追踪。如果资源已通过Terraform管理,应移除import阶段,仅在首次初始化时手动执行。阶段依赖问题:
package阶段的install_dependencies和build-dev-docker可能并行执行,导致依赖未安装完成就开始构建。可以让build-dev-docker依赖install_dependencies:build-dev-docker: # ... 其他配置 needs: [install_dependencies]
内容的提问来源于stack exchange,提问作者fairlyMinty

