Awesome
serverless-ecs-plugin
⚠ WARNING: Plugin under initial development .
Exceptions, breaking changes and malfunctioning is expected til 0.1.0 is reach.
Documentation is also not up to date.
Overall
About
This plugin will create a cluster, load balancer, vpc, subnets, and one or more services to associate with it. This plugin implements the following approaches:
- Public VPC / Public ALB / Public Subnet
- Private VPC / Private ALB / Private Subnet
If you would like to reference the VPC elsewhere (such as other clusters). The VPC will be called VPC{stage}
where {stage}
is the stage in the serverless.yml. The subnets will be called SubnetName{stage}{index}
where {stage}
is the stage in the serverless.yml, and {index}
references the index of the subnet that was specified in the subnets array. THESE ARE NOT ADDED TO OUTPUT. So you can only reference them in the same serverless.yml / same cf stack.
Notes
- This plugin only supports AWS provider
- Docker image must be built / uploaded / and properly tagged (this can be done by @hybridless/hybridless plugin)
Options
[serverless.yml content]
....
ecs: Array<{
//Misc
tags: {
owner: Me
Customer: You
};
enableContainerInsights?: boolean; //default is respecting account settings
//Load balancer
albPrivate?: boolean; //default to false, and only considered when auto creating ALB (no listener specified)
albDisabled?: boolean; //tasks can have exposed ports (to private VPC) but no alb attached to it
albListenerArn?: string; //custom ALB by specifying its listener
timeout?: number; //ALB timeout, defaults to 30
//ECS cluster
clusterArns?: { //Indicates if the cluster will not be created and an shared ECS cluster should be used instead
ecsClusterArn: string; //ECS cluster ARN
ecsIngressSecGroupId: string; //Ingress ECS VPC Group
};
clusterName: string; //required, cluster name
//IAM
executionRoleArn?: string; // execution role for services, generated if not specified
//VPC
vpc?: {
//if this options are specified it will create a VPC
cidr: string;
subnets: string[]; // subnet cidrs
//If this options are specified it will attach to existing VPC.
//all of then are required, if one missing it will turn to self-created
//VPC as described above -- All vpc parameters below are intrinsic safe
//ivars meaning that all of then accept intrinsic functions 💪
vpcId: string;
securityGroupIds: string[] | any; //object allows intrinsict functions
subnetIds: string[] | any; //object allows intrinsict functions
albSubnetIds?: string[] | object; //object allows intrinsict functions -- will superseed subnetsIds for the ALB if specified
};
//Services/tasks (1:1)
services: Array<{
name: string; // name of the service
environment: { [key: string]: string }; // environment variables passed to docker container
propagateTags?: ('OFF' | 'SERVICE' | 'TASK' ); //defaults to off
//Service auto scaling
autoScale?: {
min?: number; //default to 1
max?: number; //default to 1
metric: AutoScalingMetricType;
cooldown?: number; //defaults to 30
cooldownIn?: number; //defaults to cooldown but has priority over it
cooldownOut?: number; //defaults to cooldown but has priority over it
targetValue: number;
//Step based AS
scaleIn?: {
//scaling
adjustmentType?: 'ChangeInCapacity' | 'ExactCapacity' | 'PercentChangeInCapacity'; //defaults to ChangeInCapacity
cooldown?: number; //default to 300
aggregation: 'Average' | 'Maximum' | 'Minimum';
minAdjustmentMagnitude?: number; //Should only be used with PercentChangeInCapacity
scaleBy?: number; //defaults to 1 or -1
//scaling metric
metricNamespace: string;
metricName: string;
metricDimension: string;
metricDimensionTarget: string;
metricPeriod?: number; //defaults to 120
metricEvaluationPeriod?: number; //defaults to 1
operator: 'GreaterThanOrEqualToThreshold' | 'GreaterThanThreshold' | 'LessThanThreshold' | 'LessThanOrEqualToThreshold' | 'LessThanLowerOrGreaterThanUpperThreshold' | 'LessThanLowerThreshold' | 'GreaterThanUpperThreshold';
targetValue: number;
//additional config (scaling metric)
metricDependsOn?: string | string[];
additionalDimension?: { dimension: string, target: string }[];
treatMissingData?: ' breaching' | 'notBreaching' | 'ignore' | 'missing'; //defaults to notBreaching
fillupMissingData?: any; //fillup value is used on absence of data. default to false, true uses '0', number can be specified instead if any other fillup values is needed.
};
scaleOut?: {
//scaling
adjustmentType?: 'ChangeInCapacity' | 'ExactCapacity' | 'PercentChangeInCapacity'; //defaults to ChangeInCapacity
cooldown?: number; //default to 300
aggregation: 'Average' | 'Maximum' | 'Minimum';
minAdjustmentMagnitude?: number; //Should only be used with PercentChangeInCapacity
scaleBy?: number; //defaults to 1 or -1
//scaling metric
metricNamespace: string;
metricName: string;
metricDimension: string;
metricDimensionTarget: string;
metricPeriod?: number; //defaults to 120
metricEvaluationPeriod?: number; //defaults to 1
operator: 'GreaterThanOrEqualToThreshold' | 'GreaterThanThreshold' | 'LessThanThreshold' | 'LessThanOrEqualToThreshold' | 'LessThanLowerOrGreaterThanUpperThreshold' | 'LessThanLowerThreshold' | 'GreaterThanUpperThreshold';
targetValue: number;
//additional config (scaling metric)
metricDependsOn?: string | string[];
additionalDimension?: { dimension: string, target: string }[];
treatMissingData?: ' breaching' | 'notBreaching' | 'ignore' | 'missing'; //defaults to notBreaching
fillupMissingData?: any; //fillup value is used on absence of data. default to false, true uses '0', number can be specified instead if any other fillup values is needed.
};
}
//Load balancer
hostname?: string | string[]; //optional hostname for filter on ALB
limitSourceIPs?: string | string[]; //optional limit source IPs on ALB (only request made by the specified source IPs are allowed)
limitHeaders?: { name: string, value: string | string[] }[]; //optional limit headers on ALB (only requests made with the specified headers are allowed)
path?: string | { path: string, method?: string, priority: number }[]; // path which the ALB should send traffic to, defaults '*' (everything) and users priority 1 on the ALB
listeners?: Array<{
//If specifing a listener, you should have or the protocol or the port set,
//otherwise a random port will be attached to it
//If not albProtocol is set, this port will not be attached to the ALB
albProtocol?: "HTTP" | "HTTPS";
port?: number; // 443 for HTTPS
containerPort?: number; // If container port is different than the one exposed on the ALB, container port can be specified, e.g. 8080
//
certificateArns?: string[]; // needed for https
authorizer?: {
poolArn: string;
clientId: string;
poolDomain: string;
}; //available on HTTPS only
}>;
//ALB Health check
healthCheckUri?: string; // defaults to "/"
healthCheckProtocol?: string; // defaults to "HTTP"
healthCheckInterval?: number // in seconds, defaults to 6 seconds
healthCheckTimeout?: number; // in seconds, defaults to 5 seconds
healthCheckHealthyCount?: number; // defaults to 2
healthCheckUnhealthyCount?: number; // defaults to 2
//concurrency and task configurations
desiredCount?: number; // defaults to 1
ec2LaunchType?: boolean; //defaults to false, if true will laucnh task into EC2
cpu: number;
memory: number;
//docker images
image?: string; //optional image full URL
//optionally, can be specified individually
imageRepository?: string; //image URL repo
imageTag?: string; //image tag
entryPoint?: string[]; //custom container entry point
//scheduler
schedulerRate?: string; //creates event rule to invoke task the concurrency below or if not specified it will use 1
schedulerConcurrency?: number;
schedulerInput?: any;
//IAM
taskRoleArn?: string | object; //which role should the task have
//Logs
logsMultilinePattern?: string; //regex pattern to match multiline logs (useful for js objects for example)
}>
}>
Examples
-
HTTP Service with public docker image (you might encounter throtlling limitations from docker api and shadowing it to a private docker repository is highly recommended (e.g.: ECS or Github registry))
service: MyService plugins: - '@hybridless/serverless-ecs-plugin' provider: name: aws stage: ${env:stage, 'local'} region: ${env:region, 'ca-central-1'} ecs: - timeout: 10 clusterName: Ghost tags: Test: 123 vpc: cidr: 10.0.0.0/16 subnets: - 10.0.0.0/24 - 10.0.1.0/24 services: - name: ghost cpu: 1024 memory: 2048 desiredCount: 1 environment: NODE_ENV: development path: "/" image: ghost listeners: - albProtocol: HTTP port: 80 containerPort: 2368
####Outputs
For the configuration above CF will have the reference ECSTestClusterExampleNameServiceHTTP
to be used on your serverless template as ${cf:stackName.ECSTestClusterExampleNameServiceHTTP}
For more information about your stack name, please, check here