Skip to content

Instantly share code, notes, and snippets.

@ryu1
Last active March 26, 2020 07:02
Show Gist options
  • Select an option

  • Save ryu1/3011467ddc3e0ca7a4e18c4f84188c50 to your computer and use it in GitHub Desktop.

Select an option

Save ryu1/3011467ddc3e0ca7a4e18c4f84188c50 to your computer and use it in GitHub Desktop.
JMeter Master/Slave CloudFormation Template. It is called fullbok by some people.

fullbok

C:\jmeter\apache-jmeter-2.10\bin>jmeter.bat -n -t C:\Users\Administrator\Desktop¥sample.jmx -r -l C:\Users\Administrator\Desktop¥sample.jtl -j jmeter.log

-n コマンドライン実行 -t テストケースを指定 -l 結果ファイルを指定 -r すべてのスレーブを実行

{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "fullbok-demo - JMeter cluster demo CloudFormation template file.",
"Parameters" : {
"KeyName" : {
"Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
"Type" : "String",
"MinLength" : "1",
"MaxLength" : "64",
"AllowedPattern" : "[-_ a-zA-Z0-9]*",
"ConstraintDescription" : "can contain only alphanumeric characters, spaces, dashes and underscores."
},
"TargetCapacity" : {
"Default" : "2",
"Description" : "Number of EC2 instances to launch for the jmeter Target.",
"Type" : "Number",
"MinValue": "1"
},
"MasterInstanceAMI" : {
"Description" : "AMI ID of Master instance (Microsoft Windows Server 2012 RTM 64-bit)",
"Type" : "String",
"MinLength": "12",
"MaxLength": "12",
"AllowedPattern" : "ami-[a-zA-Z0-9]*"
},
"SlaveCapacity" : {
"Default" : "2",
"Description" : "Number of EC2 instances to launch for the jmeter Slave.",
"Type" : "Number",
"MinValue": "2"
},
"SlaveSpotPrice" : {
"Default" : "0",
"Description" : "Spot price for the jmeter slave.",
"Type" : "Number"
}
},
"Mappings" : {
"AWSAmazonLinuxAMI": {
"us-east-1": { "name":"Virginia", "201303": "ami-3275ee5b", "201309": "ami-35792c5c" },
"us-west-2": { "name":"Oregon", "201303": "ami-ecbe2adc", "201309": "ami-d03ea1e0" },
"us-west-1": { "name":"California", "201303": "ami-66d1fc23", "201309": "ami-687b4f2d" },
"eu-west-1": { "name":"Ireland", "201303": "ami-44939930", "201309": "ami-149f7863" },
"ap-southeast-1": { "name":"Singapole", "201303": "ami-aa9ed2f8", "201309": "ami-14f2b946" },
"ap-southeast-2": { "name":"Sydney", "201303": "ami-363eaf0c", "201309": "ami-a148d59b" },
"ap-northeast-1": { "name":"Tokyo", "201303": "ami-173fbf16", "201309": "ami-3561fe34" },
"sa-east-1": { "name":"SaoPaulo", "201303": "ami-dd6bb0c0", "201309": "ami-9f6ec982" }
},
"AZ" : {
"us-east-1" : { "primary" : "us-east-1d", "secondary" : "us-east-1a" },
"us-west-2" : { "primary" : "us-west-2a", "secondary" : "us-west-2b" },
"us-west-1" : { "primary" : "us-west-1a", "secondary" : "us-west-1b" },
"eu-west-1" : { "primary" : "eu-west-1a", "secondary" : "eu-west-1b" },
"ap-southeast-1" : { "primary" : "ap-southeast-1a", "secondary" : "ap-southeast-1b" },
"ap-southeast-2" : { "primary" : "ap-southeast-2a", "secondary" : "ap-southeast-2b" },
"ap-northeast-1" : { "primary" : "ap-northeast-1a", "secondary" : "ap-northeast-1c" },
"sa-east-1" : { "primary" : "sa-east-1a", "secondary" : "sa-east-1b" }
},
"StackConfig" : {
"VPC" : { "CIDR" : "10.0.0.0/16" },
"PublicSubnet1" : { "CIDR" : "10.0.0.0/24" },
"PublicSubnet2" : { "CIDR" : "10.0.1.0/24" },
"TargetInstance": { "InstanceType" : "t1.micro" }
}
},
"Resources" : {
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]},
"InstanceTenancy" : "default",
"Tags" : [
{"Key" : "Application", "Value" : {"Ref" : "AWS::StackId"} },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
"Tags" : [
{"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"AttachGateway" : {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"InternetGatewayId" : { "Ref" : "InternetGateway" }
}
},
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"DependsOn" : "AttachGateway",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"Tags" : [
{"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"PublicRoute" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "AttachGateway",
"Properties" : {
"RouteTableId" : { "Ref" : "PublicRouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
"PublicSubnet1": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::FindInMap": [ "AZ", { "Ref": "AWS::Region" }, "primary" ]},
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "PublicSubnet1", "CIDR" ]}
}
},
"PublicSubnet1RouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet1" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"PublicSubnet2": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::FindInMap": [ "AZ", { "Ref": "AWS::Region" }, "secondary" ]},
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "PublicSubnet2", "CIDR" ]}
}
},
"PublicSubnet2RouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet2" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"VPCDefaultSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Allow all communications in VPC",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} },
{ "IpProtocol" : "udp", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} },
{ "IpProtocol" : "icmp", "FromPort" : "-1", "ToPort" : "-1", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} }
]
}
},
"SSHSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable SSH access via port 22",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0" }
]
}
},
"LoadBalancerSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable HTTP access via port 80",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" }
]
}
},
"TargetLoadBalancer" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"Listeners" : [ { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP" } ],
"HealthCheck" : {
"Target" : "HTTP:80/index.html",
"HealthyThreshold" : "2",
"UnhealthyThreshold" : "5",
"Interval" : "15",
"Timeout" : "14"
},
"SecurityGroups" : [
{"Ref" : "LoadBalancerSecurityGroup"}
],
"Subnets" : [
{"Ref" : "PublicSubnet1"},
{"Ref" : "PublicSubnet2"}
]
}
},
"TargetFleet" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"AvailabilityZones" : [
{ "Fn::FindInMap": [ "AZ", { "Ref": "AWS::Region" }, "primary" ]},
{ "Fn::FindInMap": [ "AZ", { "Ref": "AWS::Region" }, "secondary" ]}
],
"VPCZoneIdentifier" : [
{ "Ref" : "PublicSubnet1" },
{ "Ref" : "PublicSubnet2" }
],
"LaunchConfigurationName" : { "Ref" : "TargetInstanceLaunchConfig" },
"MinSize" : { "Ref" : "TargetCapacity" },
"MaxSize" : { "Ref" : "TargetCapacity" },
"DesiredCapacity" : { "Ref" : "TargetCapacity" },
"LoadBalancerNames" : [ { "Ref" : "TargetLoadBalancer" } ],
"Tags" : [
{ "Key" : "Name", "Value" : "JMeterTarget", "PropagateAtLaunch" : "true" },
{ "Key" : "Network", "Value" : "Public", "PropagateAtLaunch" : "true" }
]
}
},
"TargetInstanceLaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"InstanceType": { "Fn::FindInMap" : [ "StackConfig", "TargetInstance", "InstanceType" ]},
"KeyName": { "Ref" : "KeyName" },
"ImageId": { "Fn::FindInMap": [ "AWSAmazonLinuxAMI", { "Ref": "AWS::Region" }, "201309" ]},
"SecurityGroups": [
{ "Ref" : "SSHSecurityGroup" },
{ "Ref" : "VPCDefaultSecurityGroup" }
],
"InstanceMonitoring" : "false",
"AssociatePublicIpAddress" : "true",
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#! /bin/bash -v\n",
"yum update -y\n",
"# Helper function\n",
"function error_exit\n",
"{\n",
" /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "TargetWaitHandle" }, "'\n",
" exit 1\n",
"}\n",
"# Install packages\n",
"/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r TargetInstanceLaunchConfig ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"# All is well so signal success\n",
"/opt/aws/bin/cfn-signal -e $? -r \"TargetInstanceLaunchConfig setup complete\" '", { "Ref" : "TargetWaitHandle" }, "'\n"
]]}}
},
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : {
"yum" : {
"httpd24" : [],
"php54" : [],
"php-pear" : [],
"jq" : [],
"python-magic" : []
}
},
"files" : {
"/var/www/html/index.html" : {
"content" : "<html><head><title>Hello</title></head><body>Hello, target!</body></html>",
"mode" : "000644",
"owner" : "apache",
"group" : "apache"
},
"/var/www/html/info.php" : {
"content" : "<?php phpinfo();",
"mode" : "000644",
"owner" : "apache",
"group" : "apache"
},
"/var/www/html/wait.php" : {
"content" : "<?php usleep($_GET['time']); echo \"wait complete.\".$_GET['time'];",
"mode" : "000644",
"owner" : "apache",
"group" : "apache"
}
},
"command" : {
"01-create_hosts_entry-on_boot" : {
"command" : "echo \"`curl -s curl http://169.254.169.254/latest/meta-data/local-ipv4` `hostname`\" >>/etc/hosts",
"test" : "test ! -f .create_hosts_entry-semaphore"
},
"02-signal_startup_complete" : {
"command" : "touch .create_hosts_entry-semaphore"
}
},
"services" : {
"sysvinit" : {
"httpd" : { "enabled" : "true", "ensureRunning" : "true" }
}
}
}
}
}
},
"TargetWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle"
},
"TargetWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "TargetFleet",
"Properties" : {
"Handle" : {"Ref" : "TargetWaitHandle"},
"Timeout" : "3600",
"Count" : { "Ref" : "TargetCapacity" }
}
},
"Fullbok": {
"Type" : "AWS::CloudFormation::Stack",
"DependsOn" : "AttachGateway",
"Properties" : {
"TemplateURL" : "https://cm-public-cfn-templates.s3.amazonaws.com/fullbok/fullbok-1.4.template",
"Parameters" : {
"KeyName": { "Ref": "KeyName" },
"AvailabilityZone": { "Fn::FindInMap": [ "AZ", { "Ref": "AWS::Region" }, "primary" ]},
"SSHFrom": "0.0.0.0/0",
"MasterInstanceType": "m1.medium",
"SlaveInstanceType": "m1.small",
"MasterInstanceAMI": { "Ref": "MasterInstanceAMI" },
"SlaveCapacity": { "Ref": "SlaveCapacity" },
"SlaveSpotPrice": { "Ref": "SlaveSpotPrice" }
}
}
}
},
"Outputs": {
"Endpoint": {
"Description": "URL of the target website",
"Value": { "Fn::Join": [ "", [ "http://", { "Fn::GetAtt": [ "TargetLoadBalancer", "DNSName" ]}]]}
}
}
}
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description" : "fullbok - JMeter cluster CloudFormation template file.",
"Parameters": {
"KeyName": {
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances",
"Type": "String",
"MinLength": "1",
"MaxLength": "64",
"AllowedPattern": "[-_ .a-zA-Z0-9]*",
"ConstraintDescription": "can contain only alphanumeric characters, spaces, dashes and underscores."
},
"AvailabilityZone": {
"Default" : "ap-northeast-1a",
"Description" : "Availability zone of Jmeter subnet.",
"Type": "String",
"MinLength": "1",
"MaxLength": "64",
"AllowedPattern": "[-_ a-zA-Z0-9]*"
},
"SSHFrom" : {
"Default" : "0.0.0.0/0",
"Description" : "Lockdown SSH/RDP access to the bastion host (default can be accessed from anywhere)",
"Type" : "String",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern" : "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription" : "must be a valid CIDR range of the form x.x.x.x/x."
},
"MasterInstanceAMI" : {
"Description" : "AMI ID of Master instance (Microsoft Windows Server 2012 RTM 64-bit)",
"Type" : "String",
"MinLength": "5",
"MaxLength": "30",
"AllowedPattern" : "ami-[a-zA-Z0-9]*"
},
"MasterInstanceType": {
"Default": "m1.medium",
"Description": "JMeter master EC2 instance type",
"Type": "String",
"ConstraintDescription": "must be a valid EC2 instance type."
},
"SlaveInstanceType": {
"Default": "m1.small",
"Description": "JMeter slave EC2 instance type",
"Type": "String",
"ConstraintDescription": "must be a valid EC2 instance type."
},
"SlaveCapacity" : {
"Default" : "2",
"Description" : "Number of EC2 instances to launch for the jmeter slave.",
"Type" : "Number",
"MinValue": "1"
},
"SlaveSpotPrice" : {
"Default" : "0",
"Description" : "Spot price for the jmeter slave.",
"Type" : "Number"
}
},
"Mappings": {
"AWSAmazonLinuxAMI": {
"us-east-1": { "name":"Virginia", "64": "ami-35792c5c" , "64HVM" : "ami-69792c00" },
"us-west-2": { "name":"Oregon", "64": "ami-d03ea1e0" , "64HVM" : "ami-e43ea1d4" },
"us-west-1": { "name":"California", "64": "ami-687b4f2d" , "64HVM" : "ami-4e7b4f0b" },
"eu-west-1": { "name":"Ireland", "64": "ami-149f7863" , "64HVM" : "ami-209f7857" },
"ap-southeast-1": { "name":"Singapole", "64": "ami-14f2b946" , "64HVM" : "ami-6af2b938" },
"ap-southeast-2": { "name":"Sydney", "64": "ami-a148d59b" , "64HVM" : "ami-a948d593" },
"ap-northeast-1": { "name":"Tokyo", "64": "ami-3561fe34" , "64HVM" : "ami-0961fe08" },
"sa-east-1": { "name":"SaoPaulo", "64": "ami-9f6ec982" , "64HVM" : "ami-9d6ec980" }
},
"StackConfig" : {
"VPC" : { "CIDR" : "10.0.0.0/16" },
"JMeterSubnet" : { "CIDR" : "10.0.0.0/24" },
"JMeter" : { "URL": "http://archive.apache.org/dist/jmeter/binaries/apache-jmeter-2.10.tgz" }
},
"SlaveInstanceSetting": {
"m3.xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"m3.2xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"m1.small": { "type": "64" , "HEAP": "-Xms1G -Xmx1G" ,"NEW": "-XX:NewSize=256m -XX:MaxNewSize=512m" },
"m1.medium": { "type": "64" , "HEAP": "-Xms2G -Xmx2G" ,"NEW": "-XX:NewSize=512m -XX:MaxNewSize=1G" },
"m1.large": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"m1.xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"c3.large": { "type": "64HVM" , "HEAP": "-Xms2G -Xmx2G" ,"NEW": "-XX:NewSize=512m -XX:MaxNewSize=1G" },
"c3.xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"c3.2xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"c3.4xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"c3.8xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"c1.medium": { "type": "64" , "HEAP": "-Xms1G -Xmx1G" ,"NEW": "-XX:NewSize=256m -XX:MaxNewSize=512m" },
"c1.xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"cc2.8xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"m2.xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"m2.2xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"m2.4xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"cr1.8xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"hi1.4xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"hs1.8xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"t1.micro": { "type": "64" , "HEAP": "-Xms256M -Xmx256M" ,"NEW": "-XX:NewSize=128m -XX:MaxNewSize=128m" },
"g2.2xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"cg1.4xlarge": { "type": "64" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" }
}
},
"Conditions" : {
"UseSpotInstance" : { "Fn::Not": [ { "Fn::Equals" : [ {"Ref" : "SlaveSpotPrice"}, "0" ] } ] }
},
"Resources": {
"PowerUserRole" : {
"Type" : "AWS::IAM::Role",
"Properties" : {
"AssumeRolePolicyDocument" : {
"Statement": [ {
"Effect": "Allow",
"Principal": {
"Service": [ "ec2.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
} ]
},
"Path" : "/",
"Policies" :[ {
"PolicyName" : "PowerUserPolicy",
"PolicyDocument" : {
"Statement": [ {
"Sid": "PowerUserStmt",
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
} ]
}
}]
}
},
"PowerUserProfile" : {
"Type" : "AWS::IAM::InstanceProfile",
"Properties" : {
"Path": "/",
"Roles" : [ { "Ref" : "PowerUserRole" } ]
}
},
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]},
"EnableDnsHostnames" : "true",
"InstanceTenancy" : "default",
"Tags" : [
{"Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
"Tags" : [
{"Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"AttachGateway" : {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : {"Ref" : "VPC"},
"InternetGatewayId" : {"Ref" : "InternetGateway"}
}
},
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"DependsOn" : "AttachGateway",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"Tags" : [
{"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"PublicRoute" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "AttachGateway",
"Properties" : {
"RouteTableId" : { "Ref" : "PublicRouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
"JMeterSubnet": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Ref": "AvailabilityZone" },
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "JMeterSubnet", "CIDR" ]},
"Tags" : [
{"Key" : "Application", "Value" : { "Ref" : "AWS::StackId" } },
{"Key" : "Network", "Value" : "Public" }
]
}
},
"JMeterSubnetRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "JMeterSubnet" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"VPCDefaultSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Allow all communications in VPC",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} },
{ "IpProtocol" : "udp", "FromPort" : "0", "ToPort" : "65535", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} },
{ "IpProtocol" : "icmp", "FromPort" : "-1", "ToPort" : "-1", "CidrIp" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]} }
]
}
},
"SSHSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable SSH access via port 22",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHFrom" }}
]
}
},
"RDPSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable RDP",
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : "3389", "ToPort" : "3389", "CidrIp" : { "Ref" : "SSHFrom" }}
]
}
},
"SlaveFleet" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"AvailabilityZones" : [
{ "Ref" : "AvailabilityZone" }
],
"VPCZoneIdentifier" : [
{ "Ref" : "JMeterSubnet" }
],
"LaunchConfigurationName" : { "Ref" : "SlaveInstanceLaunchConfig" },
"MinSize" : { "Ref" : "SlaveCapacity" },
"MaxSize" : { "Ref" : "SlaveCapacity" },
"DesiredCapacity" : { "Ref" : "SlaveCapacity" },
"Tags" : [
{ "Key" : "Name", "Value" : "JMeterSlave", "PropagateAtLaunch" : "true" },
{ "Key" : "Network", "Value" : "Public", "PropagateAtLaunch" : "true" }
]
}
},
"SlaveInstanceLaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"InstanceType": { "Ref" : "SlaveInstanceType" },
"SpotPrice" : { "Fn::If" : [ "UseSpotInstance", {"Ref" : "SlaveSpotPrice"}, { "Ref" : "AWS::NoValue" } ] },
"KeyName": { "Ref" : "KeyName" },
"ImageId": { "Fn::FindInMap": [ "AWSAmazonLinuxAMI", { "Ref": "AWS::Region" }, { "Fn::FindInMap": [ "SlaveInstanceSetting", { "Ref": "SlaveInstanceType" }, "type" ]} ]},
"SecurityGroups": [
{ "Ref" : "SSHSecurityGroup" },
{ "Ref" : "VPCDefaultSecurityGroup" }
],
"IamInstanceProfile": { "Ref" : "PowerUserProfile" },
"InstanceMonitoring" : "false",
"AssociatePublicIpAddress" : "true",
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#! /bin/bash -v\n",
"yum update -y\n",
"# Helper function\n",
"function error_exit\n",
"{\n",
" /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "SlaveWaitHandle" }, "'\n",
" exit 1\n",
"}\n",
"# Install packages\n",
"/opt/aws/bin/cfn-init -v -s ", { "Ref" : "AWS::StackId" }, " -r SlaveInstanceLaunchConfig ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"sysctl -p\n",
"echo \"/opt/apache-jmeter-2.10/bin/jmeter-server | logger -p daemon.info &\" >>/etc/rc.local\n",
"# All is well so signal success\n",
"/opt/aws/bin/cfn-signal -e $? -r \"SlaveInstanceLaunchConfig setup complete\" '", { "Ref" : "SlaveWaitHandle" }, "'\n"
]]}}
},
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : {
"yum" : {
"java-1.7.0-openjdk-devel" : []
}
},
"sources" : {
"/opt" : { "Fn::FindInMap" : [ "StackConfig", "JMeter", "URL" ]}
},
"files" : {
"/etc/security/limits.conf" : {
"content" : { "Fn::Join" : ["", [
"# /etc/security/limits.conf\n",
"#\n",
"#Each line describes a limit for a user in the form:\n",
"#\n",
"#\n",
"#<domain> <type> <item> <value>\n",
"#\n",
"\n",
"#* soft core 0\n",
"#* hard rss 10000\n",
"#@student hard nproc 20\n",
"#@faculty soft nproc 20\n",
"#@faculty hard nproc 50\n",
"#ftp hard nproc 0\n",
"#@student - maxlogins 4\n",
"\n",
"\n",
"* hard nofile 65536\n",
"* soft nofile 65536\n",
"* hard nproc 8192\n",
"* soft nproc 8192\n",
"\n",
"\n",
"\n",
"# End of file\n"
]]},
"mode" : "000644",
"owner" : "root",
"group" : "root"
}
},
"commands" : {
"00-use_java7" : {
"command" : "alternatives --set java /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java"
},
"01-create_hosts_entry-on_boot" : {
"command" : "echo \"`curl -s curl http://169.254.169.254/latest/meta-data/local-ipv4` `hostname`\" >>/etc/hosts",
"test" : "test ! -f .create_hosts_entry-semaphore"
},
"02-signal_startup_complete" : {
"command" : "touch .create_hosts_entry-semaphore"
},
"03-set_listen_address" : {
"command" : { "Fn::Join" : ["", [
"sed -i -e \"s/^#RMI_HOST_DEF=-Djava.rmi.server.hostname=.*$/RMI_HOST_DEF=-Djava.rmi.server.hostname=$(curl -s http://169.254.169.254/latest/meta-data/local-hostname)/\" /opt/apache-jmeter-2.10/bin/jmeter-server"
]]}
},
"03-set_heap" : {
"command" : { "Fn::Join" : ["", [
"sed -i -e \"s/^HEAP/#HEAP/ \" -e \" /^#HEAP/i HEAP=\\\"" , { "Fn::FindInMap": [ "SlaveInstanceSetting", { "Ref": "SlaveInstanceType" }, "HEAP" ]} , "\\\" \" /opt/apache-jmeter-2.10/bin/jmeter"
]]}
},
"03-set_new" : {
"command" : { "Fn::Join" : ["", [
"sed -i -e \"s/^NEW/#NEW/ \" -e \" /^#NEW/i NEW=\\\"" , { "Fn::FindInMap": [ "SlaveInstanceSetting", { "Ref": "SlaveInstanceType" }, "NEW" ]} , "\\\" \" /opt/apache-jmeter-2.10/bin/jmeter"
]]}
},
"04-tcp_param_tcp_tw_recycle" : {
"command" : "echo \"net.ipv4.tcp_tw_recycle = 1\" >> /etc/sysctl.conf"
},
"04-tcp_param_tcp_fin_timeout" : {
"command" : "echo \"net.ipv4.tcp_fin_timeout = 1\" >> /etc/sysctl.conf"
},
"05-nproc_limit" : {
"command" : "sed -i -e \"s/ nproc 1024/ nproc 8192/\" /etc/security/limits.d/90-nproc.conf"
}
}
}
}
}
},
"SlaveWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle"
},
"SlaveWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "SlaveFleet",
"Properties" : {
"Handle" : {"Ref" : "SlaveWaitHandle"},
"Timeout" : "3600",
"Count" : { "Ref" : "SlaveCapacity" }
}
},
"MasterInstance": {
"Type" : "AWS::EC2::Instance",
"Properties": {
"InstanceType" : { "Ref" : "MasterInstanceType" },
"ImageId" : { "Ref": "MasterInstanceAMI" },
"NetworkInterfaces": [{
"DeviceIndex" : "0",
"AssociatePublicIpAddress" : true,
"DeleteOnTermination" : true,
"SubnetId" : { "Ref" : "JMeterSubnet" },
"GroupSet" : [
{ "Ref" : "RDPSecurityGroup" },
{ "Ref" : "VPCDefaultSecurityGroup" }
]
}],
"KeyName" : { "Ref" : "KeyName" },
"IamInstanceProfile": { "Ref" : "PowerUserProfile" },
"Monitoring" : "false",
"Tags" : [
{ "Key" : "Name", "Value" : "JMeterMaster" },
{ "Key" : "Network", "Value" : "Public" }
],
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"<powershell>\n",
"cfn-init.exe -v -s ", { "Ref" : "AWS::StackId" }, " -r MasterInstance -c create --region ", { "Ref" : "AWS::Region" }, "\n",
"cfn-signal.exe -e $lastexitcode ", { "Fn::Base64" : { "Ref" : "MasterWaitHandle" }}, "\n",
"</powershell>"
]]}}
},
"Metadata" : {
"AWS::CloudFormation::Init" : {
"configSets" : {
"create" : [
"setup_cfn_hup",
"place_scripts",
"install_jdk",
"disable_firewall",
"install_jmeter",
"setup_jmeter"
],
"update" : [
"setup_jmeter"
]
},
"setup_cfn_hup" : {
"files" : {
"c:\\cfn\\cfn-hup.conf" : {
"content" : { "Fn::Join" : ["", [
"[main]\n",
"stack=", { "Ref" : "AWS::StackId" }, "\n",
"region=", { "Ref" : "AWS::Region" }, "\n"
]]}
},
"c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" : {
"content": { "Fn::Join" : ["", [
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.MasterInstance.Metadata.AWS::CloudFormation::Init\n",
"action=cfn-init.exe -v -s ", { "Ref" : "AWS::StackId" }, " -r MasterInstance -c update --region ", { "Ref" : "AWS::Region" }, "\n"
]]}
}
},
"services" : {
"windows" : {
"cfn-hup" : {
"enabled" : "true",
"ensureRunning" : "true",
"files" : [
"c:\\cfn\\cfn-hup.conf",
"c:\\cfn\\hooks.d\\cfn-auto-reloader.conf"
]
}
}
}
},
"place_scripts" : {
"files" : {
"c:\\install_jdk.ps1" : {
"content": { "Fn::Join" : ["", [
"$client = new-object System.Net.WebClient\n",
"$client.DownloadFile(\"https://s3-ap-northeast-1.amazonaws.com/for-devopts-public.bucket/jdk-7u80-windows-x64.exe\", \"C:\\Users\\Administrator\\jdk.exe\")\n",
"C:\\Users\\Administrator\\jdk.exe /s /lang=1041 INSTALLDIR=C:\\java\\jdk1.7.45\n",
"$env:PATH = $env:PATH + \";C:\\java\\jdk1.7.45\\bin\""
]]}
},
"c:\\create_shortcut.ps1" : {
"content": { "Fn::Join" : ["", [
"$WshShell = New-Object -comObject WScript.Shell\n",
"$shortcut = $WshShell.CreateShortcut(\"C:\\Users\\Administrator\\Desktop\\JMeter.lnk\")\n",
"$shortcut.TargetPath = \"C:\\jmeter\\apache-jmeter-2.10\\bin\\jmeterw.cmd\"\n",
"$shortcut.WorkingDirectory = \"C:\\jmeter\\apache-jmeter-2.10\\bin\"\n",
"$shortcut.Save()\n"
]]}
},
"c:\\setupjmetercluster.ps1" : {
"content": { "Fn::Join" : ["", [
"Set-DefaultAWSRegion ", { "Ref" : "AWS::Region" }, "\n",
"$slaves = (Get-ASAutoScalingInstance",
" | ? {$_.AutoScalingGroupName -eq \"", { "Ref" : "SlaveFleet" }, "\"}",
" | select -ExpandProperty InstanceId",
" | Get-EC2Instance",
" | select -ExpandProperty RunningInstance",
" | select -ExpandProperty PrivateIpAddress) -join ','\n",
"(Get-Content \"C:\\jmeter\\apache-jmeter-2.10\\bin\\jmeter.properties\")",
" | Foreach-Object {$_ -replace '^remote_hosts=.*$', (\"remote_hosts=\" + $slaves)}",
" | Set-Content \"C:\\jmeter\\apache-jmeter-2.10\\bin\\jmeter.properties\""
]]}
},
"c:\\updatejmeter.ps1" : {
"content": { "Fn::Join" : ["", [
"(Get-Content \"C:\\jmeter\\apache-jmeter-2.10\\bin\\jmeter.bat\") ",
" | Foreach-Object {$_ -replace '^set HEAP=.*$', (\"set HEAP=" , { "Fn::FindInMap": [ "SlaveInstanceSetting", { "Ref": "SlaveInstanceType" }, "HEAP" ]} , "\")} ",
" | Foreach-Object {$_ -replace '^set NEW=.*$', (\"set NEW=" , { "Fn::FindInMap": [ "SlaveInstanceSetting", { "Ref": "SlaveInstanceType" }, "NEW" ]} , "\")} ",
" | Set-Content \"C:\\jmeter\\apache-jmeter-2.10\\bin\\jmeter.bat\""
]]}
}
}
},
"install_jdk" : {
"commands" : {
"install_jdk" : {
"command" : "powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File c:\\install_jdk.ps1"
}
}
},
"disable_firewall" : {
"commands" : {
"disable_firewall" : {
"command" : "netsh advfirewall set allprofiles state off"
}
}
},
"install_jmeter" : {
"sources" : {
"c:\\jmeter" : { "Fn::FindInMap" : [ "StackConfig", "JMeter", "URL" ]}
},
"commands" : {
"create_shortcut" : {
"command" : "powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File c:\\create_shortcut.ps1"
}
}
},
"setup_jmeter" : {
"commands" : {
"setup_jmeter_cluster" : {
"command" : "powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File c:\\setupjmetercluster.ps1"
}
}
},
"setup_jmeter_jvm" : {
"commands" : {
"setup_jmeter_jvm_param" : {
"command" : "powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File c:\\updatejmeter.ps1"
}
}
}
}
}
},
"MasterWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle"
},
"MasterWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "MasterInstance",
"Properties" : {
"Handle" : {"Ref" : "MasterWaitHandle"},
"Timeout" : "3600"
}
}
},
"Outputs": {
"SSHToSlaveInstances": {
"Value": { "Fn::Join":["", [
"ssh -i /path/to/", { "Ref": "KeyName" }, ".pem ec2-user@<ip/hostname>"
]]},
"Description": "SSH command to connect to the JMeter slave instances."
},
"RDPToMasterInstance": {
"Value": { "Fn::Join":["", [
"remotedesktop://", { "Fn::GetAtt" : [ "MasterInstance", "PublicDnsName" ]}
]]},
"Description": "RDP connection to the JMeter master."
}
}
}
# ENVIRONMENT=development
STACKNAME=
PROFILE=
S3_BUCKET=
S3_PREFIX=
.PHONY: default
default: deploy
.PHONY: package
package: clean
aws cloudformation package --s3-bucket $(S3_BUCKET) --s3-prefix $(S3_PREFIX) --template-file ./fullbok.template --output-template-file ./packaged.yaml --profile $(PROFILE)
.PHONY: deploy
deploy: package
# aws cloudformation deploy \
# --template-file ./packaged.yaml \
# --stack-name $(STACKNAME) \
# --s3-prefix $(S3_PREFIX) \
# --parameter-overrides \
# AvailabilityZone=ap-northeast-1a \
# KeyName= \
# MasterInstanceAMI=ami-029100a5631c4a6ec \
# MasterInstanceType=t2.medium \
# SlaveCapacity=4 \
# SlaveInstanceType=c3.large \
# SlaveSpotPrice=0.5 \
# SSHFrom=0.0.0.0/0 \
# --profile $(PROFILE) --capabilities CAPABILITY_NAMED_IAM
aws cloudformation create-stack \
--template-body "file:///PATH/TO/packaged.yaml" \
--stack-name $(STACKNAME) \
--disable-rollback \
--parameters \
ParameterKey=AvailabilityZone,ParameterValue=ap-northeast-1a \
ParameterKey=KeyName,ParameterValue= \
ParameterKey=MasterInstanceAMI,ParameterValue=ami-029100a5631c4a6ec \
ParameterKey=MasterInstanceType,ParameterValue=t2.medium \
ParameterKey=SlaveCapacity,ParameterValue=4 \
ParameterKey=SlaveInstanceType,ParameterValue=c3.large \
ParameterKey=SlaveSpotPrice,ParameterValue=0.5 \
ParameterKey=SSHFrom,ParameterValue=0.0.0.0/0 \
--profile $(PROFILE) --capabilities CAPABILITY_NAMED_IAM
.PHONY: clean
clean:
rm -rf ./packaged.yaml
.PHONY: init
init:
code --install-extension amazonwebservices.aws-toolkit-vscode
code --install-extension kddejong.vscode-cfn-lint
.PHONY: desc
desc:
aws cloudformation describe-stack-events --stack-name $(STACKNAME) --profile $(PROFILE) | grep "FAILED" -B 10 -A 10
.PHONY: delete
delete:
aws cloudformation delete-stack --stack-name $(STACKNAME) --profile $(PROFILE)
aws cloudformation wait stack-delete-complete --stack-name $(STACKNAME) --profile $(PROFILE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment