Search code examples
amazon-ecsaws-amplifyaws-cdkamazon-ecramazon-kinesis-video-streams

How to deploy the kinesis-video-producer Docker image from AWS's own ECR to Fargate using CDK in TypeScript?


I'm trying to stand up a proof of concept that ingests an RTSP video stream into Kinesis Video. The provided documentation has a docker image all set up that seems to have everything I need to do this, hosted by AWS on 546150905175.dkr.ecr.us-west-2.amazonaws.com. What I am having trouble with, though, is getting that deployment (via an Amplify Custom category, in TypeScript CDK) to work.

I've tried different variations on

import * as iam from "@aws-cdk/aws-iam";
import * as ecs from "@aws-cdk/aws-ecs";
import * as ec2 from "@aws-cdk/aws-ec2";

const kinesisUserAccessKey = new iam.AccessKey(this, 'KinesisStreamUserAccessKey', {
    user: kinesisStreamUser,
})

const servicePrincipal = new iam.ServicePrincipal('ecs-tasks.amazonaws.com');
const executionRole = new iam.Role(this, 'IngestVideoTaskDefExecutionRole', {
    assumedBy: servicePrincipal,
    managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'),
    ]
});

const taskDefinition = new ecs.FargateTaskDefinition(this, 'IngestVideoTaskDef', {
    cpu: 512,
    memoryLimitMiB: 1024,
    executionRole,
})

const image = ecs.ContainerImage.fromRegistry('546150905175.dkr.ecr.us-west-2.amazonaws.com/kinesis-video-producer-sdk-cpp-amazon-linux:latest');

taskDefinition.addContainer('IngestVideoContainer', {
    command: [
        'gst-launch-1.0',
        'rtspsrc',
        `location="${locationParam.secretValue.toString()}"`,
        'short-header=TRUE',
        '!',
        'rtph264depay',
        '!',
        'video/x-h264,',
        'format=avc,alignment=au',
        '!',
        'kvssink',
        `stream-name="${cfnStream.name}"`,
        'storage-size=512',
        `access-key="${kinesisUserAccessKey.accessKeyId}"`,
        `secret-key="${kinesisUserAccessKey.secretAccessKey.toString()}"`,
        `aws-region="${REGION}"`,
        // `aws-region="${cdk.Aws.REGION}"`,
    ],
    image,
    logging: new ecs.AwsLogDriver({
        streamPrefix: 'IngestVideoContainer',
    }),
})

const service = new ecs.FargateService(this, 'IngestVideoService', {
    cluster,
    taskDefinition,
    desiredCount: 1,
    securityGroups: [
        ec2.SecurityGroup.fromSecurityGroupId(this, 'DefaultSecurityGroup', SECURITY_GROUP_ID)
    ],
    vpcSubnets: {
        subnets: SUBNET_IDS.map(subnetId => ec2.Subnet.fromSubnetId(this, subnetId, subnetId)),
    }
})

But it seems like regardless of what I do, an amplify push just stays in 'in progress' for like an hour until I go into the CloudFormation console and cancel the stack update, but deep in the my way to the ECS Console I managed to find an actual error message:

Resourceinitializationerror: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 3 time(s): RequestError: send request failed caused by: Post "https://api.ecr.us-west-2.amazonaws.com/": dial tcp 52.94.177.118:443: i/o timeout

It seems to be some kind of networking issue, but I'm not sure how to proceed. Any assistance you can provide would be wonderful. Cheers!


Solution

  • Figured it out. For those stuck with similar issues, you have to give it an execution role with AmazonECSTaskExecutionRolePolicy, which I already edited above, and set assignPublicIp: true in the service.