Resources declaration
- Last Updated: April 14, 2026
- 7 minute read
- MarkLogic Server
- Version 12.0
- Documentation
The Resources portion of the template defines all of the AWS resources created for your stack by this template. Each resource is defined as a specific AWS type. The details of each resource type are described in AWS resource and property types reference.
These resources defined in this template include:
-
VpcStack — See VPC Stack for details.
-
ManagedEniStack — See Managed ENI Stack for details.
-
NodeMgrLambdaStack — See Node Manager Stack for details.
-
Elastic Block Store (EBS) volumes
-
DynamoDB Table (DynamoDB is the Amazon implementation of the Metadata Database)
-
AutoScaling Groups (ASG). For each ASG, there are the following resources:
-
Security Group
-
Instance Type
-
Identity and Access Management (IAM) Instance Profile
-
Launch Configuration
-
UserData
-
Load Balancer
-
Load Balancer ports
-
Health Check values
-
Security Group for each EC2 Instance
Because ENI is not managed by the CloudFormation stack directly, the Managed ENI Lambda function needs to identify the ENIs created in order to have the ability to update or clean them up. All ENIs created by the Lambda function are tagged with stack information.
The Availability Zones for VPC subnets. Accept either 1 zone or 3 zones. In the order of Subnet 1, Subnet 2 and Subnet 3 (if applicable). The Subnets in the VPC. You must provide values for all three public and private subnets for successful deployment. The order must be same as Availability Zone(s) selected. If you only select one Availability Zone, the second and third subnets will be ignored.
Upon launch of the ManagedEniStack stack, the AWS Lambda function creates an Elastic Network Interface based on the node count, subnets, and security group. The Network Interfaces created are tagged with a stack identifier.
ManagedEniStack:
Type: AWS::CloudFormation::Stack
DependsOn:
- InstanceSecurityGroup
Properties:
NotificationARNs:
- !If
- UseLogSNS
- !Ref LogSNS
- !Ref 'AWS::NoValue'
Parameters:
S3Bucket: !Join [ "", [!FindInMap [Variable,"LambdaPackageBucket","base"], !Ref 'AWS::Region']]
S3Directory: !FindInMap [Variable,"S3Directory","base"]
NodesPerZone: !Ref NodesPerZone
NumberOfZones: !Ref NumberOfZones
Subnets: !If [MultiZone, !Join [',', [!Ref PrivateSubnet1, !Ref PrivateSubnet2, !Ref PrivateSubnet3]], !Ref PrivateSubnet1]
ParentStackName: !Ref 'AWS::StackName'
ParentStackId: !Ref 'AWS::StackId'
SecurityGroup: !Ref InstanceSecurityGroup
TemplateURL: !Join ['/', [!FindInMap [Variable,"TemplateUrl","base"],!FindInMap [Variable,"S3Directory","base"],'ml-managedeni.template']]
TimeoutInMinutes: 5
NodeMgrLambdaStack:
Type: AWS::CloudFormation::Stack
DependsOn: ManagedEniStack
Properties:
NotificationARNs:
- !If
- UseLogSNS
- !Ref LogSNS
- !Ref 'AWS::NoValue'
Parameters:
S3Bucket: !Join [ "", [!FindInMap [Variable,"LambdaPackageBucket","base"], !Ref 'AWS::Region']]
S3Directory: !FindInMap [Variable,"S3Directory","base"]
TemplateURL: !Join ['/', [!FindInMap [Variable,"TemplateUrl","base"],!FindInMap [Variable,"S3Directory","base"],'ml-nodemanager.template']]
TimeoutInMinutes: 5
The NodeMgrLambdaStack portion of the template calls the ml-nodemanager.template sub-template to deploy a Lambda function that is hooked up with Auto Scaling Group's life cycle event and manages each cluster node. The resources created by the stack are described in Node Manager Stack.
NodeMgrLambdaStack:
Type: AWS::CloudFormation::Stack
DependsOn: ManagedEniStack
Properties:
NotificationARNs:
- !If
- UseLogSNS
- !Ref LogSNS
- !Ref 'AWS::NoValue'
Parameters:
S3Bucket: !Join [ "", [!FindInMap [Variable,"LambdaPackageBucket","base"], !Ref 'AWS::Region']]
S3Directory: !FindInMap [Variable,"S3Directory","base"]
TemplateURL: !Join ['/', [!FindInMap [Variable,"TemplateUrl","base"],!FindInMap [Variable,"S3Directory","base"],'ml-nodemanager.template']]
TimeoutInMinutes: 5 NodeMgrLambdaStack:
The EBS volumes used by /var/opt/MarkLogic for the first node in Zone1, Zone2 and Zone3. For details on the AWS::EC2::Volume type, see AWS::EC2::Volume.
All EBS volume definitions are similar to MarklogicVolume1 for Zone1, shown below.
MarklogicVolume1:
Type: 'AWS::EC2::Volume'
Properties:
AvailabilityZone: !Select [0, !Ref AZ]
Size: !Ref VolumeSize
Tags:
- Key: Name
Value: MarkLogicData 1
VolumeType: !Ref VolumeType
Encrypted: !If [UseVolumeEncryption, 'true', 'false']
KmsKeyId: !If [HasCustomEBSKey, !Ref VolumeEncryptionKey, !Ref 'AWS::NoValue']
Metadata:
'AWS::CloudFormation::Designer':
id: c81032f7-b0ec-47ca-a236-e24d57b49ae3
MarkLogicDDBTable creates a DynamoDB database used as the Metadata Database, described in AWS Terminology, and returns the name of the DynamoDB Table.
Note: The read and write capacity are both set to 10 for a three-node template and 2 for a single-node template. It is critical to make sure you have enough capacity provisioned for peak periods, which occur when the instances in large cluster are restarted simultaneously. If you don’t have enough capacity, the cluster may not recouple correctly when nodes are replaced following termination. You can set a CloudWatch alarm on capacity, which can either alert you manually or trigger a script to modify the capacity.
For details on the AWS::DynamoDB::Table type, see AWS::DynamoDB::Table
MarkLogicDDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: node
AttributeType: S
KeySchema:
- KeyType: HASH
AttributeName: node
ProvisionedThroughput:
WriteCapacityUnits: '10'
ReadCapacityUnits: '10'
Metadata:
'AWS::CloudFormation::Designer':
id: e7190602-c2de-47ab-81e7-1315f8c01e2d
MarkLogicServerGroup1, MarkLogicServerGroup2 and MarkLogicServerGroup3 are the AutoScaling Groups (ASGs) for Zone1, Zone2 and Zone3. For details on the AWS::AutoScaling::AutoScalingGroup type, see AWS::AutoScaling::AutoScalingGroup. All of them are similar to MarkLogicServerGroup1 for Zone1, shown below.
MarkLogicServerGroup1:
Type: 'AWS::AutoScaling::AutoScalingGroup'
DependsOn:
- VpcStack
- ManagedEniStack
- NodeMgrLambdaStack
Properties:
VPCZoneIdentifier:
- !GetAtt [VpcStack, Outputs.PrivateSubnet1Id]
LaunchConfigurationName: !Ref LaunchConfig1
MinSize: '0'
MaxSize: !Ref NodesPerZone
DesiredCapacity: !Ref NodesPerZone
Cooldown: '300'
HealthCheckType: EC2
HealthCheckGracePeriod: '300'
LoadBalancerNames:
- !Ref ElasticLoadBalancer
NotificationConfiguration: !If
- UseLogSNS
- TopicARN: !Ref LogSNS
NotificationTypes:
- 'autoscaling:EC2_INSTANCE_LAUNCH'
- 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR'
- 'autoscaling:EC2_INSTANCE_TERMINATE'
- 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR'
- !Ref 'AWS::NoValue'
Tags:
- Key: marklogic:stack:name
Value: !Ref 'AWS::StackName'
PropagateAtLaunch: 'true'
- Key: marklogic:stack:id
Value: !Ref 'AWS::StackId'
PropagateAtLaunch: 'true'
LifecycleHookSpecificationList:
- LifecycleTransition: 'autoscaling:EC2_INSTANCE_LAUNCHING'
LifecycleHookName: NodeManager
HeartbeatTimeout: 4800
NotificationTargetARN: !GetAtt [NodeMgrLambdaStack, Outputs.NodeMgrSnsArn]
RoleARN: !GetAtt [NodeMgrLambdaStack, Outputs.NodeMgrIamArn]
Metadata:
'AWS::CloudFormation::Designer':
id: 31621dd0-4b18-4dcd-b443-db9cef64ebb1
NotificationTypes describes the notifications to be sent to the SNS Topic supplied to the cloud formation script to allow monitoring of AutoScaling group actions.
NotificationTypes:
- 'autoscaling:EC2_INSTANCE_LAUNCH'
- 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR'
- 'autoscaling:EC2_INSTANCE_TERMINATE'
- 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR'
- !Ref 'AWS::NoValue'
The InstanceSecurityGroup defines the ingress rules for the SecurityGroup.
InstanceSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
DependsOn:
- VpcStack
Properties:
GroupDescription: Enable SSH access and HTTP access on the inbound port
VpcId: !GetAtt [VpcStack, Outputs.VpcId]
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '7998'
ToPort: '7998'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '8000'
ToPort: '8010'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '7997'
ToPort: '7997'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '7999'
ToPort: '7999'
CidrIp: 0.0.0.0/0
InstanceSecurityGroupIngress:
Type: 'AWS::EC2::SecurityGroupIngress'
DependsOn:
- InstanceSecurityGroup
Properties:
IpProtocol: tcp
FromPort: '0'
ToPort: '65355'
GroupId: !Ref InstanceSecurityGroup
SourceSecurityGroupId: !Ref InstanceSecurityGroup
ElbSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
DependsOn: VpcStack
Properties:
GroupDescription: Enable SSH access and HTTP access on the inbound port
VpcId: !GetAtt [VpcStack, Outputs.VpcId]
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '7998'
ToPort: '7998'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '8000'
ToPort: '8010'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '7997'
ToPort: '7997'
CidrIp: 0.0.0.0/0
LaunchConfig1, LaunchConfig2 and LaunchConfig3 are the Launch Configurations for ASG 1, ASG 2 and ASG 3. These describe how to look up the AMI id associated with the region, instance type, and architecture (PVM vs. HVM). All are similar to that below for ASG 1. For details on the AWS::AutoScaling::LaunchConfiguration type, see AWS::AutoScaling::LaunchConfiguration.
LaunchTemp1:
Type: 'AWS::EC2::LaunchTemplate'
DependsOn:
- InstanceSecurityGroup
Properties:
LaunchTemplateData:
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 40
- DeviceName: /dev/sdf
NoDevice: true
Ebs: {}
KeyName: !Ref KeyName
ImageId: !If [PAYG, !FindInMap [LicenseRegion2AMI,!Ref 'AWS::Region',"PAYGAl2023"], !FindInMap [LicenseRegion2AMI, !Ref 'AWS::Region', "BYOLAl2023"]]
Each Launch Configuration has a UserData and a SecurityGroups property, as shown below.
The UserData property that is populated with the data assigned to the variables described in AWS Configuration Variables. Below is the UserData property for ASG 1.
Note:
In VolumeSize, the ,* defines the volume size for the 2nd and any additional nodes in each ASG. The # indicates that the nodes are dynamically named and a numeric suffix is added from 1 - MaxNodesPerZone.
UserData: !Base64
'Fn::Join':
- ''
- - MARKLOGIC_CLUSTER_NAME=
- !Ref MarkLogicDDBTable
- |+
- MARKLOGIC_EBS_VOLUME=
- !Ref MarklogicVolume1
- ',:'
- !Ref VolumeSize
- '::'
- !Ref VolumeType
- |
::,*
- |
MARKLOGIC_NODE_NAME=NodeA#
- MARKLOGIC_ADMIN_USERNAME=
- !Ref AdminUser
- |+
- MARKLOGIC_ADMIN_PASSWORD=
- !Ref AdminPass
- |+
- |
MARKLOGIC_CLUSTER_MASTER=1
- MARKLOGIC_LICENSEE=
- !Ref Licensee
- |+
- MARKLOGIC_LICENSE_KEY=
- !Ref LicenseKey
- |+
- MARKLOGIC_LOG_SNS=
- !Ref LogSNS
- |+
- !If
- UseVolumeEncryption
- !Join
- ''
- - 'MARKLOGIC_EBS_KEY='
- !If
- HasCustomEBSKey
- !Ref VolumeEncryptionKey
- 'default'
- ''
Each Launch Configuration has a SecurityGroups property that assigns the security group defined by InstanceSecurityGroup to the Amazon EC2 instances in the Auto Scaling group. Each property is like the following.
SecurityGroups:
- !Ref InstanceSecurityGroup
InstanceType: !Ref InstanceType
IamInstanceProfile: !Ref IAMRole
SpotPrice: !If
- UseSpot
- !Ref SpotPrice
- !Ref 'AWS::NoValue'
Metadata:
'AWS::CloudFormation::Designer':
id: 2efb8cfb-df53-401d-8ff2-34af0dd25993
ElasticLoadBalancer is the Load Balancer for all of the ASGs. For details on the AWS::ElasticLoadBalancing::LoadBalancertype, see AWS::ElasticLoadBalancing::LoadBalancer.
ElasticLoadBalancer:
Type: 'AWS::ElasticLoadBalancing::LoadBalancer'
DependsOn:
- VpcStack
- ElbSecurityGroup
Properties:
AppCookieStickinessPolicy:
- CookieName: SessionID
PolicyName: MLSession
SecurityGroups:
- !Ref ElbSecurityGroup
Subnets:
- !GetAtt [VpcStack, Outputs.PublicSubnet1Id]
- !If [MultiZone, !GetAtt [VpcStack, Outputs.PublicSubnet2Id], !Ref 'AWS::NoValue']
- !If [MultiZone, !GetAtt [VpcStack, Outputs.PublicSubnet3Id], !Ref 'AWS::NoValue']
ConnectionDrainingPolicy:
Enabled: 'true'
Timeout: '60'
CrossZone: 'true'
Listeners defines all of the ports the Elastic Load Balancer (ELB) opens to the public.
Listeners:
- LoadBalancerPort: '8000'
InstancePort: '8000'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8001'
InstancePort: '8001'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8002'
InstancePort: '8002'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8003'
InstancePort: '8003'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8004'
InstancePort: '8004'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8005'
InstancePort: '8005'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8006'
InstancePort: '8006'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8007'
InstancePort: '8007'
Protocol: HTTP
PolicyNames:
- MLSession
- LoadBalancerPort: '8008'
InstancePort: '8008'
Protocol: HTTP
PolicyNames:
- MLSession
HealthCheck checks the health of each MarkLogic instance by contacting its HealthCheck App Server on port 7997 every number of seconds specified by Interval. Any answer other than "200 OK" within the Timeout period (in seconds) is considered unhealthy and that instance is removed from the ELB. For details on the HealthCheck parameters, see HealthCheck.
HealthCheck:
Target: 'HTTP:7997/'
HealthyThreshold: '3'
UnhealthyThreshold: '5'
Interval: '10'
Timeout: '5'
Metadata:
'AWS::CloudFormation::Designer':
id: e188e71e-5f01-4816-896e-9bd30b9a96c1
The ALB declaration
Alb:
Condition: MultiZone
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
DependsOn:
- VpcStack
- ElbSecurityGroup
Properties:
SecurityGroups:
- !Ref ElbSecurityGroup
Subnets:
- !GetAtt [VpcStack, Outputs.PublicSubnet1Id]
- !If [MultiZone, !GetAtt [VpcStack, Outputs.PublicSubnet2Id], !Ref 'AWS::NoValue']
- !If [MultiZone, !GetAtt [VpcStack, Outputs.PublicSubnet3Id], !Ref 'AWS::NoValue']
Metadata:
'AWS::CloudFormation::Designer':
id: e188e71e-5f01-4816-896e-9bd30b9a96c1
ALB Target group section after the ALB declaration
Description: #Descriptions of the 9 TargetGroups for MultiZone deployments (3 zones). TargetGroups route requests to registered targets.
#Health checks are performed on each TargetGroup.
AlbTargetGroup1:
Condition: MultiZone
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
DependsOn:
- VpcStack
Properties:
HealthCheckIntervalSeconds: 10
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 3
HealthCheckPort: 7997
UnhealthyThresholdCount: 5
Port: 8000
Protocol: HTTP
TargetGroupAttributes:
- Key: stickiness.enabled
Value: true
- Key: stickiness.type
Value: lb_cookie
- Key: stickiness.lb_cookie.duration_seconds
Value: 3600
- Key: deregistration_delay.timeout_seconds
Value: 60
VpcId: !GetAtt [VpcStack, Outputs.VpcId]
ALB Listener groups section after the ALB target groups
Description: #Descriptions of the 9 Listeners for MultiZone deployments (3 zones). Each Listener connects Application Load Balancer to a TargetGroup with a particular port.
AlbListener1:
Condition: MultiZone
Type: "AWS::ElasticLoadBalancingV2::Listener"
DependsOn:
- Alb
- AlbTargetGroup1
Properties:
DefaultActions:
- TargetGroupArn: !Ref AlbTargetGroup1
Type: forward
LoadBalancerArn: !Ref Alb
Port: 8000
Protocol: HTTP