QuickNull QuickNull - 5 months ago 57
Java Question

Launching Instance: VPC security groups may not be used for a non-VPC launch

I'm attempting to create an instance in another region, but I get this error:

AWS Error Code: InvalidParameterCombination, AWS Error Message: VPC security groups may not be used for a non-VPC launch


Here is the code I'm executing.

RunInstancesRequest instancereq = new RunInstancesRequest();

instancereq.setInstanceType("m3.medium");
instancereq.setImageId("ami-37b1b45e");
instancereq.setMinCount(1);
instancereq.setMaxCount(1);

ArrayList<String> secgroup = new ArrayList<String>();
instancereq.setKeyName("testkey");
secgroup.add("testdefault");
instancereq.setSecurityGroups(secgroup);

instancereq.setPlacement(getAzPlacement());
RunInstancesResult instanceresult = ec2.runInstances(instancereq);


I've also tried, instead of using the name "testdefault", using the actual groupid
(sg-########)
, but I'll get an error saying that security group doesn't exist (which is wrong, it does). Which, based on the API doc, if using a non-default VPC, you should pass the actual groupid but I'll get an error like this:

InvalidGroup.NotFound, AWS Error Message: The security group 'sg-########' does not exist


If I use "default" as the
setSecurityGroups
it will use the default VPC. It just doesn't seem like like the groupid I'm passing, despite it being accurate.

Also, if I comment out the
setSecurityGroups
code, and use
setSubnetId
instead and pass the subnet id, it will create the instance just fine, but it goes into the "default" security group, not "testdefault" like I want.

All I'm trying to accomplish is creating an instance and having it use the already existing VPC group.

Answer

My Answer will focus on below statement:

All I'm trying to accomplish is creating an instance and having it use the already existing VPC group.

So, as I understand, you want to launch an instance in a non-default VPC and assign it an existing VPC security group to it.

I am not a java guy, but I could do what you wanted in ruby as below.

require 'aws-sdk-core'
Aws.config = {
  :access_key_id => "my_access_key",
  :secret_access_key => "my_secret_key",
  :region => 'us-west-2'
}

ec2 = Aws::EC2.new

ec2.run_instances(
    min_count: 1,
    max_count: 1,
    image_id: 'ami-8635a9b6',
    instance_type: 't1.micro',
    placement: {
      availability_zone: 'us-west-2a'
    },
    network_interfaces: [
      {
        subnet_id: 'subnet-e881bd63',
        groups: ['sg-fd53bf5e'],
        device_index: 0,
        associate_public_ip_address: true
      }
    ],
    key_name: 'my-key'
).each do |resp|
  resp.instances.each do |x|
    puts x.instance_id
  end
end

Although this is a Ruby code, it is pretty straight forward and should give you some clear hints on how to go about doing it in Java as all these AWS SDKs are polling the same web service APIs.

I guess, the things that you should be concentrating in above code is:

  :region => 'us-west-2'

and

placement: {
  availability_zone: 'us-west-2a'
},
network_interfaces: [
  {
    subnet_id: 'subnet-e881bd63',
    groups: ['sg-fd53bf5e'],
    device_index: 0,
    associate_public_ip_address: true
  }
],
  1. Make sure you explicitly specify the region.
  2. Check how I have defined the subnet ID and security group ID. This code will launch my EC2 instance in subnet-e881bd63 of my VPC and will apply VPC security group ID sg-fd53bf5e to its 0th network interface. Besides, it will also assign a public IP address to my instance. (by default, it will not assign a public IP address when you launch instances in VPC).
  3. FYI. When you launch instances in VPC, you must provide Security group ID instead of security group name.