move cdk folder to scripts/cdk
This commit is contained in:
parent
2730dbac82
commit
093d963a7c
20 changed files with 0 additions and 5445 deletions
|
|
@ -1,3 +0,0 @@
|
||||||
LANGFLOW_AUTO_LOGIN=false
|
|
||||||
LANGFLOW_SUPERUSER=langflow
|
|
||||||
LANGFLOW_SUPERUSER_PASSWORD=654321
|
|
||||||
9
deploy/scripts/cdk/.gitignore
vendored
9
deploy/scripts/cdk/.gitignore
vendored
|
|
@ -1,9 +0,0 @@
|
||||||
*.js
|
|
||||||
!jest.config.js
|
|
||||||
*.d.ts
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# CDK asset staging directory
|
|
||||||
.cdk.staging
|
|
||||||
cdk.out
|
|
||||||
!/lib
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
*.ts
|
|
||||||
!*.d.ts
|
|
||||||
|
|
||||||
# CDK asset staging directory
|
|
||||||
.cdk.staging
|
|
||||||
cdk.out
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# Welcome to your CDK TypeScript project
|
|
||||||
|
|
||||||
This is a blank project for CDK development with TypeScript.
|
|
||||||
|
|
||||||
The `cdk.json` file tells the CDK Toolkit how to execute your app.
|
|
||||||
|
|
||||||
## Useful commands
|
|
||||||
|
|
||||||
* `npm run build` compile typescript to js
|
|
||||||
* `npm run watch` watch for changes and compile
|
|
||||||
* `npm run test` perform the jest unit tests
|
|
||||||
* `cdk deploy` deploy this stack to your default AWS account/region
|
|
||||||
* `cdk diff` compare deployed stack with current state
|
|
||||||
* `cdk synth` emits the synthesized CloudFormation template
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
import 'source-map-support/register';
|
|
||||||
import * as cdk from 'aws-cdk-lib';
|
|
||||||
import { LangflowAppStack } from '../lib/cdk-stack';
|
|
||||||
|
|
||||||
const app = new cdk.App();
|
|
||||||
new LangflowAppStack(app, 'LangflowAppStack', {
|
|
||||||
/* If you don't specify 'env', this stack will be environment-agnostic.
|
|
||||||
* Account/Region-dependent features and context lookups will not work,
|
|
||||||
* but a single synthesized template can be deployed anywhere. */
|
|
||||||
|
|
||||||
/* Uncomment the next line to specialize this stack for the AWS Account
|
|
||||||
* and Region that are implied by the current CLI configuration. */
|
|
||||||
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
|
|
||||||
|
|
||||||
/* Uncomment the next line if you know exactly what Account and Region you
|
|
||||||
* want to deploy the stack to. */
|
|
||||||
// env: { account: '123456789012', region: 'us-east-1' },
|
|
||||||
|
|
||||||
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
|
|
||||||
});
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"app": "npx ts-node --prefer-ts-exts bin/cdk.ts",
|
|
||||||
"watch": {
|
|
||||||
"include": [
|
|
||||||
"**"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"README.md",
|
|
||||||
"cdk*.json",
|
|
||||||
"**/*.d.ts",
|
|
||||||
"**/*.js",
|
|
||||||
"tsconfig.json",
|
|
||||||
"package*.json",
|
|
||||||
"yarn.lock",
|
|
||||||
"node_modules",
|
|
||||||
"test"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"context": {
|
|
||||||
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
|
|
||||||
"@aws-cdk/core:checkSecretUsage": true,
|
|
||||||
"@aws-cdk/core:target-partitions": [
|
|
||||||
"aws",
|
|
||||||
"aws-cn"
|
|
||||||
],
|
|
||||||
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
|
|
||||||
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
|
|
||||||
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
|
|
||||||
"@aws-cdk/aws-iam:minimizePolicies": true,
|
|
||||||
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
|
|
||||||
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
|
|
||||||
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
|
|
||||||
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
|
|
||||||
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
|
|
||||||
"@aws-cdk/core:enablePartitionLiterals": true,
|
|
||||||
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
|
|
||||||
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
|
|
||||||
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
|
|
||||||
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
|
|
||||||
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
|
|
||||||
"@aws-cdk/aws-route53-patters:useCertificate": true,
|
|
||||||
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
|
|
||||||
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
|
|
||||||
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
|
|
||||||
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
|
|
||||||
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
|
|
||||||
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
|
|
||||||
"@aws-cdk/aws-redshift:columnId": true,
|
|
||||||
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
|
|
||||||
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
|
|
||||||
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
|
|
||||||
"@aws-cdk/aws-kms:aliasNameRef": true,
|
|
||||||
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
docker stop $(docker ps -aq)
|
|
||||||
docker rm $(docker ps -aq)
|
|
||||||
docker rmi -f $(docker images -aq)
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
# aws cloudformation delete-stack --stack-name LangflowAppStack
|
|
||||||
# aws ecr delete-repository --repository-name langflow-backend-repository --force
|
|
||||||
# aws ecr delete-repository --repository-name langflow-frontend-repository --force
|
|
||||||
# aws ecr describe-repositories --output json | jq -re ".repositories[].repositoryName"
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
testEnvironment: 'node',
|
|
||||||
roots: ['<rootDir>/test'],
|
|
||||||
testMatch: ['**/*.test.ts'],
|
|
||||||
transform: {
|
|
||||||
'^.+\\.tsx?$': 'ts-jest'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
import * as cdk from 'aws-cdk-lib';
|
|
||||||
import { Construct } from 'constructs';
|
|
||||||
import * as ecs from 'aws-cdk-lib/aws-ecs'
|
|
||||||
|
|
||||||
import { Network, EcrRepository, FrontEndCluster, BackEndCluster, Rds, EcsIAM } from './construct';
|
|
||||||
// import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
||||||
|
|
||||||
export class LangflowAppStack extends cdk.Stack {
|
|
||||||
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
||||||
super(scope, id, props);
|
|
||||||
// Arch
|
|
||||||
const arch = ecs.CpuArchitecture.X86_64
|
|
||||||
|
|
||||||
// VPC
|
|
||||||
const { vpc, cluster, alb, targetGroup, cloudmapNamespace, ecsFrontSG, ecsBackSG, dbSG, albSG, backendLogGroup, frontendLogGroup} = new Network(this, 'Network')
|
|
||||||
|
|
||||||
// ECR
|
|
||||||
const { ecrFrontEndRepository,ecrBackEndRepository} = new EcrRepository(this, 'Ecr', {
|
|
||||||
cloudmapNamespace:cloudmapNamespace,
|
|
||||||
arch:arch
|
|
||||||
})
|
|
||||||
|
|
||||||
// RDS
|
|
||||||
// VPCとSGのリソース情報をPropsとして引き渡す
|
|
||||||
const { rdsCluster } = new Rds(this, 'Rds', { vpc, dbSG })
|
|
||||||
|
|
||||||
// IAM
|
|
||||||
const { frontendTaskRole, frontendTaskExecutionRole, backendTaskRole, backendTaskExecutionRole } = new EcsIAM(this, 'EcsIAM',{
|
|
||||||
rdsCluster:rdsCluster
|
|
||||||
})
|
|
||||||
|
|
||||||
const backendService = new BackEndCluster(this, 'backend', {
|
|
||||||
cluster:cluster,
|
|
||||||
ecsBackSG:ecsBackSG,
|
|
||||||
ecrBackEndRepository:ecrBackEndRepository,
|
|
||||||
backendTaskRole:backendTaskRole,
|
|
||||||
backendTaskExecutionRole:backendTaskExecutionRole,
|
|
||||||
backendLogGroup:backendLogGroup,
|
|
||||||
cloudmapNamespace:cloudmapNamespace,
|
|
||||||
rdsCluster:rdsCluster,
|
|
||||||
alb:alb,
|
|
||||||
arch:arch
|
|
||||||
})
|
|
||||||
backendService.node.addDependency(rdsCluster);
|
|
||||||
|
|
||||||
const frontendService = new FrontEndCluster(this, 'frontend',{
|
|
||||||
cluster:cluster,
|
|
||||||
ecsFrontSG:ecsFrontSG,
|
|
||||||
ecrFrontEndRepository:ecrFrontEndRepository,
|
|
||||||
targetGroup: targetGroup,
|
|
||||||
backendServiceName: backendService.backendServiceName,
|
|
||||||
frontendTaskRole: frontendTaskRole,
|
|
||||||
frontendTaskExecutionRole: frontendTaskExecutionRole,
|
|
||||||
frontendLogGroup: frontendLogGroup,
|
|
||||||
cloudmapNamespace: cloudmapNamespace,
|
|
||||||
arch:arch
|
|
||||||
})
|
|
||||||
frontendService.node.addDependency(backendService);
|
|
||||||
|
|
||||||
|
|
||||||
// S3+CloudFront
|
|
||||||
// new Web(this,'Cloudfront-S3')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
import { Duration } from 'aws-cdk-lib'
|
|
||||||
import { Construct } from 'constructs';
|
|
||||||
import {
|
|
||||||
aws_ec2 as ec2,
|
|
||||||
aws_ecs as ecs,
|
|
||||||
aws_ecr as ecr,
|
|
||||||
aws_rds as rds,
|
|
||||||
aws_servicediscovery as servicediscovery,
|
|
||||||
aws_iam as iam,
|
|
||||||
aws_logs as logs,
|
|
||||||
aws_elasticloadbalancingv2 as elb,
|
|
||||||
} from 'aws-cdk-lib';
|
|
||||||
import * as dotenv from 'dotenv';
|
|
||||||
const path = require('path');
|
|
||||||
dotenv.config({path: path.join(__dirname, "../../.env")});
|
|
||||||
|
|
||||||
console.log(process.env.LANGFLOW_AUTO_LOGIN);
|
|
||||||
console.log(process.env.LANGFLOW_SUPERUSER);
|
|
||||||
console.log(process.env.LANGFLOW_SUPERUSER_PASSWORD);
|
|
||||||
|
|
||||||
interface BackEndProps {
|
|
||||||
cluster: ecs.Cluster
|
|
||||||
ecsBackSG:ec2.SecurityGroup
|
|
||||||
ecrBackEndRepository:ecr.Repository
|
|
||||||
backendTaskRole: iam.Role;
|
|
||||||
backendTaskExecutionRole: iam.Role;
|
|
||||||
backendLogGroup: logs.LogGroup;
|
|
||||||
cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
|
|
||||||
rdsCluster:rds.DatabaseCluster
|
|
||||||
alb:elb.IApplicationLoadBalancer
|
|
||||||
arch:ecs.CpuArchitecture
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BackEndCluster extends Construct {
|
|
||||||
readonly backendServiceName: string
|
|
||||||
|
|
||||||
constructor(scope: Construct, id: string, props:BackEndProps) {
|
|
||||||
super(scope, id)
|
|
||||||
const containerPort = 7860
|
|
||||||
// Secrets ManagerからDB認証情報を取ってくる
|
|
||||||
const secretsDB = props.rdsCluster.secret!;
|
|
||||||
|
|
||||||
// Create Backend Fargate Service
|
|
||||||
const backendTaskDefinition = new ecs.FargateTaskDefinition(
|
|
||||||
this,
|
|
||||||
'BackEndTaskDef',
|
|
||||||
{
|
|
||||||
memoryLimitMiB: 3072,
|
|
||||||
cpu: 1024,
|
|
||||||
executionRole: props.backendTaskExecutionRole,
|
|
||||||
runtimePlatform:{
|
|
||||||
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
|
|
||||||
cpuArchitecture: props.arch,
|
|
||||||
},
|
|
||||||
taskRole: props.backendTaskRole,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
backendTaskDefinition.addContainer('backendContainer', {
|
|
||||||
image: ecs.ContainerImage.fromEcrRepository(props.ecrBackEndRepository, "latest"),
|
|
||||||
containerName:'langflow-back-container',
|
|
||||||
logging: ecs.LogDriver.awsLogs({
|
|
||||||
streamPrefix: 'my-stream',
|
|
||||||
logGroup: props.backendLogGroup,
|
|
||||||
}),
|
|
||||||
environment:{
|
|
||||||
// user:pass@endpoint:port/dbname
|
|
||||||
// "LANGFLOW_DATABASE_URL" : `mysql+pymysql://${username}:${password}@${host}:3306/${dbname}`,
|
|
||||||
// "LANGFLOW_DATABASE_URL" : "sqlite:///./langflow.db",
|
|
||||||
// "LANGFLOW_LANGCHAIN_CACHE" : "SQLiteCache",
|
|
||||||
// "LANGFLOW_AUTO_LOGIN" : "false",
|
|
||||||
// "LANGFLOW_SUPERUSER" : "admin",
|
|
||||||
// "LANGFLOW_SUPERUSER_PASSWORD" : "1234567"
|
|
||||||
"LANGFLOW_AUTO_LOGIN" : process.env.LANGFLOW_AUTO_LOGIN ?? 'false',
|
|
||||||
"LANGFLOW_SUPERUSER" : process.env.LANGFLOW_SUPERUSER ?? "admin",
|
|
||||||
"LANGFLOW_SUPERUSER_PASSWORD" : process.env.LANGFLOW_SUPERUSER_PASSWORD ?? "123456"
|
|
||||||
},
|
|
||||||
portMappings: [
|
|
||||||
{
|
|
||||||
containerPort: containerPort,
|
|
||||||
protocol: ecs.Protocol.TCP,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// Secretの設定
|
|
||||||
secrets: {
|
|
||||||
"dbname": ecs.Secret.fromSecretsManager(secretsDB, 'dbname'),
|
|
||||||
"username": ecs.Secret.fromSecretsManager(secretsDB, 'username'),
|
|
||||||
"host": ecs.Secret.fromSecretsManager(secretsDB, 'host'),
|
|
||||||
"password": ecs.Secret.fromSecretsManager(secretsDB, 'password'),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.backendServiceName = 'backend'
|
|
||||||
const backendService = new ecs.FargateService(this, 'BackEndService', {
|
|
||||||
cluster: props.cluster,
|
|
||||||
serviceName: this.backendServiceName,
|
|
||||||
taskDefinition: backendTaskDefinition,
|
|
||||||
enableExecuteCommand: true,
|
|
||||||
securityGroups: [props.ecsBackSG],
|
|
||||||
cloudMapOptions: {
|
|
||||||
cloudMapNamespace: props.cloudmapNamespace,
|
|
||||||
containerPort: containerPort,
|
|
||||||
dnsRecordType: servicediscovery.DnsRecordType.A,
|
|
||||||
dnsTtl: Duration.seconds(10),
|
|
||||||
name: this.backendServiceName
|
|
||||||
},
|
|
||||||
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
import { Construct } from 'constructs';
|
|
||||||
import * as ec2 from 'aws-cdk-lib/aws-ec2'
|
|
||||||
import * as rds from "aws-cdk-lib/aws-rds";
|
|
||||||
|
|
||||||
interface RdsProps {
|
|
||||||
vpc: ec2.Vpc
|
|
||||||
dbSG:ec2.SecurityGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Rds extends Construct{
|
|
||||||
readonly rdsCluster: rds.DatabaseCluster
|
|
||||||
|
|
||||||
constructor(scope: Construct, id:string, props: RdsProps){
|
|
||||||
super(scope, id);
|
|
||||||
|
|
||||||
const {vpc, dbSG} = props
|
|
||||||
const instanceType = ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE4_GRAVITON, ec2.InstanceSize.MEDIUM)
|
|
||||||
|
|
||||||
// RDSのパスワードを自動生成してSecrets Managerに格納
|
|
||||||
const rdsCredentials = rds.Credentials.fromGeneratedSecret('db_user',{
|
|
||||||
secretName: 'langflow-DbSecret',
|
|
||||||
})
|
|
||||||
|
|
||||||
// DB クラスターのパラメータグループ作成
|
|
||||||
const clusterParameterGroup = new rds.ParameterGroup(scope, 'ClusterParameterGroup',{
|
|
||||||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
|
||||||
version: rds.AuroraMysqlEngineVersion.VER_3_02_0
|
|
||||||
}),
|
|
||||||
description: 'for-langflow',
|
|
||||||
})
|
|
||||||
clusterParameterGroup.bindToCluster({})
|
|
||||||
|
|
||||||
// DB インスタンスのパラメタグループ作成
|
|
||||||
const instanceParameterGroup = new rds.ParameterGroup(scope, 'InstanceParameterGroup',{
|
|
||||||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
|
||||||
version: rds.AuroraMysqlEngineVersion.VER_3_02_0,
|
|
||||||
}),
|
|
||||||
description: 'for-langflow',
|
|
||||||
})
|
|
||||||
instanceParameterGroup.bindToInstance({})
|
|
||||||
|
|
||||||
this.rdsCluster = new rds.DatabaseCluster(scope, 'LangflowDbCluster', {
|
|
||||||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
|
||||||
version: rds.AuroraMysqlEngineVersion.VER_3_02_0,
|
|
||||||
}),
|
|
||||||
storageEncrypted: true,
|
|
||||||
credentials: rdsCredentials,
|
|
||||||
instanceIdentifierBase: 'langflow-instance',
|
|
||||||
vpc:vpc,
|
|
||||||
vpcSubnets:vpc.selectSubnets({
|
|
||||||
subnetGroupName: 'langflow-Isolated',
|
|
||||||
}),
|
|
||||||
securityGroups:[dbSG],
|
|
||||||
writer: rds.ClusterInstance.provisioned("WriterInstance", {
|
|
||||||
instanceType: instanceType,
|
|
||||||
enablePerformanceInsights: true,
|
|
||||||
parameterGroup:instanceParameterGroup,
|
|
||||||
}),
|
|
||||||
// 2台目以降はreaders:で設定
|
|
||||||
parameterGroup: clusterParameterGroup,
|
|
||||||
defaultDatabaseName: 'langflow',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
import { RemovalPolicy } from 'aws-cdk-lib'
|
|
||||||
import * as ecr from 'aws-cdk-lib/aws-ecr'
|
|
||||||
import * as ecrdeploy from 'cdk-ecr-deployment'
|
|
||||||
import * as ecs from 'aws-cdk-lib/aws-ecs'
|
|
||||||
import * as servicediscovery from 'aws-cdk-lib/aws-servicediscovery'
|
|
||||||
import { DockerImageAsset, Platform } from 'aws-cdk-lib/aws-ecr-assets'
|
|
||||||
import * as path from "path";
|
|
||||||
import { Construct } from 'constructs'
|
|
||||||
|
|
||||||
|
|
||||||
interface ECRProps {
|
|
||||||
cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
|
|
||||||
arch:ecs.CpuArchitecture;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EcrRepository extends Construct {
|
|
||||||
readonly ecrFrontEndRepository: ecr.Repository
|
|
||||||
readonly ecrBackEndRepository: ecr.Repository
|
|
||||||
|
|
||||||
constructor(scope: Construct, id: string, props: ECRProps) {
|
|
||||||
super(scope, id)
|
|
||||||
|
|
||||||
const imagePlatform = props.arch == ecs.CpuArchitecture.ARM64 ? Platform.LINUX_ARM64 : Platform.LINUX_AMD64
|
|
||||||
const backendPath = path.join(__dirname, "../../../../../../", "langflow")
|
|
||||||
const frontendPath = path.join(__dirname, "../../../../../src/", "frontend")
|
|
||||||
const excludeDir = ['node_modules','.git', 'cdk.out']
|
|
||||||
const LifecycleRule = {
|
|
||||||
tagStatus: ecr.TagStatus.ANY,
|
|
||||||
description: 'Delete more than 30 image',
|
|
||||||
maxImageCount: 30,
|
|
||||||
}
|
|
||||||
|
|
||||||
// リポジトリ作成
|
|
||||||
this.ecrFrontEndRepository = new ecr.Repository(scope, 'LangflowFrontEndRepository', {
|
|
||||||
repositoryName: 'langflow-frontend-repository',
|
|
||||||
removalPolicy: RemovalPolicy.RETAIN,
|
|
||||||
imageScanOnPush: true,
|
|
||||||
})
|
|
||||||
this.ecrBackEndRepository = new ecr.Repository(scope, 'LangflowBackEndRepository', {
|
|
||||||
repositoryName: 'langflow-backend-repository',
|
|
||||||
removalPolicy: RemovalPolicy.RETAIN,
|
|
||||||
imageScanOnPush: true,
|
|
||||||
})
|
|
||||||
// LifecycleRule作成
|
|
||||||
this.ecrFrontEndRepository.addLifecycleRule(LifecycleRule)
|
|
||||||
this.ecrBackEndRepository.addLifecycleRule(LifecycleRule)
|
|
||||||
|
|
||||||
// Create Docker Image Asset
|
|
||||||
const dockerFrontEndImageAsset = new DockerImageAsset(this, "DockerFrontEndImageAsset", {
|
|
||||||
directory: frontendPath,
|
|
||||||
buildArgs:{
|
|
||||||
"BACKEND_URL":`http://backend.${props.cloudmapNamespace.namespaceName}:7860`
|
|
||||||
},
|
|
||||||
exclude: excludeDir,
|
|
||||||
platform: imagePlatform,
|
|
||||||
});
|
|
||||||
const dockerBackEndImageAsset = new DockerImageAsset(this, "DockerBackEndImageAsset", {
|
|
||||||
directory: backendPath,
|
|
||||||
exclude: excludeDir,
|
|
||||||
platform: imagePlatform,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Deploy Docker Image to ECR Repository
|
|
||||||
new ecrdeploy.ECRDeployment(this, "DeployFrontEndImage", {
|
|
||||||
src: new ecrdeploy.DockerImageName(dockerFrontEndImageAsset.imageUri),
|
|
||||||
dest: new ecrdeploy.DockerImageName(this.ecrFrontEndRepository.repositoryUri)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Deploy Docker Image to ECR Repository
|
|
||||||
new ecrdeploy.ECRDeployment(this, "DeployBackEndImage", {
|
|
||||||
src: new ecrdeploy.DockerImageName(dockerBackEndImageAsset.imageUri),
|
|
||||||
dest: new ecrdeploy.DockerImageName(this.ecrBackEndRepository.repositoryUri)
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
import { Duration } from 'aws-cdk-lib'
|
|
||||||
import { Construct } from 'constructs'
|
|
||||||
import {
|
|
||||||
aws_ec2 as ec2,
|
|
||||||
aws_ecs as ecs,
|
|
||||||
aws_ecr as ecr,
|
|
||||||
aws_servicediscovery as servicediscovery,
|
|
||||||
aws_iam as iam,
|
|
||||||
aws_logs as logs,
|
|
||||||
aws_elasticloadbalancingv2 as elb,
|
|
||||||
} from 'aws-cdk-lib';
|
|
||||||
import { CpuArchitecture } from 'aws-cdk-lib/aws-ecs';
|
|
||||||
|
|
||||||
interface FrontEndProps {
|
|
||||||
cluster:ecs.Cluster
|
|
||||||
ecsFrontSG:ec2.SecurityGroup
|
|
||||||
ecrFrontEndRepository:ecr.Repository
|
|
||||||
targetGroup: elb.ApplicationTargetGroup;
|
|
||||||
backendServiceName: string;
|
|
||||||
frontendTaskRole: iam.Role;
|
|
||||||
frontendTaskExecutionRole: iam.Role;
|
|
||||||
frontendLogGroup: logs.LogGroup;
|
|
||||||
cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
|
|
||||||
arch:ecs.CpuArchitecture;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FrontEndCluster extends Construct {
|
|
||||||
constructor(scope: Construct, id: string, props:FrontEndProps) {
|
|
||||||
super(scope, id)
|
|
||||||
|
|
||||||
const containerPort = 3000
|
|
||||||
const frontendTaskDefinition = new ecs.FargateTaskDefinition(
|
|
||||||
this,
|
|
||||||
'FrontendTaskDef',
|
|
||||||
{
|
|
||||||
memoryLimitMiB: 3072,
|
|
||||||
cpu: 1024,
|
|
||||||
executionRole: props.frontendTaskExecutionRole,
|
|
||||||
runtimePlatform:{
|
|
||||||
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
|
|
||||||
cpuArchitecture: props.arch,
|
|
||||||
},
|
|
||||||
taskRole: props.frontendTaskRole,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const frontendServiceName = 'frontend'
|
|
||||||
frontendTaskDefinition.addContainer('frontendContainer', {
|
|
||||||
image: ecs.ContainerImage.fromEcrRepository(props.ecrFrontEndRepository, "latest"),
|
|
||||||
containerName:'langflow-front-container',
|
|
||||||
environment: {
|
|
||||||
BACKEND_SERVICE_NAME: props.backendServiceName,
|
|
||||||
BACKEND_URL: `http://${props.backendServiceName}.${props.cloudmapNamespace.namespaceName}:7860/`,
|
|
||||||
VITE_PROXY_TARGET: `http://${props.backendServiceName}.${props.cloudmapNamespace.namespaceName}:7860/`,
|
|
||||||
},
|
|
||||||
logging: ecs.LogDriver.awsLogs({
|
|
||||||
streamPrefix: 'my-stream',
|
|
||||||
logGroup: props.frontendLogGroup,
|
|
||||||
}),
|
|
||||||
portMappings: [
|
|
||||||
{
|
|
||||||
name:frontendServiceName,
|
|
||||||
containerPort: containerPort,
|
|
||||||
protocol: ecs.Protocol.TCP,
|
|
||||||
appProtocol:ecs.AppProtocol.http,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
const frontendService = new ecs.FargateService(
|
|
||||||
this,
|
|
||||||
'FrontendService',
|
|
||||||
{
|
|
||||||
serviceName: frontendServiceName,
|
|
||||||
cluster: props.cluster,
|
|
||||||
desiredCount: 1,
|
|
||||||
assignPublicIp: false,
|
|
||||||
taskDefinition: frontendTaskDefinition,
|
|
||||||
enableExecuteCommand: true,
|
|
||||||
securityGroups: [props.ecsFrontSG],
|
|
||||||
cloudMapOptions: {
|
|
||||||
cloudMapNamespace: props.cloudmapNamespace,
|
|
||||||
containerPort: containerPort,
|
|
||||||
dnsRecordType: servicediscovery.DnsRecordType.A,
|
|
||||||
dnsTtl: Duration.seconds(10),
|
|
||||||
name: frontendServiceName
|
|
||||||
},
|
|
||||||
healthCheckGracePeriod: Duration.seconds(1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
props.targetGroup.addTarget(frontendService);
|
|
||||||
|
|
||||||
// // Create ALB and ECS Fargate Service
|
|
||||||
// const frontService = new ecs_patterns.ApplicationLoadBalancedFargateService(
|
|
||||||
// this,
|
|
||||||
// "FrontEndService",
|
|
||||||
// {
|
|
||||||
// cluster: cluster,
|
|
||||||
// serviceName: 'langflow-frontend-service',
|
|
||||||
// cpu: 256,
|
|
||||||
// memoryLimitMiB: 512,
|
|
||||||
// listenerPort: 80,
|
|
||||||
// assignPublicIp: true, // Public facing - ALB
|
|
||||||
// taskSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
||||||
// securityGroups:[ecsFrontSG],
|
|
||||||
// taskImageOptions: {
|
|
||||||
// family: 'langflow-taskdef',
|
|
||||||
// containerName: 'langflow-front-container',
|
|
||||||
// image: ecs.ContainerImage.fromEcrRepository(ecrFrontEndRepository, "latest"),
|
|
||||||
// containerPort: 3000, // L2なので、TargetGroupのportが3000で設定されるはず
|
|
||||||
// },
|
|
||||||
// loadBalancer:alb,
|
|
||||||
// openListener:false,
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
import { RemovalPolicy, Duration } from 'aws-cdk-lib'
|
|
||||||
import { Construct } from 'constructs'
|
|
||||||
import {
|
|
||||||
aws_rds as rds,
|
|
||||||
aws_iam as iam,
|
|
||||||
} from 'aws-cdk-lib';
|
|
||||||
|
|
||||||
interface IAMProps {
|
|
||||||
rdsCluster:rds.DatabaseCluster
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EcsIAM extends Construct {
|
|
||||||
readonly frontendTaskRole: iam.Role;
|
|
||||||
readonly frontendTaskExecutionRole: iam.Role;
|
|
||||||
readonly backendTaskRole: iam.Role;
|
|
||||||
readonly backendTaskExecutionRole: iam.Role;
|
|
||||||
|
|
||||||
constructor(scope: Construct, id: string, props:IAMProps) {
|
|
||||||
super(scope, id)
|
|
||||||
|
|
||||||
// Policy Statements
|
|
||||||
// ECS Policy State
|
|
||||||
const ECSExecPolicyStatement = new iam.PolicyStatement({
|
|
||||||
sid: 'allowECSExec',
|
|
||||||
resources: ['*'],
|
|
||||||
actions: [
|
|
||||||
'ecr:GetAuthorizationToken',
|
|
||||||
'ecr:BatchCheckLayerAvailability',
|
|
||||||
'ecr:GetDownloadUrlForLayer',
|
|
||||||
'ecr:BatchGetImage',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
// Bedrock Policy State
|
|
||||||
const BedrockPolicyStatement = new iam.PolicyStatement({
|
|
||||||
sid: 'allowBedrockAccess',
|
|
||||||
resources: ['*'],
|
|
||||||
actions: [
|
|
||||||
'bedrock:*',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
// Kendra Policy State
|
|
||||||
const KendraPolicyStatement = new iam.PolicyStatement({
|
|
||||||
sid: 'allowKendraAccess',
|
|
||||||
resources: ['*'],
|
|
||||||
actions: [
|
|
||||||
'kendra:*'
|
|
||||||
],
|
|
||||||
});
|
|
||||||
// Create Rag Policy
|
|
||||||
const RagAccessPolicy = new iam.Policy(this, 'RAGFullAccess', {
|
|
||||||
statements: [KendraPolicyStatement,BedrockPolicyStatement],
|
|
||||||
})
|
|
||||||
// Secrets ManagerからDB認証情報を取ってくるためのPolicy
|
|
||||||
const SecretsManagerPolicy = new iam.Policy(this, 'SMGetPolicy', {
|
|
||||||
statements: [new iam.PolicyStatement({
|
|
||||||
actions: ['secretsmanager:GetSecretValue'],
|
|
||||||
resources: [props.rdsCluster.secret!.secretArn],
|
|
||||||
})],
|
|
||||||
})
|
|
||||||
|
|
||||||
// FrontEnd Task Role
|
|
||||||
this.frontendTaskRole = new iam.Role(this, 'FrontendTaskRole', {
|
|
||||||
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
|
|
||||||
});
|
|
||||||
this.frontendTaskRole.addToPolicy(ECSExecPolicyStatement);
|
|
||||||
|
|
||||||
// BackEnd Task Role
|
|
||||||
this.backendTaskRole = new iam.Role(this, 'BackendTaskRole', {
|
|
||||||
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
|
|
||||||
});
|
|
||||||
// ECS Exec Policyの付与
|
|
||||||
this.backendTaskRole.addToPolicy(ECSExecPolicyStatement);
|
|
||||||
// KendraとBedrockのアクセス権付与
|
|
||||||
this.backendTaskRole.attachInlinePolicy(RagAccessPolicy);
|
|
||||||
|
|
||||||
// FrontEnd Task ExecutionRole
|
|
||||||
this.frontendTaskExecutionRole = new iam.Role(this, 'frontendTaskExecutionRole', {
|
|
||||||
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
|
|
||||||
managedPolicies: [
|
|
||||||
{
|
|
||||||
managedPolicyArn:
|
|
||||||
'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// BackEnd Task ExecutionRole
|
|
||||||
this.backendTaskExecutionRole = new iam.Role(this, 'backendTaskExecutionRole', {
|
|
||||||
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
|
|
||||||
managedPolicies: [
|
|
||||||
{
|
|
||||||
managedPolicyArn:
|
|
||||||
'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
this.backendTaskExecutionRole.attachInlinePolicy(SecretsManagerPolicy);
|
|
||||||
this.backendTaskExecutionRole.attachInlinePolicy(RagAccessPolicy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
export * from './db';
|
|
||||||
export * from './ecr';
|
|
||||||
export * from './iam';
|
|
||||||
export * from './frontend';
|
|
||||||
export * from './backend';
|
|
||||||
export * from './network';
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
import { RemovalPolicy, Duration } from 'aws-cdk-lib'
|
|
||||||
import { Construct } from 'constructs'
|
|
||||||
import {
|
|
||||||
aws_ec2 as ec2,
|
|
||||||
aws_ecs as ecs,
|
|
||||||
aws_logs as logs,
|
|
||||||
aws_servicediscovery as servicediscovery,
|
|
||||||
aws_elasticloadbalancingv2 as elb,
|
|
||||||
} from 'aws-cdk-lib';
|
|
||||||
|
|
||||||
export class Network extends Construct {
|
|
||||||
readonly vpc: ec2.Vpc;
|
|
||||||
readonly cluster: ecs.Cluster;
|
|
||||||
readonly alb: elb.IApplicationLoadBalancer;
|
|
||||||
readonly targetGroup: elb.ApplicationTargetGroup;
|
|
||||||
readonly cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
|
|
||||||
readonly ecsFrontSG: ec2.SecurityGroup;
|
|
||||||
readonly ecsBackSG: ec2.SecurityGroup;
|
|
||||||
readonly dbSG: ec2.SecurityGroup;
|
|
||||||
readonly albSG: ec2.SecurityGroup;
|
|
||||||
readonly backendLogGroup: logs.LogGroup;
|
|
||||||
readonly frontendLogGroup: logs.LogGroup;
|
|
||||||
|
|
||||||
constructor(scope: Construct, id: string) {
|
|
||||||
super(scope, id)
|
|
||||||
const alb_listen_port=80
|
|
||||||
const front_service_port=3000
|
|
||||||
const back_service_port=7860
|
|
||||||
|
|
||||||
// VPC等リソースの作成
|
|
||||||
this.vpc = new ec2.Vpc(scope, 'VPC', {
|
|
||||||
vpcName: 'langflow-vpc',
|
|
||||||
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
|
|
||||||
maxAzs: 3,
|
|
||||||
subnetConfiguration: [
|
|
||||||
{
|
|
||||||
cidrMask: 24,
|
|
||||||
name: 'langflow-Isolated',
|
|
||||||
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cidrMask: 24,
|
|
||||||
name: 'langflow-Public',
|
|
||||||
subnetType: ec2.SubnetType.PUBLIC,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cidrMask: 24,
|
|
||||||
name: 'langflow-Private',
|
|
||||||
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS
|
|
||||||
},
|
|
||||||
],
|
|
||||||
natGateways: 1,
|
|
||||||
})
|
|
||||||
// Cluster
|
|
||||||
this.cluster = new ecs.Cluster(this, 'EcsCluster', {
|
|
||||||
clusterName: 'langflow-cluster',
|
|
||||||
vpc: this.vpc,
|
|
||||||
enableFargateCapacityProviders: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Private DNS
|
|
||||||
this.cloudmapNamespace = new servicediscovery.PrivateDnsNamespace(
|
|
||||||
this,
|
|
||||||
'Namespace',
|
|
||||||
{
|
|
||||||
name: 'ecs-deploy.com',
|
|
||||||
vpc: this.vpc,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// ALBに設定するセキュリティグループ
|
|
||||||
this.albSG = new ec2.SecurityGroup(scope, 'ALBSecurityGroup', {
|
|
||||||
securityGroupName: 'alb-sg',
|
|
||||||
description: 'for alb',
|
|
||||||
vpc: this.vpc,
|
|
||||||
})
|
|
||||||
this.albSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(alb_listen_port))
|
|
||||||
|
|
||||||
this.alb = new elb.ApplicationLoadBalancer(this,'alb',{
|
|
||||||
internetFacing: true, //インターネットからのアクセスを許可するかどうか指定
|
|
||||||
loadBalancerName: 'alb',
|
|
||||||
securityGroup: this.albSG, //作成したセキュリティグループを割り当てる
|
|
||||||
vpc:this.vpc,
|
|
||||||
})
|
|
||||||
|
|
||||||
const listener = this.alb.addListener('Listener', { port: alb_listen_port });
|
|
||||||
|
|
||||||
this.targetGroup = listener.addTargets('targetGroup', {
|
|
||||||
port: front_service_port,
|
|
||||||
protocol: elb.ApplicationProtocol.HTTP,
|
|
||||||
healthCheck: {
|
|
||||||
enabled: true,
|
|
||||||
path: '/health',
|
|
||||||
healthyThresholdCount: 2,
|
|
||||||
unhealthyThresholdCount: 4,
|
|
||||||
interval: Duration.seconds(100),
|
|
||||||
timeout: Duration.seconds(30),
|
|
||||||
healthyHttpCodes: '200',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// ECS FrontEndに設定するセキュリティグループ
|
|
||||||
this.ecsFrontSG = new ec2.SecurityGroup(scope, 'ECSFrontEndSecurityGroup', {
|
|
||||||
securityGroupName: 'langflow-ecs-front-sg',
|
|
||||||
description: 'for langflow-front-ecs',
|
|
||||||
vpc: this.vpc,
|
|
||||||
})
|
|
||||||
this.ecsFrontSG.addIngressRule(this.albSG, ec2.Port.allTcp())
|
|
||||||
|
|
||||||
// ECS BackEndに設定するセキュリティグループ
|
|
||||||
this.ecsBackSG = new ec2.SecurityGroup(scope, 'ECSBackEndSecurityGroup', {
|
|
||||||
securityGroupName: 'langflow-ecs-back-sg',
|
|
||||||
description: 'for langflow-back-ecs',
|
|
||||||
vpc: this.vpc,
|
|
||||||
})
|
|
||||||
this.ecsBackSG.addIngressRule(this.ecsFrontSG, ec2.Port.tcp(back_service_port))
|
|
||||||
|
|
||||||
// RDSに設定するセキュリティグループ
|
|
||||||
this.dbSG = new ec2.SecurityGroup(scope, 'DBSecurityGroup', {
|
|
||||||
allowAllOutbound: true,
|
|
||||||
securityGroupName: 'langflow-db',
|
|
||||||
description: 'for langflow-db',
|
|
||||||
vpc: this.vpc,
|
|
||||||
})
|
|
||||||
// AppRunnerSecurityGroupからのポート3306:mysql(5432:postgres)のインバウンドを許可
|
|
||||||
this.dbSG.addIngressRule(this.ecsBackSG, ec2.Port.tcp(3306))
|
|
||||||
|
|
||||||
// Create CloudWatch Log Group
|
|
||||||
this.backendLogGroup = new logs.LogGroup(this, 'backendLogGroup', {
|
|
||||||
logGroupName: 'myapp-backend',
|
|
||||||
removalPolicy: RemovalPolicy.DESTROY,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.frontendLogGroup = new logs.LogGroup(this, 'frontendLogGroup', {
|
|
||||||
logGroupName: 'myapp-frontend',
|
|
||||||
removalPolicy: RemovalPolicy.DESTROY,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
4601
deploy/scripts/cdk/package-lock.json
generated
4601
deploy/scripts/cdk/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"name": "cdk",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"bin": {
|
|
||||||
"cdk": "bin/cdk.js"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"watch": "tsc -w",
|
|
||||||
"test": "jest",
|
|
||||||
"cdk": "cdk"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/jest": "^29.5.1",
|
|
||||||
"@types/node": "20.1.7",
|
|
||||||
"aws-cdk": "2.86.0",
|
|
||||||
"jest": "^29.5.0",
|
|
||||||
"ts-jest": "^29.1.0",
|
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"typescript": "~5.1.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"aws-cdk-lib": "^2.86.0",
|
|
||||||
"cdk-ecr-deployment": "^2.5.30",
|
|
||||||
"constructs": "^10.0.0",
|
|
||||||
"source-map-support": "^0.5.21"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// import * as cdk from 'aws-cdk-lib';
|
|
||||||
// import { Template } from 'aws-cdk-lib/assertions';
|
|
||||||
// import * as Cdk from '../lib/cdk-stack';
|
|
||||||
|
|
||||||
// example test. To run these tests, uncomment this file along with the
|
|
||||||
// example resource in lib/cdk-stack.ts
|
|
||||||
test('SQS Queue Created', () => {
|
|
||||||
// const app = new cdk.App();
|
|
||||||
// // WHEN
|
|
||||||
// const stack = new Cdk.CdkStack(app, 'MyTestStack');
|
|
||||||
// // THEN
|
|
||||||
// const template = Template.fromStack(stack);
|
|
||||||
|
|
||||||
// template.hasResourceProperties('AWS::SQS::Queue', {
|
|
||||||
// VisibilityTimeout: 300
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue