Solution for local ip changes of AWS EC2 instances - amazon-ec2

Amazon only gives you a certain number of static ip address and the local (private) ips of each EC2 instance can change when the machine is restarted. This makes creating a stable platform where EC2 instances depend on each other ridiculously hard to use as far as I can tell.
I've search online a lot about various solutions and so far have found nothing reasonable outside of assigning an elastic ip address on ever EC2 even if its not public facing. Does anyone have any other good ideas that is actually easy to execute on?
Thanks!
See the AWS team's response to question Static local IP:
The internal IP address of EC2 instances is allocated via DHCP. On
instance shutdown, or when the DHCP lease expires, the IP address is
returned to the general EC2 DHCP pool of addresses available for other
instances.
There is no way to guarantee that you will obtain the same DHCP
address across reboots.
Edit: The answer is to use Amazon VPC. There is no downside except a trivial amount of extra setup because now you control the router. It's a world apart from plain old EC2 instance on AWS. It's so necessary in fact that VPC will be enabled for all future AWS setups by default. See this post for more information: http://www.reddit.com/r/aws/comments/1a3n0r/ec2_update_virtual_private_clouds_for_everyone/

The stock answers are:
Use AWS VPC so you have complete control over instance addressing
Use Elastic IPs, which will resolve to the instance's local address (not the public, as you'd expect) when used to communicate between EC2 instances

I stumbled upon third option. There's ec2-ssh by the Instragram folks. It's a python shell script that you install globally and lets you both query the public dns of your ec2 instances by tag name and also ssh in via tag name as well.
The documentation for it is virtually nonexistent. I've written down the steps to install below:
To install ec2-ssh:
sudo yum install python-boto (python wrapper for ec2 api)
git clone https://github.com/Instagram/ec2-ssh
In your ~/.bash_profile set your AWS access key and secret like so:
export AWS_ACCESS_KEY_ID=XYZ123
export AWS_SECRET_ACCESS_KEY=XYZ123
cd into the bin folder of the repo, there will be two files:
ec2-host and ec2-ssh
copy them to your /usr/bin or /usr/local/bin.
Now you can do awesome stuff like:
$ ec2-host ZenWorker
ec2-999-xy-999-99.compute-1.amazonaws.com
and
$ ec2-ssh ZenWorker
Connecting to ec2-999-xy-999-99.compute-1.amazonaws.com.
Note that in your regular shell scripts you can use backticks to call these global tools. I've timed these calls and they take between 0.25 and 0.5 second using an EC2 instance, so that's really the only downside. Perhaps you can live with the delay, or use the fact that public DNS only changes for an instance on reboot to work up a solution.
Note that these two programs are commandline scripts and you don't need any Python knowledge to use them. For PHP fans, or those that also want an easy way to scp files without knowing the changing public DNS, you can checkout ec2dns.

I was in the same situation once. I still dont have the expertise to solve it properly. My ugly solution was to use elb not really for load balancing but just for the endpoint.
But I think a good solution can be obtained by using aws vpc.

Here's another Ruby solution for Updating Route 53 DNS from instance on AWS. You shouldn't reference raw 3rd party system IP addresses in your applications or server configurations.

you can change Ip Address using Elastic Ip:
You Can Do Using C# Code:
var associateRequest = new AssociateAddressRequest
{
PublicIp = your Elastic Ip,
InstanceId = Your Instance Id Which You Assign
};
amazonEc2Client.AssociateAddress(associateRequest);
after That DeAssociate It.
var disAssociateRequest = new isassociateAddressRequest(publicIp.ElasticIpAddress1);
AmazonEc2Client.DisassociateAddress(your Elastic Ip);
your Public Ip Will Change

Related

Best way to deploy multiple preconfigured VMs to AWS

I'm just looking for advice, I can do most of my own research, but I'm not sure where to start. Here's the situation:
I want to be able to deploy 3 vms that have 2 nic's a piece. 1 nic will have a standard IP that AWS provides. The second nic will have a pre-configured internal static IP. Let's say, 192.168.0.100, 101, and 102. That way each vm can talk to each other automatically without needing to know what the external IP is. The purpose of this is so that I can have a small cluster already configured and I won't have to do a lot of work every time I deploy the cluster.
I want this to be repeatable. Let's say I want this for a classroom. Each student has the identical set of clustered VMs. All they need to do is power them on and start working.
So, I think I can do this with Terreform. I don't know if AWS has it's own tooling that can do this also. If it has, I haven't been able to find it yet.
Any suggestions would be greatly appreciated!
In general, every VM gets a private IP, if the VM is public you can assign a public IP which makes the VM accessible from external and also provides internet access, this is be done by source/destination NAT.
https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html
As long as they are part of you VPC CIDR and available you can specify the IP addresses on instance launch. This can be done via AWS Console, API, CLI, CloudFormation and also with Terraform. The AWS native tools for doing it at scale / repeatable is CloudFormation or maybe also a script that runs AWS CLI commands would work.
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/opsworks/create-instance.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-network-interface-privateipspec.html

Forward Traffic from Windows EC2 Instance to ElasticSearch VPC Endpoint

I have Windows EC2 instance I use for my public-facing C# API. The VPC(and related Internet Gateway, subnets, etc) are all default.
I've now setup an AWS ElasticSearch service using their more secure VPC Endpoint option (instead of public-facing) and I've associated it to the same subnet and vpc as my above Windows EC2 instance.
I'd like to get them to talk to each other.
Reading from https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html
It seems what you'd do is ssh tunnel / port forward traffic from localhost:9200 on the EC2 instance to the actual Elastic Search service (via that VPC endpoint).
It seems this command is where the magic happens:
ssh -i ~/.ssh/your-key.pem ec2-user#your-ec2-instance-public-ip -N -L 9200:vpc-your-amazon-es-domain.region.es.amazonaws.com:443
but that is for a Linux EC2 instance.
If I am Remote Desktopped into my Windows EC2 instance (the API), how can I make it so when I go to a browser, http://localhost:9200
will send traffic to my VPC Endpoint:
vpc-your-amazon-es-domain.region.es.amazonaws.com:443
Thanks!
Alright, so I'll answer my two questions:
First, it's actually quite easy, just RDP to your box and access the instance directly via the VPC endpoint. You don't need to do anything wacky like port forwarding using the netsh command or anything like that. Simply make sure the server (in my case my API) is on the same VPC and you're fine. I just had an error in my connection string that's why it didn't connect. To confirm, I RDP'D in and was able to hit the endpoint directly in a browser on port 80. While it's true the actual Elasticsearch runs on port 9200, you don't need to forward to localhost:9200 --> vpc:9200.
Now, regarding the second question, about hitting it locally, I think the problem is that because this service lacks a public IP address and you can't access it, that you can go through some complicated setup on AWS, or easier is just set it up to run locally for now until you are ready to use the VPC one (and thus your code will just run). Another option is to use security groups and make a publicly accessible cluster for now, and then when your code is done, search service/layer done, etc, you can start anew with a VPC/secure Elasticsearch service and that should be it.
Another thing that many mention is that it is cheaper/you have more control of things if you setup your own Elasticsearch on your local machine, and then set one up on EC2 (this is just reading blogs and seeing people mention how much frustration they had with it).

Automatically assign Elastic IP from a pool of IPs to auto scalling instance

I am trying my hand at autoscalling and all is well except that I need all of my instances to be assigned an elastic ip (this is for my payment gateway which needs to know all IPs that we are using.)
Im happy to add say 8 elastic ips to my account but what I need is a facility to auto assign one of these to the instance as it boots up and then release it as it switches off.
I guess I need a startup script but this is beyond my knowledge of AWS (so far I do everything through the web console).
Any samples/help appreciated!
If your gateway is deployed in the same Amazon account as your servers, you might want to look at a VPC solution where you can control the instances' private IPs using masks.
If that is not an option, you will need to write a script, which you should add to the Launch Configuration's User Data.
In this script you can use AWS CLI to find which IP Addresses are available using describe-addresses, and use one of them to associate to your newly created instance using associate-address.

How to refer to other ec2 instances? Is Elastic IP the only feasible solution?

Initially my issue was "How do I RDP into an EC2 instance without having to first find its ip address". To solve that I wrote a script that executes periodically on each instance. The script reads a particular tag value and updates the corresponding entry in Route53 with the public dns name of the instance.
This way I can always rdp into web-01.ec2.mydomain.com and be connected to the right instance.
As I continued with setting up my instances, I realized to setup mongodb replication, I will need to somehow refer to three separated instances. I cannot use the internal private ip addresses as they keep changing (or are prone to change on instance stop/start & when the dhcp lease expires).
Trying to access web-01.ec2.mydomain.com from within my EC2 instance returns the internal ip address of the instance. Which seems to be standard behaviour. Thus by mentioning the route53 cnames for my three instances, I can ensure that they can always be discovered by each other. I wouldn't be paying any extra data transfer charges, as the cnames will always resolve to internal ip. I would however be paying for all those route53 queries.
I can run my script every 30 secs or even lesser to ensure that the dns entries are as uptodate as possible.
At this point, I realized that what I have in place is very much an Elastic IP alternative. Maybe not completely, but surely for all my use cases. So I am wondering, whether to use Elastic IP or not. There is no charge involved as long as my instances are running. It does seem an easier option.
What do most people do? If someone with experience with this could reply, I would appreciate that.
Secondly, what happens in those few seconds/minutes during which the instance loses its current private ip and gets a new internal ip. Am assuming all existing connections get dropped. Does that affect the ELB health checks (A ping every 30 secs)? Am assuming if I were using an Elastic IP, the dns name would immediately resolve to the new ip, as opposed to say after my script executes. Assuming my script runs every 30 secs, will there be only 30secs of downtime, or can there possibly be more? Will an Elastic ip always perform better than my scripted solution?
According to the official AWS documentation a "private IP address is associated exclusively with the instance for its lifetime and is only returned to Amazon EC2 when the instance is stopped or terminated. In Amazon VPC, an instance retains its private IP addresses when the instance is stopped.". Therefore checking nevertheless every 30s if something changed seems inherently wrong. This leaves you with two obvious options:
Update the DNS once at/after boot time
Use an elastic IP and static DNS
Used elastic IPs don't cost you anything, and even parked ones cost only little. If your instances are mostly up, use an elastic IP. If they are mostly down, go the boot time update route. If your instance sits in a VPC, not even the boot time update is strictly needed (but in a VPC you probably have different needs and a more complex network setup anyways).
Another option that you could consider is to use a software defined datacenter solution such as Amazon VPC or Ravello Systems (disclaimer: our company).
Using such a solution will allow you to create a walled off private environment in the public cloud. Inside the environment you have full control, including your own private L2 network on which you manage IP addressing and can use e.g. statically allocated IPs. Communications with the outside (e.g. your app servers) happens via the IPs and ports that you configure.

How do I connect up my Amazon EC2 instances without manually modifying config files?

I have a three-tier Windows-based web application bundled into 3 AMIs on Amazon EC2 that I use for load testing.
An ASP.NET web application on IIS
An .NET application server
SQL Server
After I launch them, the config files of each tier needs modifying to update the IP addresses.
At the moment I am doing this manually: I connect to the webserver instance via remote desktop and modify the config file to point to the new IP of the application server instance. Then I do the same with the application server to change the IP in the connection string.
This must be a common requirement and I must be missing something obvious. There must be a better way!
I could use Elastic IP addresses, but these machines are only provisioned for a couple of hours at a time, and I would be charged for the addresses when they were NOT in use (which would be most of the time).
Is there some way of persistently naming the machines? Can I somehow get all the machines on the same network and use machine names instead of IP addresses?
I could write some nifty PowerShell script that would perform the modifications remotely. Is there an example somewhere?
I could use a dynamic IP address service. I'm not sure if this would have any negative effect on performance or availability... Are there any downsides to this approach?
I could install some sort of self-configuring service on each machine (which connects to S3? SNS? SimpleDB?) to publish/retrieve the addresses of the other machines and update the config files automatically. Is there an example somewhere?
What is best practice?
You could use Amazon Virtual Private Cloud (Amazon VPC). You have a private subnet where you can assign an IP address to an instance, but it may require launching an instance from command line to assign IP. VPC is charged the same way as EC2.

Resources