Amazon EC2 and ECS (Elastic Container Service) Example
This example demonstrates how to create Amazon EC2 (Elastic Compute Cloud) instances and ECS (Elastic Container Service) services using FsCDK.
EC2 Instance (Virtual Machine)
#r "../src/bin/Release/net8.0/publish/Amazon.JSII.Runtime.dll"
#r "../src/bin/Release/net8.0/publish/Constructs.dll"
#r "../src/bin/Release/net8.0/publish/Amazon.CDK.Lib.dll"
#r "../src/bin/Release/net8.0/publish/System.Text.Json.dll"
#r "../src/bin/Release/net8.0/publish/FsCDK.dll"
open Amazon.CDK
open Amazon.CDK.AWS.EC2
open FsCDK
ECS Cluster and Fargate Service
open Amazon.CDK.AWS.ECS
stack "ECSStack" {
scope (app { context [ "environment", "production" ] })
description "ECS cluster with Fargate service"
// Create VPC
let! myVpc =
vpc "MyVpc" {
maxAzs 2
natGateways 1
cidr "10.0.0.0/16"
}
// Create ECS cluster
let myCluster =
ecsCluster "MyCluster" {
vpc myVpc
containerInsights ContainerInsights.ENABLED
enableFargateCapacityProviders true
}
()
}
Key Features
EC2 (Virtual Machines)
- IMDSv2 Required: Enhanced security for instance metadata by default
- EBS Encryption: Enabled by default for data-at-rest protection
- Cost-Effective Defaults: t3.micro instance type for dev/test workloads
- Flexible Configuration: Support for custom instance types, AMIs, and user data
ECS (Container Orchestration)
- Container Insights: Enabled by default for monitoring and observability
- Fargate Support: Serverless container execution
- Private by Default: Services don't get public IPs unless explicitly configured
- Best Practices: Follows AWS Well-Architected Framework principles
Security Best Practices
-
EC2 Instances:
- IMDSv2 is required by default to prevent SSRF attacks
- EBS volumes are encrypted by default
- Detailed monitoring is opt-in to control costs
-
ECS Services:
- Services are private by default (no public IP)
- Container Insights enabled for security monitoring
- Follows principle of least privilege
Deployment
|
namespace Amazon
namespace Amazon.CDK
namespace Amazon.CDK.AWS
namespace Amazon.CDK.AWS.EC2
namespace FsCDK
val get: unit -> {| Account: string; Region: string |}
namespace System
type Environment =
static member Exit: exitCode: int -> unit
static member ExpandEnvironmentVariables: name: string -> string
static member FailFast: message: string -> unit + 1 overload
static member GetCommandLineArgs: unit -> string array
static member GetEnvironmentVariable: variable: string -> string + 1 overload
static member GetEnvironmentVariables: unit -> IDictionary + 1 overload
static member GetFolderPath: folder: SpecialFolder -> string + 1 overload
static member GetLogicalDrives: unit -> string array
static member SetEnvironmentVariable: variable: string * value: string -> unit + 1 overload
static member CommandLine: string
...
<summary>Provides information about, and means to manipulate, the current environment and platform. This class cannot be inherited.</summary>
<summary>Provides information about, and means to manipulate, the current environment and platform. This class cannot be inherited.</summary>
System.Environment.GetEnvironmentVariable(variable: string) : string
System.Environment.GetEnvironmentVariable(variable: string, target: System.EnvironmentVariableTarget) : string
System.Environment.GetEnvironmentVariable(variable: string, target: System.EnvironmentVariableTarget) : string
val config: {| Account: string; Region: string |}
module Config
from Ec2-ecs
val stack: name: string -> StackBuilder
<summary>Creates an AWS CDK Stack construct.</summary>
<param name="name">The name of the stack.</param>
<code lang="fsharp"> stack "MyStack" { lambda myFunction bucket myBucket } </code>
<summary>Creates an AWS CDK Stack construct.</summary>
<param name="name">The name of the stack.</param>
<code lang="fsharp"> stack "MyStack" { lambda myFunction bucket myBucket } </code>
custom operation: scope (Constructs.Construct)
Calls StackBuilder.Scope
val app: AppBuilder
<summary>Creates an AWS CDK App construct.</summary>
<code lang="fsharp"> app { context [ ("environment", "production"); ("feature-flag", true) ] stackTraces true } </code>
<summary>Creates an AWS CDK App construct.</summary>
<code lang="fsharp"> app { context [ ("environment", "production"); ("feature-flag", true) ] stackTraces true } </code>
custom operation: context ((string * obj) list)
Calls AppBuilder.Context
<summary>Adds context to the App with a key-value pair.</summary>
<param name="config">The current stack configuration.</param>
<param name="keys">The context key-value pairs to add.</param>
<code lang="fsharp"> app { context [ ("environment", "production") ("feature-flag", true) ] } </code>
<summary>Adds context to the App with a key-value pair.</summary>
<param name="config">The current stack configuration.</param>
<param name="keys">The context key-value pairs to add.</param>
<code lang="fsharp"> app { context [ ("environment", "production") ("feature-flag", true) ] } </code>
custom operation: env (IEnvironment)
Calls StackBuilder.Env
val environment: EnvironmentBuilder
<summary>Creates an AWS CDK Environment configuration.</summary>
<code lang="fsharp"> environment { account "123456789012" region "us-west-2" } </code>
<summary>Creates an AWS CDK Environment configuration.</summary>
<code lang="fsharp"> environment { account "123456789012" region "us-west-2" } </code>
custom operation: account (string)
Calls EnvironmentBuilder.Account
<summary>Sets the AWS account ID for the environment.</summary>
<param name="config">The current configuration.</param>
<param name="accountId">The AWS account ID.</param>
<code lang="fsharp"> environment { account "123456789012" } </code>
<summary>Sets the AWS account ID for the environment.</summary>
<param name="config">The current configuration.</param>
<param name="accountId">The AWS account ID.</param>
<code lang="fsharp"> environment { account "123456789012" } </code>
anonymous record field Account: string
custom operation: region (string)
Calls EnvironmentBuilder.Region
<summary>Sets the AWS region for the environment.</summary>
<param name="config">The current configuration.</param>
<param name="regionName">The AWS region name.</param>
<code lang="fsharp"> environment { region "us-west-2" } </code>
<summary>Sets the AWS region for the environment.</summary>
<param name="config">The current configuration.</param>
<param name="regionName">The AWS region name.</param>
<code lang="fsharp"> environment { region "us-west-2" } </code>
anonymous record field Region: string
custom operation: description (string)
Calls StackBuilder.Description
<summary>Sets the stack description.</summary>
<param name="config">The current stack configuration.</param>
<param name="desc">A description of the stack.</param>
<code lang="fsharp"> stack "MyStack" { description "My application stack" } </code>
<summary>Sets the stack description.</summary>
<param name="config">The current stack configuration.</param>
<param name="desc">A description of the stack.</param>
<code lang="fsharp"> stack "MyStack" { description "My application stack" } </code>
val myVpc: IVpc
val vpc: name: string -> VpcBuilder
<summary>Creates a VPC configuration with AWS best practices.</summary>
<param name="name">The VPC name.</param>
<code lang="fsharp"> vpc "MyVpc" { maxAzs 2 natGateways 1 cidr "10.0.0.0/16" } </code>
<summary>Creates a VPC configuration with AWS best practices.</summary>
<param name="name">The VPC name.</param>
<code lang="fsharp"> vpc "MyVpc" { maxAzs 2 natGateways 1 cidr "10.0.0.0/16" } </code>
custom operation: maxAzs (int)
Calls VpcBuilder.MaxAzs
<summary>Sets the maximum number of Availability Zones to use.</summary>
<param name="config">The current VPC configuration.</param>
<param name="maxAzs">The maximum number of AZs (default: 2 for HA).</param>
<code lang="fsharp"> vpc "MyVpc" { maxAzs 3 } </code>
<summary>Sets the maximum number of Availability Zones to use.</summary>
<param name="config">The current VPC configuration.</param>
<param name="maxAzs">The maximum number of AZs (default: 2 for HA).</param>
<code lang="fsharp"> vpc "MyVpc" { maxAzs 3 } </code>
custom operation: natGateways (int)
Calls VpcBuilder.NatGateways
<summary>Sets the number of NAT Gateways.</summary>
<param name="config">The current VPC configuration.</param>
<param name="natGateways">The number of NAT gateways (default: 1 for cost optimization).</param>
<code lang="fsharp"> vpc "MyVpc" { natGateways 2 } </code>
<summary>Sets the number of NAT Gateways.</summary>
<param name="config">The current VPC configuration.</param>
<param name="natGateways">The number of NAT gateways (default: 1 for cost optimization).</param>
<code lang="fsharp"> vpc "MyVpc" { natGateways 2 } </code>
custom operation: cidr (string)
Calls VpcBuilder.Cidr
<summary>Sets the CIDR block for the VPC.</summary>
<param name="config">The current VPC configuration.</param>
<param name="cidr">The CIDR block (e.g., "10.0.0.0/16").</param>
<code lang="fsharp"> vpc "MyVpc" { cidr "10.0.0.0/16" } </code>
<summary>Sets the CIDR block for the VPC.</summary>
<param name="config">The current VPC configuration.</param>
<param name="cidr">The CIDR block (e.g., "10.0.0.0/16").</param>
<code lang="fsharp"> vpc "MyVpc" { cidr "10.0.0.0/16" } </code>
val ec2Instance: name: string -> EC2InstanceBuilder
<summary> Creates a new EC2 instance builder with secure defaults. Example: ec2Instance "my-instance" { instanceType (InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.SMALL)) } </summary>
<summary> Creates a new EC2 instance builder with secure defaults. Example: ec2Instance "my-instance" { instanceType (InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.SMALL)) } </summary>
custom operation: instanceType (InstanceType)
Calls EC2InstanceBuilder.InstanceType
Multiple items
type InstanceType = inherit DeputyBase new: instanceTypeIdentifier: string -> unit member IsBurstable: unit -> bool member SameInstanceClassAs: other: InstanceType -> bool member ToString: unit -> string static member Of: instanceClass: InstanceClass * instanceSize: InstanceSize -> InstanceType member Architecture: InstanceArchitecture
--------------------
InstanceType(instanceTypeIdentifier: string) : InstanceType
type InstanceType = inherit DeputyBase new: instanceTypeIdentifier: string -> unit member IsBurstable: unit -> bool member SameInstanceClassAs: other: InstanceType -> bool member ToString: unit -> string static member Of: instanceClass: InstanceClass * instanceSize: InstanceSize -> InstanceType member Architecture: InstanceArchitecture
--------------------
InstanceType(instanceTypeIdentifier: string) : InstanceType
InstanceType.Of(instanceClass: InstanceClass, instanceSize: InstanceSize) : InstanceType
[<Struct>]
type InstanceClass =
| STANDARD3 = 0
| M3 = 1
| STANDARD4 = 2
| M4 = 3
| STANDARD5 = 4
| M5 = 5
| STANDARD5_NVME_DRIVE = 6
| M5D = 7
| STANDARD5_AMD = 8
| M5A = 9
...
field InstanceClass.BURSTABLE3: InstanceClass = 172
[<Struct>]
type InstanceSize =
| NANO = 0
| MICRO = 1
| SMALL = 2
| MEDIUM = 3
| LARGE = 4
| XLARGE = 5
| XLARGE2 = 6
| XLARGE3 = 7
| XLARGE4 = 8
| XLARGE6 = 9
...
field InstanceSize.SMALL: InstanceSize = 2
custom operation: machineImage (IMachineImage)
Calls EC2InstanceBuilder.MachineImage
type MachineImage =
inherit DeputyBase
static member FromSsmParameter: parameterName: string * ?options: ISsmParameterImageOptions -> IMachineImage
static member GenericLinux: amiMap: IDictionary<string,string> * ?props: IGenericLinuxImageProps -> IMachineImage
static member GenericWindows: amiMap: IDictionary<string,string> * ?props: IGenericWindowsImageProps -> IMachineImage
static member LatestAmazonLinux: ?props: IAmazonLinuxImageProps -> IMachineImage
static member LatestAmazonLinux2: ?props: IAmazonLinux2ImageSsmParameterProps -> IMachineImage
static member LatestAmazonLinux2022: ?props: IAmazonLinux2022ImageSsmParameterProps -> IMachineImage
static member LatestAmazonLinux2023: ?props: IAmazonLinux2023ImageSsmParameterProps -> IMachineImage
static member LatestWindows: version: WindowsVersion * ?props: IWindowsImageProps -> IMachineImage
static member Lookup: props: ILookupMachineImageProps -> IMachineImage
...
MachineImage.LatestAmazonLinux2(?props: IAmazonLinux2ImageSsmParameterProps) : IMachineImage
custom operation: vpc (IVpc)
Calls EC2InstanceBuilder.Vpc
custom operation: requireImdsv2 (bool)
Calls EC2InstanceBuilder.RequireImdsv2
custom operation: detailedMonitoring (bool)
Calls EC2InstanceBuilder.DetailedMonitoring
namespace Amazon.CDK.AWS.ECS
val myCluster: ECSClusterSpec
val ecsCluster: name: string -> ECSClusterBuilder
<summary> Creates a new ECS cluster builder with best practices. Example: ecsCluster "my-cluster" { vpc myVpc } </summary>
<summary> Creates a new ECS cluster builder with best practices. Example: ecsCluster "my-cluster" { vpc myVpc } </summary>
custom operation: vpc (IVpc)
Calls ECSClusterBuilder.Vpc
custom operation: containerInsights (ContainerInsights)
Calls ECSClusterBuilder.ContainerInsights
[<Struct>]
type ContainerInsights =
| ENABLED = 0
| DISABLED = 1
| ENHANCED = 2
field ContainerInsights.ENABLED: ContainerInsights = 0
custom operation: enableFargateCapacityProviders (bool)
Calls ECSClusterBuilder.EnableFargateCapacityProviders
FsCDK