-
-
Save MrHertal/549b31a18e350b69c7200ae8d26ed691 to your computer and use it in GitHub Desktop.
AWSTemplateFormatVersion: "2010-09-09" | |
Description: This template creates resources for Flowise application | |
Parameters: | |
Stage: | |
Description: Prefix of resource names | |
Type: String | |
Default: flowise | |
Mappings: | |
SubnetConfig: | |
VPC: | |
CIDR: "10.0.0.0/16" | |
PublicOne: | |
CIDR: "10.0.0.0/24" | |
PublicTwo: | |
CIDR: "10.0.1.0/24" | |
PrivateOne: | |
CIDR: "10.0.2.0/24" | |
PrivateTwo: | |
CIDR: "10.0.3.0/24" | |
Resources: | |
#### | |
# VPC related resources | |
#### | |
VPC: | |
Type: AWS::EC2::VPC | |
Properties: | |
EnableDnsSupport: true | |
EnableDnsHostnames: true | |
CidrBlock: !FindInMap ["SubnetConfig", "VPC", "CIDR"] | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, vpc]] | |
PublicSubnetOne: | |
Type: AWS::EC2::Subnet | |
Properties: | |
AvailabilityZone: !Select | |
- 0 | |
- Fn::GetAZs: !Ref "AWS::Region" | |
VpcId: !Ref "VPC" | |
CidrBlock: !FindInMap ["SubnetConfig", "PublicOne", "CIDR"] | |
MapPublicIpOnLaunch: true | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, public-subnet-one]] | |
PublicSubnetTwo: | |
Type: AWS::EC2::Subnet | |
Properties: | |
AvailabilityZone: !Select | |
- 1 | |
- Fn::GetAZs: !Ref "AWS::Region" | |
VpcId: !Ref "VPC" | |
CidrBlock: !FindInMap ["SubnetConfig", "PublicTwo", "CIDR"] | |
MapPublicIpOnLaunch: true | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, public-subnet-two]] | |
PrivateSubnetOne: | |
Type: AWS::EC2::Subnet | |
Properties: | |
AvailabilityZone: !Select | |
- 0 | |
- Fn::GetAZs: !Ref "AWS::Region" | |
VpcId: !Ref "VPC" | |
CidrBlock: !FindInMap ["SubnetConfig", "PrivateOne", "CIDR"] | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, private-subnet-one]] | |
PrivateSubnetTwo: | |
Type: AWS::EC2::Subnet | |
Properties: | |
AvailabilityZone: !Select | |
- 1 | |
- Fn::GetAZs: !Ref "AWS::Region" | |
VpcId: !Ref "VPC" | |
CidrBlock: !FindInMap ["SubnetConfig", "PrivateTwo", "CIDR"] | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, private-subnet-two]] | |
InternetGateway: | |
Type: AWS::EC2::InternetGateway | |
Properties: | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, igw]] | |
GatewayAttachement: | |
Type: AWS::EC2::VPCGatewayAttachment | |
Properties: | |
VpcId: !Ref "VPC" | |
InternetGatewayId: !Ref "InternetGateway" | |
PublicRouteTable: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref "VPC" | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, public-rt]] | |
PublicRoute: | |
Type: AWS::EC2::Route | |
DependsOn: GatewayAttachement | |
Properties: | |
RouteTableId: !Ref "PublicRouteTable" | |
DestinationCidrBlock: "0.0.0.0/0" | |
GatewayId: !Ref "InternetGateway" | |
PublicSubnetOneRouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
SubnetId: !Ref PublicSubnetOne | |
RouteTableId: !Ref PublicRouteTable | |
PublicSubnetTwoRouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
SubnetId: !Ref PublicSubnetTwo | |
RouteTableId: !Ref PublicRouteTable | |
NatGatewayOneAttachment: | |
Type: AWS::EC2::EIP | |
DependsOn: GatewayAttachement | |
Properties: | |
Domain: vpc | |
NatGatewayTwoAttachment: | |
Type: AWS::EC2::EIP | |
DependsOn: GatewayAttachement | |
Properties: | |
Domain: vpc | |
NatGatewayOne: | |
Type: AWS::EC2::NatGateway | |
Properties: | |
AllocationId: !GetAtt NatGatewayOneAttachment.AllocationId | |
SubnetId: !Ref PublicSubnetOne | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, ngw-one]] | |
NatGatewayTwo: | |
Type: AWS::EC2::NatGateway | |
Properties: | |
AllocationId: !GetAtt NatGatewayTwoAttachment.AllocationId | |
SubnetId: !Ref PublicSubnetTwo | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, ngw-two]] | |
PrivateRouteTableOne: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref "VPC" | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, private-rt-one]] | |
PrivateRouteOne: | |
Type: AWS::EC2::Route | |
Properties: | |
RouteTableId: !Ref PrivateRouteTableOne | |
DestinationCidrBlock: 0.0.0.0/0 | |
NatGatewayId: !Ref NatGatewayOne | |
PrivateRouteTableOneAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
RouteTableId: !Ref PrivateRouteTableOne | |
SubnetId: !Ref PrivateSubnetOne | |
PrivateRouteTableTwo: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref "VPC" | |
Tags: | |
- Key: Name | |
Value: !Join ["-", [!Ref Stage, private-rt-two]] | |
PrivateRouteTwo: | |
Type: AWS::EC2::Route | |
Properties: | |
RouteTableId: !Ref PrivateRouteTableTwo | |
DestinationCidrBlock: 0.0.0.0/0 | |
NatGatewayId: !Ref NatGatewayTwo | |
PrivateRouteTableTwoAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
RouteTableId: !Ref PrivateRouteTableTwo | |
SubnetId: !Ref PrivateSubnetTwo | |
#### | |
# ALB related resources | |
#### | |
PublicLoadBalancerSG: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupName: !Join ["-", [!Ref Stage, public-lb-sg]] | |
GroupDescription: Access to the public facing load balancer | |
VpcId: !Ref "VPC" | |
SecurityGroupIngress: | |
- CidrIp: 0.0.0.0/0 | |
IpProtocol: -1 | |
PublicLoadBalancer: | |
Type: AWS::ElasticLoadBalancingV2::LoadBalancer | |
Properties: | |
Name: !Join ["-", [!Ref Stage, public-lb]] | |
Scheme: internet-facing | |
LoadBalancerAttributes: | |
- Key: idle_timeout.timeout_seconds | |
Value: "30" | |
Subnets: | |
- !Ref "PublicSubnetOne" | |
- !Ref "PublicSubnetTwo" | |
SecurityGroups: [!Ref "PublicLoadBalancerSG"] | |
# A dummy target group is used to setup the ALB to just drop traffic | |
# initially, before any real service target groups have been added. | |
DummyTargetGroupPublic: | |
Type: AWS::ElasticLoadBalancingV2::TargetGroup | |
Properties: | |
Name: !Join ["-", [!Ref Stage, dummy-tg]] | |
HealthCheckIntervalSeconds: 6 | |
HealthCheckPath: / | |
HealthCheckProtocol: HTTP | |
HealthCheckTimeoutSeconds: 5 | |
HealthyThresholdCount: 2 | |
Port: 80 | |
Protocol: HTTP | |
UnhealthyThresholdCount: 2 | |
VpcId: !Ref "VPC" | |
PublicLoadBalancerListener: | |
Type: AWS::ElasticLoadBalancingV2::Listener | |
DependsOn: | |
- PublicLoadBalancer | |
Properties: | |
DefaultActions: | |
- TargetGroupArn: !Ref "DummyTargetGroupPublic" | |
Type: "forward" | |
LoadBalancerArn: !Ref "PublicLoadBalancer" | |
Port: 80 | |
Protocol: HTTP | |
#### | |
# ECS cluster related resources | |
#### | |
ECSCluster: | |
Type: AWS::ECS::Cluster | |
Properties: | |
ClusterName: !Join ["-", [!Ref Stage, ecs-cluster]] | |
ContainerSecurityGroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupName: !Join ["-", [!Ref Stage, container-sg]] | |
GroupDescription: Access to the containers | |
VpcId: !Ref "VPC" | |
SecurityGroupIngress: | |
- IpProtocol: tcp | |
FromPort: 0 | |
ToPort: 65535 | |
SourceSecurityGroupId: !Ref "PublicLoadBalancerSG" | |
#### | |
# EFS related resources | |
#### | |
EFSFileSystemSecurityGroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupName: !Join ["-", [!Ref Stage, efs-sg]] | |
GroupDescription: Security group for EFS file system | |
VpcId: !Ref "VPC" | |
SecurityGroupIngress: | |
- IpProtocol: tcp | |
FromPort: 2049 | |
ToPort: 2049 | |
SourceSecurityGroupId: !Ref ContainerSecurityGroup | |
EFSFileSystem: | |
Type: AWS::EFS::FileSystem | |
Properties: | |
Encrypted: true | |
PerformanceMode: generalPurpose | |
ThroughputMode: bursting | |
EFSMountTargetOne: | |
Type: AWS::EFS::MountTarget | |
Properties: | |
FileSystemId: !Ref EFSFileSystem | |
SubnetId: !Ref PrivateSubnetOne | |
SecurityGroups: | |
- !Ref EFSFileSystemSecurityGroup | |
EFSMountTargetTwo: | |
Type: AWS::EFS::MountTarget | |
Properties: | |
FileSystemId: !Ref EFSFileSystem | |
SubnetId: !Ref PrivateSubnetTwo | |
SecurityGroups: | |
- !Ref EFSFileSystemSecurityGroup | |
#### | |
# IAM roles related resources | |
#### | |
AutoScalingRole: | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: ecs-tasks.amazonaws.com | |
Action: "sts:AssumeRole" | |
ManagedPolicyArns: | |
- "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceAutoscaleRole" | |
ECSRole: | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: [ecs.amazonaws.com] | |
Action: ["sts:AssumeRole"] | |
Path: / | |
Policies: | |
- PolicyName: ecs-service | |
PolicyDocument: | |
Statement: | |
- Effect: Allow | |
Action: | |
- "ec2:AttachNetworkInterface" | |
- "ec2:CreateNetworkInterface" | |
- "ec2:CreateNetworkInterfacePermission" | |
- "ec2:DeleteNetworkInterface" | |
- "ec2:DeleteNetworkInterfacePermission" | |
- "ec2:Describe*" | |
- "ec2:DetachNetworkInterface" | |
- "elasticloadbalancing:DeregisterInstancesFromLoadBalancer" | |
- "elasticloadbalancing:DeregisterTargets" | |
- "elasticloadbalancing:Describe*" | |
- "elasticloadbalancing:RegisterInstancesWithLoadBalancer" | |
- "elasticloadbalancing:RegisterTargets" | |
Resource: "*" | |
ManagedPolicyArns: | |
- "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" | |
ECSTaskExecutionRole: | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: [ecs-tasks.amazonaws.com] | |
Action: ["sts:AssumeRole"] | |
Path: / | |
Policies: | |
- PolicyName: AmazonECSTaskExecutionRolePolicy | |
PolicyDocument: | |
Statement: | |
- Effect: Allow | |
Action: | |
# Allow the ECS Tasks to download images from ECR | |
- "ecr:GetAuthorizationToken" | |
- "ecr:BatchCheckLayerAvailability" | |
- "ecr:GetDownloadUrlForLayer" | |
- "ecr:BatchGetImage" | |
# Allow the ECS tasks to upload logs to CloudWatch | |
- "logs:CreateLogStream" | |
- "logs:PutLogEvents" | |
Resource: "*" | |
- Effect: Allow | |
Action: | |
- elasticfilesystem:ClientMount | |
- elasticfilesystem:ClientWrite | |
- elasticfilesystem:DescribeMountTargets | |
- elasticfilesystem:DescribeFileSystems | |
Resource: !GetAtt EFSFileSystem.Arn | |
#### | |
# Flowise ECS service related resources | |
#### | |
ServiceFlowise: | |
Type: AWS::ECS::Service | |
DependsOn: | |
- PrivateRouteOne | |
- PrivateRouteTwo | |
- ListenerRuleFlowise | |
Properties: | |
Cluster: !Ref ECSCluster | |
TaskDefinition: !Ref TaskDefinitionFlowise | |
LaunchType: FARGATE | |
DesiredCount: 2 | |
NetworkConfiguration: | |
AwsvpcConfiguration: | |
AssignPublicIp: DISABLED | |
Subnets: | |
- !Ref PrivateSubnetOne | |
- !Ref PrivateSubnetTwo | |
SecurityGroups: | |
- !Ref ContainerSecurityGroup | |
LoadBalancers: | |
- ContainerName: "flowise-service" | |
ContainerPort: 3000 | |
TargetGroupArn: !Ref TargetGroupFlowise | |
TaskDefinitionFlowise: | |
Type: "AWS::ECS::TaskDefinition" | |
Properties: | |
ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn | |
RequiresCompatibilities: | |
- FARGATE | |
ContainerDefinitions: | |
- Name: "flowise-service" | |
Image: "flowiseai/flowise:latest" | |
Essential: true | |
PortMappings: | |
- ContainerPort: 3000 | |
Protocol: tcp | |
Environment: | |
- Name: Port | |
Value: "3000" | |
- Name: CORS_ORIGINS | |
Value: "" | |
- Name: IFRAME_ORIGINS | |
Value: "" | |
- Name: FLOWISE_USERNAME | |
Value: "" | |
- Name: FLOWISE_PASSWORD | |
Value: "" | |
- Name: FLOWISE_FILE_SIZE_LIMIT | |
Value: "" | |
- Name: DEBUG | |
Value: "" | |
- Name: DATABASE_PATH | |
Value: "/root/.flowise" | |
- Name: DATABASE_TYPE | |
Value: "" | |
- Name: DATABASE_PORT | |
Value: "" | |
- Name: DATABASE_HOST | |
Value: "" | |
- Name: DATABASE_NAME | |
Value: "" | |
- Name: DATABASE_USER | |
Value: "" | |
- Name: DATABASE_PASSWORD | |
Value: "" | |
- Name: DATABASE_SSL | |
Value: "" | |
- Name: DATABASE_SSL_KEY_BASE64 | |
Value: "" | |
- Name: APIKEY_PATH | |
Value: "/root/.flowise" | |
- Name: SECRETKEY_PATH | |
Value: "/root/.flowise" | |
- Name: FLOWISE_SECRETKEY_OVERWRITE | |
Value: "" | |
- Name: LOG_LEVEL | |
Value: "" | |
- Name: LOG_PATH | |
Value: "/root/.flowise/logs" | |
- Name: BLOB_STORAGE_PATH | |
Value: "/root/.flowise/storage" | |
- Name: DISABLE_FLOWISE_TELEMETRY | |
Value: "" | |
EntryPoint: | |
- /bin/sh | |
- -c | |
- "sleep 3; flowise start" | |
MountPoints: | |
- SourceVolume: efs-volume | |
ContainerPath: "/root/.flowise" | |
LogConfiguration: | |
LogDriver: awslogs | |
Options: | |
awslogs-group: !Ref CloudWatchLogsGroupFlowise | |
awslogs-region: !Ref AWS::Region | |
awslogs-stream-prefix: !Ref Stage | |
NetworkMode: awsvpc | |
Memory: "512" | |
Cpu: "256" | |
Volumes: | |
- Name: efs-volume | |
EFSVolumeConfiguration: | |
FilesystemId: !Ref EFSFileSystem | |
RootDirectory: / | |
TransitEncryption: ENABLED | |
CloudWatchLogsGroupFlowise: | |
Type: AWS::Logs::LogGroup | |
Properties: | |
LogGroupName: !Ref AWS::StackName | |
RetentionInDays: 7 | |
TargetGroupFlowise: | |
Type: AWS::ElasticLoadBalancingV2::TargetGroup | |
Properties: | |
VpcId: !Ref VPC | |
Port: 80 | |
Protocol: HTTP | |
Matcher: | |
HttpCode: 200-299 | |
HealthCheckIntervalSeconds: 10 | |
HealthCheckPath: / | |
HealthCheckProtocol: HTTP | |
HealthCheckTimeoutSeconds: 5 | |
HealthyThresholdCount: 2 | |
TargetType: ip | |
ListenerRuleFlowise: | |
Type: AWS::ElasticLoadBalancingV2::ListenerRule | |
Properties: | |
ListenerArn: !Ref PublicLoadBalancerListener | |
Priority: 1 | |
Conditions: | |
- Field: path-pattern | |
Values: | |
- /* | |
Actions: | |
- TargetGroupArn: !Ref TargetGroupFlowise | |
Type: forward | |
Outputs: | |
ExternalUrl: | |
Description: The url of Flowise application | |
Value: !Sub http://${PublicLoadBalancer.DNSName} |
I had the same error. Any clue?
@ciscogeek @carrgust Thanks for sharing, I've pushed a new revision with a fix.
Hello,
I have forked your Gist and made some modifications to fix the 400 Bad Request errors. The issue was caused by a mismatch between the target group port and the ECS task port. The target group was configured to forward traffic to port 80, while the Flowise ECS service is listening on port 3000. This misconfiguration caused the load balancer to forward requests to the wrong port, resulting in the 400 errors. I have updated the target group configuration to forward traffic to port 3000, matching the ECS task port.
You can review the changes at the following link:
https://gist.github.com/huiseo/c6c085091c49b9b5a9700d6a0e922fda
Please take a look at the changes and, if appropriate, merge them into your original Gist.
Thank you for your time, and I appreciate your consideration.
Best regards,
huiseo
I could not deploy the stack and encountered below error in ECS task in AWS us-west-2 region.