Pattern which creates the resources needed to run an application on EC2 instances. For convenience, you may wish to use [[GuPlayApp]] or [[GuNodeApp]], which extend this class.

This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on this, see [[GuInstanceRole]]. To add additional permissions to your EC2 instances, see [[GuEc2AppProps]].

This pattern will automatically create security groups/rules which allow for:

  1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the [[AppAccess]] specified).
  2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.
  3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).

Example usage for a public facing app (open to the internet):

new GuEc2App(stack, {
applicationPort: 1234,
app: "app-name",
access: { scope: AccessScope.PUBLIC },
instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
certificateProps:{
domainName: "prod-guardian.com",
},
monitoringConfiguration: {
snsTopicName: "alerts-topic-for-my-team",
http5xxAlarm: {
tolerated5xxPercentage: 1,
},
unhealthyInstancesAlarm: true,
},
userData: {
distributable: {
fileName: "app-name.deb",
executionStatement: `dpkg -i /app-name/app-name.deb`,
}
},
});

Example usage for an app which is restricted to specific CIDR ranges:

new GuEc2App(stack, {
applicationPort: 1234,
app: "app-name",
access: {
scope: AccessScope.RESTRICTED,
cidrRanges: [Peer.ipv4("192.168.1.1/32"), Peer.ipv4("8.8.8.8/32")],
},
instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),
certificateProps:{
domainName: "prod-guardian.com",
},
monitoringConfiguration: {
snsTopicName: "alerts-topic-for-my-team",
http5xxAlarm: {
tolerated5xxPercentage: 1,
},
unhealthyInstancesAlarm: true,
}
userData: {
distributable: {
fileName: "app-name.deb",
executionStatement: `dpkg -i /app-name/app-name.deb`,
}
},
});

Varying values by stage

There are times when you want a resource's configuration to be stage aware, for example the number of instances in an ASG.

To do this, we can use a simple ternary:

new GuEc2App(this, {
// other required properties
scaling: this.stage === "PROD" ? { minimumInstances: 6 } : { minimumInstances: 1 }
});

If multiple properties need to be stage aware, consider encoding this into the props of the calling class:

export interface MyAppProps extends GuStackProps {
domainName: string;
scaling: GuAsgCapacity;
monitoringConfiguration: Alarms | NoMonitoring;
}

export class MyApp extends GuStack {
private static app = "cdk-playground";

constructor(scope: App, id: string, props: MyAppProps) {
const { stage, domainName, scaling, monitoringConfiguration } = props;

super(scope, id, props);

new GuPlayApp(this, {
app: "my-app",
instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),
access: { scope: AccessScope.PUBLIC },
userData: {
distributable: {
fileName: `my-app.deb`,
executionStatement: `dpkg -i /my-app/my-app.deb`,
},
},
certificateProps: {
domainName,
},
monitoringConfiguration,
scaling,
});
}
}

new MyApp(app, "MyApp-CODE", {
stage: "CODE",
domainName: "my-app.code.dev-gutools.co.uk",
scaling: { minimumInstances: 1 },
monitoringConfiguration: { noMonitoring: true },
});

new MyApp(app, "MyApp-PROD", {
stage: "PROD",
domainName: "my-app.prod.gutools.co.uk",
scaling: { minimumInstances: 6 },
monitoringConfiguration: {
// config to enable alarms in PROD
},
});

If you must support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which instances will be started. You need to set the three props below in order for this to work: vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from Vpc.fromVpcAttributes) privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually obtained from GuVpc.subnets) publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer is intended for public access (usually obtained from GuVpc.subnets) On the other hand, if the access is private, then an "internal" loadbalancer is used in the privateSubnets list. Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting Cloudformation will fail to deploy.

Customising the infrastructure generated by this pattern

Although we allow users to customise many aspects of their infrastructure via [[GuEc2AppProps]], it's possible that there are less common use-cases which are currently unsupported via the API. In these circumstances escape hatches can be used to override specific resources in the stack.

In order to do this:

  1. Create desired resource using Guardian or AWS constructs, for example:
const sg = new GuSecurityGroup(
// custom parameters
);
  1. Access the CloudFormation version of the resource that you wish to customise, for example:
const pattern = new GuEc2App(
// all parameters
)
const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;
  1. Replace the resource generated by the pattern with your bespoke resource, for example:
cfnLb.securityGroups = [sg.securityGroupId];

Hierarchy

Constructors

Properties

autoScalingGroup: GuAutoScalingGroup
certificate: GuCertificate
node: Node

The tree node.

vpc: IVpc

Methods

  • Returns a string representation of this construct.

    Returns string

  • Checks if x is a construct.

    Use this method instead of instanceof to properly detect Construct instances, even when the construct library is symlinked.

    Explanation: in JavaScript, multiple copies of the constructs library on disk are seen as independent, completely different libraries. As a consequence, the class Construct in each copy of the constructs library is seen as a different class, and an instance of one class will not test as instanceof the other class. npm install will not create installations like this, but users may manually symlink construct libraries together or use a monorepo tool: in those cases, multiple copies of the constructs library can be accidentally installed, and instanceof will behave unpredictably. It is safest to avoid using instanceof, and using this type-testing method instead.

    Returns

    true if x is an object created from a class which extends Construct.

    Parameters

    • x: any

      Any object

    Returns x is Construct

Generated using TypeDoc