0
0

cdkでECRのイメージがpushされずlambda関数がそれを読み込めないエラー

Posted at

Envs

  "dependencies": {
    "@aws-cdk/aws-lambda": "^1.204.0",
    "@aws-cdk/aws-s3": "^1.204.0",
    "@aws-cdk/aws-s3-deployment": "^1.204.0",
    "@aws-cdk/core": "^1.204.0",
    "aws-cdk-lib": "2.126.0",
    "cdk-ecr-deployment": "^3.0.68",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.21"
  },

問題点

awsのcdkを使用し、別stackで定義したECRリポジトリにイメージをプッシュ、そしてlambda関数を作成するコードが動かなかった。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';
import { ECRDeployment, DockerImageName } from 'cdk-ecr-deployment';

interface LambdaDefineThemeStackProps extends cdk.StackProps {
  bucket: s3.Bucket;
  xxxLambdaArn: string;
}

export class LambdaDefineThemeStack extends cdk.Stack {
  constructor(
    scope: Construct,
    id: string,
    props: LambdaDefineThemeStackProps
  ) {
    super(scope, id, props);

    const bucket = props.bucket;
    const xxxLambdaArn = props.xxxLambdaArn;

    const repository = ecr.Repository.fromRepositoryName(
      this,
      'GetEcrRepository',
      'lambda-repository-define-theme'
    );

    const dockerAsset = new ecr_assets.DockerImageAsset(
      this,
      'LambdaDockerImageDefineTheme',
      {
        directory: 'runtime/define_theme',
      }
    );

    const awsAccount = 'xxxxxxxxxx';
    const tag = 'latest';
    new ECRDeployment(
      this,
      'DeployDockerImageDefineTheme',
      {
        src: new DockerImageName(dockerAsset.imageUri),
        dest: new DockerImageName(
          `${awsAccount}.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-repository-define-theme:${tag}`
        ),
      }
    );

    const lambdaDefineTheme = new lambda.DockerImageFunction(
      this,
      'LambdaFunctionDefineTheme',
      {
        code: lambda.DockerImageCode.fromEcr(repository, {
          tag: tag,
        }),
        architecture: lambda.Architecture.X86_64,
        timeout: cdk.Duration.seconds(30),
        environment: {
          BUCKET_NAME: bucket.bucketName,
          XXX_LAMBDA_ARN: xxxLambdaArn,
        },
      }
    );

    bucket.grantRead(lambdaDefineTheme);

    const lambdaInvokePolicy = new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: ['lambda:InvokeFunction'],
      resources: [xxxLambdaArn],
    });
    lambdaDefineTheme.addToRolePolicy(lambdaInvokePolicy);
  }
}
14:58:49 | CREATE_FAILED        | AWS::Lambda::Function       | LambdaFunctionDefineTheme0C0ABCFC
Resource handler returned message: "Source image xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-repository-define-theme:latest does not exist. Provide a valid source image. (Service: Lambda, St
atus Code: 400, Request ID: 870882f9-78ad-4544-a14b-f04f27599c5f)" (RequestToken: 4b5b394e-858c-724d-7273-75febbaacff5, HandlerErrorCode: InvalidRequest)

解決法

原因はイメージがプッシュされる前にLambda関数を作成しようと試みたため、イメージが存在せず、エラーになった。
そのため、イメージプッシュ後にLambda関数が作成されるように依存関係を設定する必要がある。
次のページが参考になった。

次の一文を追加するだけである。

lambdaDefineTheme.node.addDependency(ecrDeployment);

コードは次のようになる。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';
import { ECRDeployment, DockerImageName } from 'cdk-ecr-deployment';

interface LambdaDefineThemeStackProps extends cdk.StackProps {
  bucket: s3.Bucket;
  xxxLambdaArn: string;
}

export class LambdaDefineThemeStack extends cdk.Stack {
  constructor(
    scope: Construct,
    id: string,
    props: LambdaDefineThemeStackProps
  ) {
    super(scope, id, props);

    const bucket = props.bucket;
    const xxxLambdaArn = props.xxxLambdaArn;

    const repository = ecr.Repository.fromRepositoryName(
      this,
      'GetEcrRepository',
      'lambda-repository-define-theme'
    );

    const dockerAsset = new ecr_assets.DockerImageAsset(
      this,
      'LambdaDockerImageDefineTheme',
      {
        directory: 'runtime/define_theme',
      }
    );

    const awsAccount = 'xxxxxxxxxx';
    const tag = 'latest';
    // 返り値を定数に入れる
    const ecrDeployment = new ECRDeployment(
      this,
      'DeployDockerImageDefineTheme',
      {
        src: new DockerImageName(dockerAsset.imageUri),
        dest: new DockerImageName(
          `${awsAccount}.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-repository-define-theme:${tag}`
        ),
      }
    );

    const lambdaDefineTheme = new lambda.DockerImageFunction(
      this,
      'LambdaFunctionDefineTheme',
      {
        code: lambda.DockerImageCode.fromEcr(repository, {
          tag: tag,
        }),
        architecture: lambda.Architecture.X86_64,
        timeout: cdk.Duration.seconds(30),
        environment: {
          BUCKET_NAME: bucket.bucketName,
          XXX_LAMBDA_ARN: xxxLambdaArn,
        },
      }
    );

    lambdaDefineTheme.node.addDependency(ecrDeployment); // 追加

    bucket.grantRead(lambdaDefineTheme);

    const lambdaInvokePolicy = new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: ['lambda:InvokeFunction'],
      resources: [xxxLambdaArn],
    });
    lambdaDefineTheme.addToRolePolicy(lambdaInvokePolicy);
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0