While creating a spot instance using console, it is not compulsory to choose a subnet. I can...
Subnet: No preference (default subnet in any Availability Zone)
But while creating a spot instance using cloudformation template, I need to choose a subnet and I am not sure which one to choose for best price. Does it mean that using web interface is better than cloudformation template (for spot instances)?
I interpreted your requirement "best price" as obtaining a SpotFleet [1] which is configured for cost optimization. AWS describes how to create a cost-optimized spot fleet in the docs [2]:
To optimize the costs for your use of Spot Instances, specify the lowestPrice allocation strategy so that Spot Fleet automatically deploys the cheapest combination of instance types and Availability Zones based on the current Spot price.
You already specified the correct AllocationStrategy lowestPrice
for this case in your CloudFormation template provided in the comments above. AWS describes this allocation strategy as:
The Spot Instances come from the pool with the lowest price. This is the default strategy.
A Spot Instance pool is a set of unused EC2 instances with the same instance type (for example, m5.large), operating system, Availability Zone, and network platform [i.e. EC2-Classic or EC2-VPC, see [3]].
The Spot Fleet selects the Spot Instance pools that are used to fulfill the request, based on the launch specifications included in your Spot Fleet request, and the configuration of the Spot Fleet request [which is lowestPrice in our case]. [2]
That answers one part of your question:
No, the subnet does not directly determine the spot price. It is the availability zone which determines the price, i.e. instances of the same instance type, operating system and network platform always have the same spot price if they reside in the same availability zone. Since a subnet cannot span multiple availability zones, the spot price for instances in a particular subnet is always identical - i.e. the price for the (AZ, Instance Type, OS, Network Platform) combination.
You state in your question that you have to choose a subnet. That is not true. The NetworkInterfaces attribute of your LaunchSpecification [4] is optional. If you omit it, CloudFormation behaves exactly the same as the AWS Management Console. You can read about it in the Spot Fleet Examples section of the docs [5]:
Example 1: Launch Spot Instances Using the Lowest-Priced Availability Zone or Subnet in the Region
The following example specifies a single launch specification without an Availability Zone or subnet. The Spot Fleet launches the instances in the lowest-priced Availability Zone that has a default subnet. The price you pay does not exceed the On-Demand price.
{ "TargetCapacity": 20, "IamFleetRole": "arn:aws:iam::123456789012:role/aws-ec2-spot-fleet-tagging-role", "LaunchSpecifications": [ { "ImageId": "ami-1a2b3c4d", "KeyName": "my-key-pair", "SecurityGroups": [ { "GroupId": "sg-1a2b3c4d" } ], "InstanceType": "m3.medium", "IamInstanceProfile": { "Arn": "arn:aws:iam::123456789012:instance-profile/my-iam-role" } } ] }
If you really need to assign a NetworkInterface to your instance (e.g. because you require a public IP address), there is also a solution listed in [5]:
{ "ImageId": "ami-1a2b3c4d", "KeyName": "my-key-pair", "InstanceType": "m3.medium", "NetworkInterfaces": [ { "DeviceIndex": 0, "SubnetId": "subnet-1a2b3c4d", "Groups": [ "sg-1a2b3c4d" ], "AssociatePublicIpAddress": true } ], "IamInstanceProfile": { "Arn": "arn:aws:iam::880185128111:instance-profile/my-iam-role" } }
That is exactly what you implemented in your CloudFormation template as far as I see. AWS states for this approach:
The Spot service launches the instances in whichever subnet is in the lowest-priced Availability Zone.
and
You can't specify different subnets from the same Availability Zone in a Spot Fleet request.
That means, you should create one launch specification for each availability zone you want to distribute your instances across. Each of those launch specifications should differ by SubnetId:
[...]
LaunchSpecifications: [
{
[...]
"NetworkInterfaces": [
{
"DeviceIndex": 0,
"SubnetId": "subnet-1a2b3c4d", // choose a subnet from AZ a
"Groups": [ "sg-1a2b3c4d" ],
"AssociatePublicIpAddress": true
}
],
[...]
},
{
[...]
"NetworkInterfaces": [
{
"DeviceIndex": 0,
"SubnetId": "subnet-xxxxxxxx", // choose a subnet from AZ b
"Groups": [ "sg-1a2b3c4d" ],
"AssociatePublicIpAddress": true
}
],
[...]
},
[... etc. for each AZ]
],
[...]
[1] https://docs.aws.amazon.com/de_de/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-spotfleet.html
[2] https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet.html#spot-fleet-allocation-strategy
[3] https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-classic-platform.html
[4] https://docs.aws.amazon.com/de_de/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-spotfleet-spotfleetrequestconfigdata-launchspecifications.html#cfn-ec2-spotfleet-spotfleetrequestconfigdata-launchspecifications-networkinterfaces
[5] https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-examples.html#fleet-config1