![](/img/trans.png)
[英]Running AWS CDK custom resource for database setup after RDS instance is created
[英]How to run Fargate task after database instance is created with AWS CDK?
我有一个 AWS CDK 堆栈,它从 docker 容器创建一个 Fargate 任务(使用ApplicationLoadBalancedFargateService
)。 容器是连接到数据库的 Web 应用程序。 当我部署 CDK 堆栈时,创建一个数据库实例需要 7 分钟。 但是,Fargate 任务启动得更快,因此该任务因无法连接到数据库而停止(因为尚未创建)。 然后它尝试再次启动任务,失败并停止。 这样重复四次,直到创建数据库。
问题:有没有办法在 CDK 代码中将 Fargate 任务的启动延迟到数据库创建完成?
这是 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
});
}
}
如果你想在fargate之前运行数据库,你应该做一些事情让fargate依赖于数据库。 就我而言,我只是在下面做一个技巧。
首先,将数据库声明为 const
const database = new DatabaseInstance(this, `${stackPrefix}DatabaseInstance`, {
...
然后,在定义 Fargate 服务时在某处调用数据库变量。
例子:
webTaskDefinition.addContainer(`${stackPrefix}Container`, {
image: image,
portMappings: [{ containerPort: 80 }],
secrets: {
...
TRICK: database.endpoint // or something like this, Idk exactly grammar
},
logging: webLogging,
});
希望它可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.