Создайте образ 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 в два разных вложенных стека и добавлять зависимость от одного к другому, но я не понимаю, почему это будет работать лучше.

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

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
0
84
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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);

В итоге я разделил ECR и сборку, а также ресурсы Lambda на отдельные вложенные стеки и объявил зависимость стека Lambda от стека ECR, и это сработало! На самом деле это стало немного чище, поскольку каждый стек теперь имеет свою собственную область видимости. Хотя я не могу поверить, что был так близко! Спасибо за ответ!

Philippe CARLE 03.05.2024 17:46

Другие вопросы по теме