Создайте образ Docker, загрузите его в ECR и используйте в функции Lambda

Это похоже на проблему курицы и яйца. Я пытаюсь создать образ Docker, добавить его в свой репозиторий ECR и использовать в функции Lambda с помощью CDK V2.

Вот мой код:

const repository = new ecr.Repository(this, `WorkerHelloRepository`, {
    repositoryName: `worker-hello`,
    imageTagMutability: ecr.TagMutability.IMMUTABLE,
    imageScanOnPush: true,
    removalPolicy: cdk.RemovalPolicy.DESTROY,
    lifecycleRules: [
    {
        description: 'Keeps a maximum number of images to minimize storage',
        maxImageCount: 10,
    },
    ],
});

const asset = new DockerImageAsset(this, `WorkerHelloDockerImageAsset`, {
    directory: path.join(__dirname, `../../../workers/hello`),
    buildArgs: {},
});

const destinationImageName = `${repository.repositoryUri}:${asset.assetHash}`;
new ecrdeploy.ECRDeployment(this, 'EcrDeployment', {
    src: new ecrdeploy.DockerImageName(asset.imageUri),
    dest: new ecrdeploy.DockerImageName(destinationImageName),
});

const lambdaFunction = new lambda.DockerImageFunction(this, `WorkerHelloFunction`, {
    code: lambda.DockerImageCode.fromEcr(repository, {
    tagOrDigest: asset.assetHash,
    cmd: ['index.newEntry'],
    }),
});

repository.grantPull(lambdaFunction);

lambdaFunction.addToRolePolicy(
    new cdk.aws_iam.PolicyStatement({
    actions: ['ecr:BatchGetImage', 'ecr:GetDownloadUrlForLayer'],
    resources: [repository.repositoryArn],
    effect: cdk.aws_iam.Effect.ALLOW,
    }),
);

Ошибка, возвращаемая CloudFormation, говорит о том, что изображение не существует:

4:05:35 AM | CREATE_FAILED        | AWS::Lambda::Function                 | workers-stack/work...orkerHelloFunction
Resource handler returned message: "Source image ***********.dkr.ecr.us-west-2.amazonaws.com/worker-hello:55106229314a459e2cf7fbfa14c2c03b728ffd20a70dad
3cf25ff51d7664abce does not exist. Provide a valid source image. (Service: Lambda, Status Code: 400, Request ID: 6ef7e839-ddb3-43c1-9170-c50865f6af70)" (Reques
tToken: be9bf05b-47e6-5239-da32-46cbe422853d, HandlerErrorCode: InvalidRequest)

Но когда я проверяю репозиторий ECR (который CloudFormation не может удалить, поскольку он не пуст), я вижу изображение и его URI верны.

Я попытался вручную добавить зависимость от функции Lambda к созданным активам, выполнив:

lambdaFunction.node.addDependency(asset);

Я почти уверен, что CDK достаточно умен, чтобы в любом случае обнаружить эту зависимость, и это не решило проблему.

Я действительно хочу избежать создания отдельного стека только для ECR, но думаю, это решит проблему. Чего я не пробовал, так это перемещать элементы ECR и ресурсы Lambda в два разных вложенных стека и добавлять зависимость от одного к другому, но я не понимаю, почему это будет работать лучше.

Есть идеи? Или хотя бы какие-нибудь рекомендации о том, как решить проблему курицы и яйца?


84
1

Ответ:

Решено

Ваша зависимость должна быть от развертывания ECR, а не от исходного актива (поскольку лямбда-выражение не использует актив напрямую).

Вы прошли большую часть пути, это должно сработать:

const deployment = new ecrdeploy.ECRDeployment(this, 'EcrDeployment', {
    src: new ecrdeploy.DockerImageName(asset.imageUri),
    dest: new ecrdeploy.DockerImageName(destinationImageName),
});

const lambdaFunction = new lambda.DockerImageFunction(this, `WorkerHelloFunction`, {
    code: lambda.DockerImageCode.fromEcr(repository, {
    tagOrDigest: asset.assetHash,
    cmd: ['index.newEntry'],
    }),
});

// Dependency on the deployment, not the asset
lambdaFunction.node.addDependency(deployment);