简体   繁体   English

使用 AWS CDK 创建数据库实例后如何运行 Fargate 任务?

[英]How to run Fargate task after database instance is created with AWS CDK?

I have a AWS CDK stack that creates a Fargate task (with ApplicationLoadBalancedFargateService ) from a docker container.我有一个 AWS CDK 堆栈,它从 docker 容器创建一个 Fargate 任务(使用ApplicationLoadBalancedFargateService )。 The container is a web app that connects to database.容器是连接到数据库的 Web 应用程序。 When I deploy the CDK stack, it takes seven minutes to create a database instance.当我部署 CDK 堆栈时,创建一个数据库实例需要 7 分钟。 However, the Fargate task is launched quicker, so the task is stopped because it can not connect to database (because is has not been created yet).但是,Fargate 任务启动得更快,因此该任务因无法连接到数据库而停止(因为尚未创建)。 Then it tries to start the task again, fails and stops.然后它尝试再次启动任务,失败并停止。 This repeats four times, until the database is created.这样重复四次,直到创建数据库。

Question: is there a way to delay the staring of the Fargate task until the database is creation is finished in the CDK code?问题:有没有办法在 CDK 代码中将 Fargate 任务的启动延迟到数据库创建完成?

Here is the CDK code, I'm using version 2.30.0 of the aws-cdk library.这是 CDK 代码,我使用的是aws-cdk库的 2.30.0 版本。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';
import * as secretManager from "aws-cdk-lib/aws-secretsmanager";
import { Credentials, DatabaseInstance, DatabaseInstanceEngine, DatabaseSecret, PostgresEngineVersion } from 'aws-cdk-lib/aws-rds';
import { SecurityGroup } from 'aws-cdk-lib/aws-ec2';

export class RailsEcsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const stackPrefix = 'PgRails'

    const vpc = new ec2.Vpc(this, `${stackPrefix}VPC`, {
      maxAzs: 3,
      subnetConfiguration: [
        {
          name: 'Public',
          subnetType: ec2.SubnetType.PUBLIC,
          cidrMask: 28,
        },
        {
          name: 'Private',
          subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
          cidrMask: 24,
        },
        {
          name: 'Isolated',
          subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
          cidrMask: 28,
        },
      ],
    });


    // Security groups
    // ------------

    // Fargate security group
    const fargateSecurityGroup = new SecurityGroup(this, `${stackPrefix}FargateSecurityGroup`, { vpc })

    // Database security group
    const databaseSecurityGroup = new SecurityGroup(this, `${stackPrefix}DatabaseSecurityGroup`, {
      vpc,
      allowAllOutbound: false
    });

    databaseSecurityGroup.addIngressRule(
      fargateSecurityGroup,
      ec2.Port.tcp(5432),
      'Permit the database to accept requests from the fargate service'
    );


    // Database
    // -----------

    const databaseSecret = new DatabaseSecret(this, `${stackPrefix}DatabaseSecret`, {
      username: 'postgres',
    });

    new DatabaseInstance(this, `${stackPrefix}DatabaseInstance`, {
      vpc,
      securityGroups: [databaseSecurityGroup],
      engine: DatabaseInstanceEngine.postgres({
        version: PostgresEngineVersion.VER_14_2,
      }),
      removalPolicy: cdk.RemovalPolicy.DESTROY, // CHANGE TO .SNAPSHOT FOR PRODUCTION !!!!!!!!!!!!!!!!!!!!!!
      credentials: Credentials.fromSecret(databaseSecret),
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO),
      vpcSubnets: {
        subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      },
      backupRetention: cdk.Duration.days(7),
      allocatedStorage: 10,
      maxAllocatedStorage: 30,
      databaseName: 'rails_postgres_production',
    });


    // Fargate service
    // ------------

    const repo = ecr.Repository.fromRepositoryName(this, 'pg_rails_docker', 'pg_rails_docker');
    const image =  ecs.ContainerImage.fromEcrRepository(repo, 'latest');
    const cluster = new ecs.Cluster(this, "DataCluster", { vpc });
    const mySecret = secretManager.Secret.fromSecretNameV2(this, 'MySecret', 'MySecret');

    const webLogging = new ecs.AwsLogDriver({
      streamPrefix: "my_pg_rails",
    })

    const webTaskDefinition = new ecs.FargateTaskDefinition(this, `${stackPrefix}FargateTask`, {
      cpu: 256,
      memoryLimitMiB: 512,
      runtimePlatform: {
        operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
        cpuArchitecture: ecs.CpuArchitecture.ARM64
      },
    });

    webTaskDefinition.addContainer(`${stackPrefix}Container`, {
      image: image,
      portMappings: [{ containerPort: 80 }],
      secrets: {
        RDS_HOSTNAME: ecs.Secret.fromSecretsManager(databaseSecret, 'host'),
        RDS_PORT: ecs.Secret.fromSecretsManager(databaseSecret, 'port'),
        RDS_USERNAME: ecs.Secret.fromSecretsManager(databaseSecret, 'username'),
        RDS_PASSWORD: ecs.Secret.fromSecretsManager(databaseSecret, 'password'),
        TRIST: ecs.Secret.fromSecretsManager(mySecret, 'TRIST')
      },
      logging: webLogging,
    });

    new ecsp.ApplicationLoadBalancedFargateService(this, `${stackPrefix}WebServer`, {
      cluster: cluster,
      taskDefinition: webTaskDefinition,
      securityGroups: [fargateSecurityGroup],
      publicLoadBalancer: true
    });
  }
}

if you want to database run before fargate, you should do something to make fargate depends on database.如果你想在fargate之前运行数据库,你应该做一些事情让fargate依赖于数据库。 In my case, I just do below for a trick.就我而言,我只是在下面做一个技巧。

First, declare database as const首先,将数据库声明为 const

const database = new DatabaseInstance(this, `${stackPrefix}DatabaseInstance`, {
...

Then, call database variable somewhere when define fargate service.然后,在定义 Fargate 服务时在某处调用数据库变量。

example:例子:

webTaskDefinition.addContainer(`${stackPrefix}Container`, {
      image: image,
      portMappings: [{ containerPort: 80 }],
      secrets: {
        ...
        TRICK: database.endpoint // or something like this, Idk exactly grammar

      },
      logging: webLogging,
    });

Hope it can help!希望它可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在创建 RDS 实例后运行 AWS CDK 自定义资源以进行数据库设置 - Running AWS CDK custom resource for database setup after RDS instance is created AWS CDK EcsDeployAction 更新现有 Fargate 服务 - AWS CDK EcsDeployAction update existing Fargate Service 如何从 AWS CDK 开始在 ASG EC2 实例上运行命令 - How do you run commands on ASG EC2 instance start from AWS CDK 如何在 fargate 计划任务的 nodejs 应用程序中使用 AWS IAM - How to use AWS IAM in nodejs application on fargate scheduled task 从 AWS CDK 中的 Fargate 集群获取所有服务 - Get all Services from a Fargate Cluster in AWS CDK 如何让 CDK 仅创建一个弹性 IP 地址以用于单个 EC2 实例 (AWS CDK) - How to have the CDK create only one Elastic IP address for use with a single EC2 instance (AWS CDK) 使用 aws cdk 创建 elasticbeanstalk 实例 - Using aws cdk to create elasticbeanstalk instance AWS CDK 步骤 Function 任务 - 在 DynamoPutItem 任务中包含对象列表 - AWS CDK Step Function Task - Include list of objects in DynamoPutItem task cfn 模板和管道都是使用 AWS CDK 创建的,如何使用 CodePipeline 部署 CloudFormation 堆栈? - How to deploy a CloudFormation stack using CodePipeline when both, the cfn template and the pipeline where created using the AWS CDK? 导出 ECS Fargate 容器的 TaskID 并稍后在 AWS CDK 代码中使用它 - Exporting TaskID of ECS Fargate container and use it later point in AWS CDK code
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM