[英]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.