How do I upgrade my AWS EC2 instance using the AWS CLI? - amazon-web-services

I would like to increase the number of CPU cores in my EC2 instance, using the AWS CLI.
My instance is currently a C5.4 Large.
I don't know the command for this, and I don't know if I have to know the instance type I want to switch to beforehand, or if I can browse different instance types from the AWS CLI.

aws ec2 help lists the commands describe-instances, stop-instances, modify-instance-attribute, and start-instances.
Calling aws ec2describe-instances may provide too much information. You can select the fields you would like with the --query option. --query takes a "JMESPath", which stands for "JSON Matching Expression paths" - a set of special syntaxes for getting values out of complicated JSON.1
You need enough information to identify the instance, for example, its name and type. Start the JMESPath with Reservations[*].Instances[*], followed by [InstanceId, InstanceType, KeyName].2
Example:
aws ec2 describe-instances \
--query 'Reservations[*].Instances[*].[InstanceId, InstanceType, KeyName]' \
--region us-east-1
Copy the ID.
Stop the instance before upgrading it:
aws ec2 stop-instances \
--instance-ids "$INSTANCE_ID"
It can take 5-10 minutes for it to stop.
Change the instance type with modify-instance-attribute:
aws ec2 modify-instance-attribute \
--instance-id "$INSTANCE_ID" \
--instance-type "{\"Value\":\"$REQUESTED_TYPE\"}
Replace $REQUESTED_TYPE with the name of a type, for example, t2.small.3
There may be limitations on what kinds of instances are allowed for your account, so make sure it's an instance type you have access to.
Now, restart the instance and you're done:
aws ec2 start-instances \
--instance-ids "$INSTANCE_ID"
You'll have to wait a few minutes before the instance has finished booting up.
1 Here is a tutorial on using JMESPath.
2 Every time you call an ec2 command, it is important to specify the region with the option --region. If you don't query a specific region, you won't see your instances.
3 (The quotes are escaped with a backslash so your shell doesn't misinterpret them.)

Related

How to delete autoscaling groups with aws cli?

I am trying to write a bash script that will delete my EC2 instances and the auto scaling group that launched them:
EC2s=$(aws ec2 describe-instances --region=eu-west-3 \
--filters "Name=tag:Name,Values=*-my-dev-eu-west-3" \
--query "Reservations[].Instances[].InstanceId" \
--output text)
for id in $EC2s
do
aws ec2 terminate-instances --region=eu-west-3 --instance-ids $id
done
aws autoscaling delete-auto-scaling-group --region eu-west-3 \
--auto-scaling-group-name my-asg-dev-eu-west-3
But it fails with this error:
An error occurred (ResourceInUse) when calling the DeleteAutoScalingGroup operation:
You cannot delete an AutoScalingGroup while there are instances or pending Spot
instance request(s) still in the group.
There is no issue if I use the AWS console to do the same thing. Why does the aws cli prevent me from deleting the ASG if I have terminated all the instances?
if you really want to do this with CLI, you may first want to use aws autoscaling suspend-processes command to prevent ASG from creating new instances. Then use aws ec2 terminate-instances like you are doing. Then use aws ec2 wait instance-terminated command and pass instance ids. Once all that is done, you should be able use aws autoscaling delete-auto-scaling-group
aws ec2 terminate-instances will return before the instances have finished terminating (which could take several minutes).
I highly recommend using something like CloudFormation or Terraform for this sort of thing instead of the AWS CLI tool.
You can force delete the ASG with active spot instance requests with AWS cli:
aws autoscaling delete-auto-scaling-group --auto-scaling-group-name Your-ASG-Name --force-delete

AWS SSM : Pass tag-name instead of Instance-ID

I am working on AWS, where we have instances running SSM client. For automation, I am passing certain commands to these instances time-to-time. Currently, I have them setup with instance-id. This is proving inflexible for us, since any change to instance-id, will force me to update repository-code, and it's a hardcoded value.
How can I replace instance-id with tag:Name or similar.
Current code :
aws ssm send-command --instance-ids 'i-12434546' --region 'eu-central-1' --document-name 'AWS-RunShellScript' --comment 'Restart Pod' --parameters commands='sudo -u ubuntu kubectl rollout restart deployment.v1.apps/supplier-service-deployment' --output text
I want to replace
--instance-ids 'i-12434546'
With tag:Name. Any help would be nice. Thank you. :-)
The answer to your question is provided directly on the documentation page (https://docs.aws.amazon.com/cli/latest/reference/ssm/send-command.html)
To target a larger number of instances, or if you prefer not to list individual instance IDs, we recommend using the Targets option instead. Using Targets , which accepts tag key-value pairs to identify the instances to send commands to, you can a send command to tens, hundreds, or thousands of instances at once.
You can use --targets option instead of --instance-ids:
aws ssm send-command \
--targets Key=tag:tag-name,Values=tag-value \
[...]

AMI from create-image not maintaining user-data modifications, but console Launch is

TL;DR: when launching an instance of an AMI created with CLI aws ec2 create-image the previous applied user-data is gone, whereas launching off an AMI created in the console has all user-data modifications.
Scenario:
I want to automate creation of a custom AMI for our use which itself is based on a regularly updated base AMI. Whenever I get a notification I take the new AMI ID and then run a script, which I'll excerpt from.
I spin up an EC2 instance to which I add user-data of some form. Create files, add packages, etc. This step is straight-forward and works.
# base_ami_id is set elsewhere
ec2_id=$(aws ec2 run-instances \
--image-id ${base_ami_id} \
--count 1 \
--instance-type t2.micro \
--key-name ${key_name} \
--security-group-ids ${security_group} \
--subnet-id ${subnet} \
--user-data file://user-data.sh \
--iam-instance-profile Name=${iamprof} \
--output text --query 'Instances[*].InstanceId' \
)
echo "Instance ID is ${ec2_id}"
echo "Waiting for instance ${ec2_id} to run"
aws ec2 wait instance-running --instance-ids ${ec2_id}
NOTE: At this point, I can ssh into the created instance and verify that cloud-init applied all my user-data correctly. All is well.
Taking the returned Instance ID, I create an AMI image, as per
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html
echo Create image from instance ${ec2_id}
image_id=$(aws ec2 create-image --name ${image_name} --instance-id ${ec2_id} --output text --query 'ImageId')
echo "image ID is ${image_id}"
echo "Waiting for image ${image_id} to be available"
aws ec2 wait image-available --image-ids ${image_id}
echo "Image ${image_id} (${image_name}) available"
Watching in the console, after a while I see my new AMI.
To test, I launch an instance off the AMI created by this step - and am surprised to find that my modifications are NOT in the instance! It's as if I had launched off the original AMI. Which makes no sense: as described above, the user-data was there when I did a test login. And as seen in the shell excerpt above, I used the return $[ec2_id} which I got from the aws ec2 run-instance stage, as basis for the AMI creation and not , inadvertently, some other ID.
Making this even more confusing, I use the console and test by doing a Create Image from exactly that running instance, the one with Instance ID ${ec2_id} as above, which showed that all my user-data was there.
Then I launch an instance off that AMI - and won't you know it has all my modifications! Everything is there.
I've checked and triple-checked and I just don't see where/what I'm doing wrong! I thought maybe there's some extra command line options in aws ec2 create-image which is used in the console equivalent when making the API call. If there is, I can't see it.
What am I missing?!
It's like the AMI created from the console, off the same instance ID and the one from the CLI are different, but I've compared the ID numbers, they're definitely the same. You would think that using the right instance ID implies that the underlying snapshots and/or volumes would be the same, because --instance-id is the only value I can provide to create-image, right?
EDIT:
Following #Michael-sqlbot advice, I looked into the CloudTrail logs. Sadly that made this even more frustrating.
EDIT of EDIT:
I have removed the CloudTrail logs, as they turned out not to be pertinent to the issue and its solution and would quite possibly only confuse things.
I found the issue and how to fix it, and it may help others running into the same issue:
It turns out that using
aws ec2 wait instance-running
is NOT sufficient to ensure that all user-data is complete and has finished.
You may want to use
aws ec2 wait instance-status-ok
either in addition or instead. Even then you may want to be paranoid and add a simple sleep of several minutes to be certain!

EC2 instance from AWS command line

I am very new to AWS. I've got a Windows instance running and have my aws command line configured. I've read through the AWS docs but can't seem to find exactly what I'm looking for.
How do I view my current instances from the command line?
If by view your current instances, you mean list all running instances from the command line, you can call the describe-instances command:
aws ec2 describe-instances
This will list all of your current instances.
See describe-instances
As noted in the answer by Rodrigo M, you should use describe-instances to view your EC2 instances. In general, the help command is the best way to explore the CLI. Start with aws ec2 help and try the various options. You can get more details on subcommands with aws ec2 describe-instances help as well.
The output is a bit verbose and by default in JSON. This can be a bit overwhelming and hard to read without additional processing. I'd recommend getting familiar with the --query aws CLI parameter if you intend to use the CLI interactively.
In particular, I use this for a quick overview of my EC2 instances:
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId, Tags[?Key==`Name`] | [0].Value, State.Name, PublicDnsName]' --output table
To check one particular attribute on an instance:
aws ec2 describe-instances --query Reservations[0].Instances[0].InstanceType --output text --instance-ids <my-instance-id>
The CLI is very powerful once you get comfortable with learning the commands and managing the output. It's also helpful for learning the porgramming APIs as well, since aws CLI commands generally map one-to-one with an API call.

Get information about new instances spawned by auto scaling using CLI

I am working on creating a monitor dashboard for monitoring status of ec2 instances.
I am searching for a method to get information (especially instances ID) of newly spawned instances using auto scaling.
Can anyone point me in the right direction. Thanks
If you know your instance type then you can use describe-instances command to get details about instances and use query command to get the details what you need (in your case Instance-id)
aws ec2 describe-instances --filters "Name=instance-type,Values=t1.micro" --query 'Reservations[*].{InstanceId:Instances[0].InstanceId}'
## Enter your instance type in the 'Values' field of '--filters' command
I was able to get instance id by using combination of following commands
aws elb describe-load-balancers --load-balancer-name "LoadBalanceID" --region "region" --output text | grep INSTANCES
Using the AWS CLI you can get a list of scaling activities for an auto scaling group.
aws autoscaling describe-scaling-activities --auto-scaling-group-name my-group-name
See AWS CLI
This is the newer Python CLI, so you would need to install that if you have not already done so. It will return a JSON block with all of the scale up and down activities in the group, including the reason an the date and time.