Do EC2 instances change the IP address for your instance each time you stop/start the instance? Is there a way to keep the IP address constant?
Yes, there is a way: Elastic IP Addressing.
AWS instances are launched with a dynamic IP address by default, which means that the IP address changes every time the server is stopped and restarted. In many cases, this is not desired and so, users also have the option to assign the server a static IP address (also known as an “elastic IP”).3
According to Amazon 1, 2:
An Elastic IP address is a static IPv4 address designed for dynamic cloud computing. An Elastic IP address is associated with your AWS account. With an Elastic IP address, you can mask the failure of an instance or software by rapidly remapping the address to another instance in your account.
And:
You can have one Elastic IP (EIP) address associated with a running instance at no charge. If you associate additional EIPs with that instance, you will be charged for each additional EIP associated with that instance per hour on a pro rata basis. Additional EIPs are only available in Amazon VPC.
To configure a static IP address:
Log in to the AWS EC2 Dashboard. If required, use the region selector
in the top right corner to switch to the region where your instance was launched.
Select the instance in the dashboard.
In the left navigation bar, select the “Network & Security -> Elastic IPs” menu item.
Click the “Allocate New Address” button.
For more details on setting it up, see Allocating an Elastic IP Address
and Configure a static IP address.
There is a charge a small hourly charge if an Elastic IP address is not associated with a running instance, or if it is associated with a stopped instance or an unattached network interface. The charge is prorated and depends on the region; details can be found on Amazon EC2 Pricing.
Get an EIP (Elastic IP) which is free when the instance is running but paid a bit when the instance is stopped.
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html
Elastic IP has its limitations.
If you have reached the maximum number of Elastic IP addresses in a region, and all you want is a constant way to connect to an EC2 instance, I would recommend using a route53 record instead of using IP address.
I create a route53 record that points to the IP address of my EC2 instance. The record doesn't get changed when the EC2 is stopped.
And the way to keep the record pointing to the address of the EC2 is by running a script that changes the route53 record when the EC2 launches.
Here's the user data of my EC2:
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
# get the public ip address
# Ref: https://stackoverflow.com/questions/38679346/get-public-ip-address-on-current-ec2-instance
export public_ip=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
cat <<EOF > input.json
{
"Comment": "optional comment about the changes in this change batch request",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "my-domain.my-company.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{
"Value": "${public_ip}"
}
]
}
}
]
}
EOF
# change route53 record
/usr/bin/aws route53 change-resource-record-sets \
--hosted-zone-id <hosted_zone_of_my-company.con> \
--change-batch file://input.json >
--//
Here I use my-domain.my-company.com as the route53 record for my EC2.
By using this method, you get a route53 record that points to your EC2 instance. And the record does not change when you stop and start the EC2. So you can always use the route53 record to connect to your EC2.
Remember to assign an IAM role that has route53 permissions to the EC2 instance so that you can run the user data without errors.
And remember that the user data I provided is intended for use with Amazon Linux 2, and the commands may not work for other Linux distributions.
Related
I take create an AMI image from a Linux running instance [ centos ]. It has only private IP. Some of the random instance while restoring in a different VPC, retains the old IP or we just couldn't reach it.
Source AMI server has:
[centos#ip-xxxx ~]$ cat /etc/sysconfig/network
# Created by cloud-init on instance boot automatically, do not edit.
#
NETWORKING=yes
[centos#ip-xxxx ~]$ cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
[centos#ip-xxxx ~]$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search ec2.internal
nameserver xxxx
Has anyone faced this? Why is it happening? I couldn't find any pattern. Similar servers from same VPC when I restore the AMI, some works, some doesn't randomnly. Its so confusing! Any help appreciated. Thanks.
An Amazon EC2 instance should not be hard-coding its IP address.
Rather, the private IP address is allocated to the instance via DHCP. The VPC will always serve the same private IP address to an instance (similar to having a DHCP reservation). However, a new instance launched from the same AMI is not considered to be the same instance, so it will receive a 'new' private IP address via DHCP. (It could be the same IP address if both subnets have the same CIDR range, but it is unlikely.)
If you are seeing an incorrect IP address associated with an instance, it is likely because somebody hard-coded it into a configuration file (which is not a good idea).
I need to provide my customers with fixed urls that don't change when the EC2 instances are stopped/started because sometimes we need to change the size of the EC2 and when we restart the instance the public IP has changed.
I thought on using Elastic IPs so I can keep the same public IP when the instance is rebooted, but I've seen that Amazon tells you that you only have 5 Elastic IPs. If you ask them they say that they can give you more, but I guess they're not giving you 10.000 of them.
How can I use a single public Elastic IP to give each user different URLs for out service?
It would be something like this, being 11.22.33.44 the Elastic IP and 192.168.0.X two EC2 instances:
11.22.33.44:**1000** --> 192.168.0.**1**:22
11.22.33.44:**1001** --> 192.168.0.**1**:80
11.22.33.44:**1002** --> 192.168.0.**1**:443
11.22.33.44:**1003** --> 192.168.0.**2**:22
11.22.33.44:**1004** --> 192.168.0.**2**:80
11.22.33.44:**1005** --> 192.168.0.**2**:443
I need to make it work programmatically, as I'm creating EC2 instances from the SDK as needed.
Another way I thought is using subdomains from my .com domain that points to the current public IP of each EC2 instance, but using the IP as I described before sounds better.
The issue is that instances are receiving new (temporary) Public IP addresses after they are stopped and started.
A simple way to handle this is to add a script to each instance that runs during every boot. This script can update a DNS record to point it at the instance.
The script should go into the /var/lib/cloud/scripts/per-boot directory, which will cause Cloud-Init to automatically run the script each time the instance is started.
# Set these values based on your Route 53 Record Sets
ZONE_ID=Z3NAOAOAABC1XY
RECORD_SET=my-domain.com
# Extract information about the Instance
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id/)
AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone/)
MY_IP=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4/)
# Extract Name tag associated with instance
NAME_TAG=$(aws ec2 describe-tags --region ${AZ::-1} --filters "Name=resource-id,Values=${INSTANCE_ID}" --query 'Tags[?Key==`Name`].Value' --output text)
# Update Route 53 Record Set based on the Name tag to the current Public IP address of the Instance
aws route53 change-resource-record-sets --hosted-zone-id $ZONE_ID --change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"'$NAME_TAG.$RECORD_SET'","Type":"A","TTL":300,"ResourceRecords":[{"Value":"'$MY_IP'"}]}}]}'
The script will extract the Name tag of the instance and update the corresponding Record Set in Route 53. (Feel free to change this to use a different Tag.) The instance will also require IAM permissions for ec2 describe-tags and route53 change-resource-record-sets.
Update: I've turned this answer into a blog post: Amazon Route 53: How to automatically update IP addresses without using Elastic IPs
I am running an EC2 Linux instance. For some maintenance purposes I shutdown the instance and started it again. However, EC2 IP has changed now.
How to keep an IP address of Amazon EC2 instance unchanged after stop and start it again?
Actually, When you stop/start your instance, the IP address will change. If you reboot the instance, it will keep the same IP addresses. Unfortunately, it is not possible for us to reassign the address to your instance as that address would have been released back into the pool used by other EC2 instances.
If you want to avoid this issue in the future, depending on your needs:
If you only need a fixed public IP address, you can assign an Elastic IP address to your instance.
If you need both public and private IP addresses to remain the same throughout the lifetime of the instance, you can launch your instance in VPC instead. The private IP address assigned to an instance in VPC remains with the instance through to termination.
To learn more, see the aws documentation to assign elastic ip.
Elastic IP has its limitations.
If you have reached the maximum number of Elastic IP addresses in a region, and all you want is a constant way to connect to an EC2 instance, I would recommend using a route53 record instead of using IP address.
I create a route53 record that points to the IP address of my EC2 instance. The record doesn't get changed when the EC2 is stopped.
And the way to keep the record pointing to the address of the EC2 is by running a script that changes the route53 record when the EC2 launches.
Here's the user data of my EC2:
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
# get the public ip address
# Ref: https://stackoverflow.com/questions/38679346/get-public-ip-address-on-current-ec2-instance
export public_ip=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
cat <<EOF > input.json
{
"Comment": "optional comment about the changes in this change batch request",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "my-domain.my-company.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{
"Value": "${public_ip}"
}
]
}
}
]
}
EOF
# change route53 record
/usr/bin/aws route53 change-resource-record-sets \
--hosted-zone-id <hosted_zone_of_my-company.com> \
--change-batch file://input.json >
--//
Here I use my-domain.my-company.com as the route53 record for my EC2.
Also remember to replace <hosted_zone_of_my-company.com> with the ID of your hosted zone.
By using this method, you get a route53 record that points to your EC2 instance. And the record does not change when you stop and start the EC2. So you can always use the route53 record to connect to your EC2.
Remember to assign an IAM role that has route53 permissions to the EC2 instance so that you can run the user data without errors.
And remember that the user data I provided is intended for use with Amazon Linux 2, and the commands may not work for other Linux distributions.
Yes, you can.
Go to Elastic IP and Create one.
Then select the newly created Elastic IP and Select Associate Elastic IP and select the Instance ID to which you want to associate it with.
That's it. The IP will now be assigned even if you reboot your EC2.
Do note that AWS charges $0.005/hr for each Elastic IP, And $0.10 per Elastic IP address remap for additional remaps over 100 per month
It depends on which IP you speak about:
Public IP: try to use an Elastic Ip, then you will not have this problem anymore. You can allocate an new one to your instance directly on AWS Console or programmatically. But if your are using an autoscaling-group you will have to do it on your user-data or cloud-init process.
Private IP: Unfortunately you cannot fix a private Ip address to an instance. The only way is to use DNS and in that case a private DNS zone for you VPC (https://docs.aws.amazon.com/fr_fr/vpc/latest/userguide/vpc-dns.html). No need to buy a domain in that case.
I would also recommend to use DNS on the first case with maybe a domain you have rather than using an IP address
If you don't want your IP adddress to be changed after stopping and starting your EC2 Instance, use Elastic IP.
For more reference on how to use Elastic IP:
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html
There are two easy ways to solve this problem:
1.Use Elastic IP. However, I don't recommend this method. Last I checked, if your instance is not running, elastic IP will cost you. This I think is to ensure you do not reserve an IP not to use it.
2.Use load balancers like application load balancer. Connect your load balancer to your EC2 instance. This way, even if you start and stop your instance, it does not matter since you are using the public DNS of your application load balancer. You can also tie your load balancer to route 53 to get a better DNS.
I first list emr cluster:
✗ aws emr list-clusters
{
"Clusters": [
{
"Id": "j-MQIKB378OARL",
"Name": "Spark cluster",
"Status": {
"State": "WAITING",
"StateChangeReason": {
"Message": "Cluster ready after last step failed."
},
"Timeline": {
"CreationDateTime": 1524200251.319,
"ReadyDateTime": 1524201100.225
}
},
"NormalizedInstanceHours": 6
},
Then I try to connect:
✗ aws emr ssh --cluster-id j-MQIKB378OARL --key-pair-file ~/.ssh/keys/key-pair.pem
ssh -o StrictHostKeyChecking=no -o ServerAliveInterval=10 -i /Users/myuser/.ssh/keys/key-pair.pem hadoop#ec2-xxxxxxxxxx.compute-1.amazonaws.com -t
ssh: connect to host ec2-xxxxxxxxxx.compute-1.amazonaws.com port 22: Connection refused
Am I missing something?
It seems that the security group of your instance does not allow incoming ssh traffic.
From AWS Documentation
Security groups enable you to control traffic to your instance,
including the kind of traffic that can reach your instance. For
example, you can allow computers from only your home network to access
your instance using SSH. If your instance is a web server, you can
allow all IP addresses to access your instance using HTTP or HTTPS, so
that external users can browse the content on your web server.
To add a rule to a security group for inbound SSH traffic over IPv4 using the console:
In the navigation pane of the Amazon EC2 console, choose Instances. Select your instance and look at the Description tab; Security groups lists the security groups that are associated with the instance. Choose view rules to display a list of the rules that are in effect for the instance.
In the navigation pane, choose Security Groups. Select one of the security groups associated with your instance.
In the details pane, on the Inbound tab, choose Edit. In the dialog, choose Add Rule, and then choose SSH from the Type list.
In the Source field, choose My IP to automatically populate the field with the public IPv4 address of your local computer. Alternatively, choose Custom and specify the public IPv4 address of your computer or network in CIDR notation. For example, if your IPv4 address is 203.0.113.25, specify 203.0.113.25/32 to list this single IPv4 address in CIDR notation. If your company allocates addresses from a range, specify the entire range, such as 203.0.113.0/24.
Choose Save.
Edit security group ElasticMapReduce-...
Edit source ip for port 22
It was incorrect
Update to either your source ip or anywhere.
I got the same answer everywhere on the internet regarding my question of how to get the IP address of an RDS instance in AWS, but I don't know what dig is, and how to use it.
How to allocate IP address in VPC to RDS instance?
Please help me find the IP address of my RDS instance in AWS?
It won't display the ip address on the configuration page for the RDS instance because RDS IP's are dynamic in nature. You can dig for them if you need them but you would be better server using the DNS endpoint for the instance. This remains static and can be found on the details tab of the RDS instance within AWS.
The IP address of your AWS instance will be the IP address of the RDS instance.
If your hostname of your AWS instance is blah.blah.amazonaws.com then you can use the dig command (on Linux machines) or ping command on both Windows and Linux to find out the IP address of the host:
ping blah.blah.amazonaws.com
This will give you back the IP address of the host (something like this):
c:\ping www.google.com
Pinging www.google.com [216.58.210.100] with 32 bytes of data:
Reply from 216.58.210.100: bytes=32 time=14ms TTL=58
Reply from 216.58.210.100: bytes=32 time=15ms TTL=58
Reply from 216.58.210.100: bytes=32 time=14ms TTL=58
So the IP address of www.google.com is 216.58.210.100. dig will give you more output but the IP address is also in there. But sometimes the actual IP address of your AWS instance is actually in the hostname itself. For example:
ip-12-34-56-78.us-west-2.compute.internal
The IP address 12.34.56.78 is already in the name (depending on your instance). You can find the hostname in the AWS Console/Dashboard.
Use this:
SELECT inet_server_addr();
Simple method to find RDS ip address: Open command prompt from local machine and ping your RDS Endpoint. You will see the reply from destination host ip address. That is your RDS ip address! Regardless if it is public accessible or not.
The answer given by Paolo Bolla is good, but only works for Postgresql.
For Microsoft SQL Server, please use:
SELECT
local_net_address = ConnectionProperty('local_net_address')
, local_tcp_port = ConnectionProperty('local_tcp_port')
You can also use Nslookup <<RDS SQL Server>> command to figure out the IP address as suggested in this AWS blog post.
dig is command-line utility that finds an IP address a domain name leads to.
You can simply install it using :
apt-get update && apt-get install dnsutils -y
Then to find an IP of RDS instance (with endpoint xxx.yyy.us-east-1.rds.amazonaws.com), run the following command :
dig xxx.yyy.us-east-1.rds.amazonaws.com
In the output of dig, you will be able to find IP address in ANSWER SECTION :
;; ANSWER SECTION:
xxx.yyy.us-east-1.rds.amazonaws.com. 5 IN A 172.30.1.253
As you can see RDS instance endpoint, resolved to A type of DNS record with Private IP address
On AWS Management Console - Location : AWS Management Console -> EC2 -> Network & Security, Network interfaces
You can see all of IP addresses and its resource's details on description tab together.