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

Terraform+GitLab CI/CD更新AWS Lambda代码失败求助

问题:GitLab CI/CD+Terraform更新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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:42:11