やりたいこと
- CloudFormationテンプレートを実行するだけでテストシナリオを実行するためのMaster(Windows)とSlave(Amazon Linux)が構築されます。(後々CentOSに変わりますw)
- そのため 単一のJMeterマシンではかけられないような負荷を簡単にかけることが出来ます。
classmethod様のfullbokを使う
参考資料
http://dev.classmethod.jp/cloud/aws/aws-cfn-advent-calendar-2013-fullbok/
http://dev.classmethod.jp/study_meeting/cm-regrowth-2014-fullbok/
1.cloudformation準備
- s3に fullbokからテンプレートを追加
2.実行するjenkinsの準備
実行するjobを作成
## Jenkins shell
# !/bin/bash -xv
set -eu
# power user
export AWS_ACCESS_KEY_ID=xxxxxxxxxxx
export AWS_SECRET_ACCESS_xxxxxxxxxxxxxxxxxx
export AWS_DEFAULT_REGION=ap-northeast-1
aws cloudformation create-stack --stack-name gozuqi-fullbok \
--template-url https://s3-ap-northeast-1.amazonaws.com/fullbok/fullbok.template \
--parameters \
ParameterKey=AvailabilityZone,ParameterValue=ap-northeast-1a \
ParameterKey=KeyName,ParameterValue=local.pem \
ParameterKey=MasterInstanceAMI,ParameterValue=ami-ff435e91 \
ParameterKey=MasterInstanceType,ParameterValue=t2.medium \
ParameterKey=SlaveCapacity,ParameterValue=2 \
ParameterKey=SlaveInstanceType,ParameterValue=c3.large \
ParameterKey=SlaveSpotPrice,ParameterValue=0.5 \
ParameterKey=SSHFrom,ParameterValue=0.0.0.0/0 \
--capabilities CAPABILITY_IAM
aws cloudformation wait stack-create-complete --stack-name gozuqi-fullbok
3.実行
ん? 動かない。。。。
unboundのインストールに失敗しているようだ。。。
調べてみると、
http://kiq.biz/news/post175.html
みたいなようだ。
ならAmazonLinuxってCentOSだしCentOSで動くようにレシピを修正
できあがったレシピがこちら
{
"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": "12",
"MaxLength": "12",
"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-507f9631" , "64HVM" : "ami-600ae001" },
"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.medium": { "type": "64HVM" , "HEAP": "-Xms2G -Xmx2G" ,"NEW": "-XX:NewSize=512m -XX:MaxNewSize=1G" },
"m3.large": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"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" },
"r3.large": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"r3.xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"r3.2xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"r3.4xlarge": { "type": "64HVM" , "HEAP": "-Xms4G -Xmx4G" ,"NEW": "-XX:NewSize=1G -XX:MaxNewSize=2G" },
"r3.8xlarge": { "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",
"yum install -y epel-release python-pip wget gcc make zlib-devel openssl-devel\n",
"python -V\n",
"export PATH=$PATH:/opt/aws/bin\n",
"export PATH\n",
"# Install aws-cli\n",
"pip install pystache\n",
"pip install argparse\n",
"pip install python-daemon\n",
"pip install requests\n",
"pip install awscli\n",
"yum -y update\n",
"cd /opt\n",
"curl -O https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
"tar -xvpf aws-cfn-bootstrap-latest.tar.gz\n",
"cd aws-cfn-bootstrap-1.4/\n",
"python setup.py build\n",
"python setup.py install\n",
"chmod 775 /opt/aws-cfn-bootstrap-1.4/bin/*\n",
"cd /opt\n",
"mkdir aws\n",
"cd aws\n",
"ln -s /opt/aws-cfn-bootstrap-1.4/bin /opt/aws/\n",
"# Continuous Release Repository setting for unbound\n",
"yum install -y java-1.7.0-openjdk\n",
"yum install -y java-1.7.0-openjdk-devel\n",
"# Install local dns resolver\n",
"yum install -y unbound\n",
"sed -i 's/val-permissive-mode: .*/val-permissive-mode: yes/g' /etc/unbound/unbound.conf\n",
"echo -e 'forward-zone:\n\tname: ", { "Ref": "AWS::Region" } ,".compute.internal\n\tforward-addr: 10.0.0.2' >> /etc/unbound/unbound.conf\n",
"service unbound start\n",
"chkconfig unbound on\n",
"sed -i 's/PEERDNS=yes/PEERDNS=no/g' /etc/sysconfig/network-scripts/ifcfg-eth0\n",
"sed -i 's/nameserver .*/nameserver 127.0.0.1/g' /etc/resolv.conf\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",
"sh /opt/apache-jmeter-2.10/bin/jmeter -s -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" : {
}
},
"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"
]]}
},
"03-add_disabling_dns_caching" : {
"command" : "sed -i -e \" /^java/i JVM_ARGS=\\\"\\$JVM_ARGS -Dsun.net.inetaddr.ttl=0\\\"\" /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.Headers.add(\"Cookie\", \"oraclelicense=accept-securebackup-cookie\")\n",
"$client.DownloadFile(\"http://download.oracle.com/otn-pub/java/jdk/7u45-b18/jdk-7u45-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."
}
}
}
再度実行
- Status CREATE_COMPLETE
出来上がったみたいですね。
準備
自分はELBにぶら下がった集団ガイルに対して負荷をかけたかったのでELBの設定。
Masterはwindowsなのでmac使ってる人はRemoteDesctopかなんかでログインしてテスト書いて実行
Test実行
windowsで実行
slaveからテストサーバに流れてるか確認する
掃除用Jenkins
環境削除jobを作成
# !/bin/bash -xv
set -eu
export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxx
export AWS_DEFAULT_REGION=ap-northeast-1
aws cloudformation delete-stack --stack-name gozuqi-fullbok
aws cloudformation wait stack-delete-complete --stack-name gozuqi-fullbok