Find all aws load balancers which has a particular instance - amazon-web-services

I would like to get names of all the aws load balancers which has a particular instance.
I can list the instances in the ELB's using the following command
aws elb describe-load-balancers --query "LoadBalancerDescriptions[*].{ID:LoadBalancerName,InstanceId:Instances[*].InstanceId}[*]. {ELB:ID,InstanceId:InstanceId[*]}" --output=json
Sample Output:
[
{
"ELB": "my_name",
"InstanceId": [
"instance-id-A",
"instance-id-B",
]
},
{
"ELB": "my_name2",
"InstanceId": [
"instance-id-B",
"instance-id-C"
]
},
{
"ELB": "my_name3",
"InstanceId": [
"instance-id-A",
"instance-id-C"
]
}
]
How do I filter this output to only return the ELB names which has instance id A?

The contains command will give you what you're looking for
aws elb describe-load-balancers --query "LoadBalancerDescriptions[*].{ID:LoadBalancerName,InstanceId:Instances[*].InstanceId}[?contains(to_string(#),'instance-id-A')]"
Provides output:
[
{
"ID": "lb_name",
"InstanceId": [
"i-1234567890"
]
}
]
References
http://jmespath.org/specification.html#contains

Another approach, which I like better as I think is more easy to use, is to use jq for filtering:
aws elb describe-load-balancers | jq -r '.LoadBalancerDescriptions[] | select (.Instances[].InstanceId == "instance-id-A") | .LoadBalancerName'
Output:
SampleLBName1
SampleLBName2

Related

How to find EC2 instances that have "null" for the PublicIpAddress?

When I run ...
$ aws ec2 describe-instances --region=us-west-1 \
> --filters Name=instance-state-name,Values=stopped \
> Name=ip-address,Values=null \
> Name=block-device-mapping.status,Values=attached \
> --query "Reservations[].Instances[].[InstanceId,PublicIpAddress,BlockDeviceMappings[].Ebs.VolumeId]"
I get back ...
[]
If I take out the filter Name=ip-address,Values=null I get this back ...
[
[
"i-XXXXX",
null,
[
"vol-f6f6f6f"
]
],
[
"i-d4XXXX8b",
"XX.XX.XXX.XX",
[
"vol-0ca0ca0ca"
]
],
How can I just get those EC2 instances that just have "null" for the PublicIpAddress?
Since there is no public-ip, that filter doesn't seem to work.
Instead, I notice that such instances seem to have this entry:
"PublicDnsName": "",
Therefore, you should be able to use this logic:
aws ec2 describe-instances --query 'Reservations[].Instances[?PublicDnsName==``].InstanceId'

How can I list all resources that belongs to a certain VPC?

At my AWS account, I have few VPC. I'm trying to find a way to list all resources that located under a certain VPC.
Thanks!!
You can do it in three ways: AWS CLI, AWS console or code.
AWS CLI
You can use AWS CLI to list all ENIs associated with the VPC and prettify the output using the --query parameter to get a resource list with the desired fields (AZ, instance-id, etc.).
aws ec2 describe-network-interfaces --filters Name=vpc-id,Values=<vpc-id> --query 'NetworkInterfaces[*].[AvailabilityZone, OwnerId, Attachment.InstanceId, PrivateIpAddresses[*].Association.PublicIp]'
aws ec2 describe-network-interfaces --filters Name=vpc-id,Values=<vpc-id> --query 'NetworkInterfaces[*].[RequesterId,Description]'
A sample of the raw output (only one instance on the VPC):
"NetworkInterfaces": [
{
"Association": {
"IpOwnerId": "amazon",
"PublicDnsName": "ec2-54-196-57-169.compute-1.amazonaws.com",
"PublicIp": "54.196.57.169"
},
"Attachment": {
"AttachTime": "2020-08-24T10:59:16+00:00",
"AttachmentId": "eni-attach-047e562690aabbffd",
"DeleteOnTermination": true,
"DeviceIndex": 0,
"InstanceId": "i-0fe495a6c17bd0f82",
"InstanceOwnerId": "570398916848",
"Status": "attached"
},
"AvailabilityZone": "us-east-1d",
"Description": "",
"Groups": [
{
"GroupName": "launch-wizard-1",
"GroupId": "sg-0aa7d8257bb487e1b"
}
],
"InterfaceType": "interface",
"Ipv6Addresses": [],
"MacAddress": "0e:58:38:33:9a:31",
"NetworkInterfaceId": "eni-0b20855178d276783",
"OwnerId": "570398916848",
"PrivateDnsName": "ip-172-31-34-30.ec2.internal",
"PrivateIpAddress": "172.31.34.30",
"PrivateIpAddresses": [
{
"Association": {
"IpOwnerId": "amazon",
"PublicDnsName": "ec2-54-196-57-169.compute-1.amazonaws.com",
"PublicIp": "54.196.57.169"
},
"Primary": true,
"PrivateDnsName": "ip-172-31-34-30.ec2.internal",
"PrivateIpAddress": "172.31.34.30"
}
],
"RequesterManaged": false,
"SourceDestCheck": true,
"Status": "in-use",
"SubnetId": "subnet-e2bc5fbd",
"TagSet": [],
"VpcId": "vpc-6ad2e110"
}
]
And now filtered:
For the first --query
[
"us-east-1d",
"57039816848",
"i-0fe495a6c17bd0f82",
[
"44.196.57.169"
]
]
And for the second --query (another VPC):
[
"amazon-elasticache",
"ElastiCache alon-001"
],
[
"amazon-elasticache",
"ElastiCache alon-002"
],
[
"975289786086",
"arn:aws:ecs:us-east-2:57039916848:attachment/22a90802-fae7-4afb-9a7e-43e6f4be8ca4"
],
[
"074689309192",
"Interface for NAT Gateway nat-069344579d8bda20"
],
[
"amazon-elb",
"ELB app/EC2Co-EcsEl-YX74WCWEGOK/0b6d7bc60b540b1"
],
[
"amazon-elb",
"ELB app/EC2Co-EcsEl-YX74WCWGGOK/0b6bd7c60b540b1"
],
[
"amazon-elasticache",
"ElastiCache alon-003"
]
AWS Console
You can do the same using the AWS console.
Under EC2->Network Interfaces, search for the desired vpc-id in the search bar.
Code
Using a python script called vpc-inside.py you can describe all of your VPC resources.
usage: vpc-inside.py [-h] -v VPC [-r REGION] [-p PROFILE]
optional arguments:
-h, --help show this help message and exit
-v VPC, --vpc VPC The VPC to annihilate
-r REGION, --region REGION AWS region that the VPC resides in
-p PROFILE, --profile PROFILE AWS profile
And the output will look like this:
EKSs in VPC vpc-07ef7f777429cfd82:
Omikron
--------------------------------------------
ASGs in VPC vpc-07ef7f777429cfd82:
eks-pooks-9ebf225b-70a9-a026-034f-c7431df9b7ba resides in vpc-07ef7f777429cfd82
eks-pooks-9ebf225b-70a9-a026-034f-c7431df9b7ba
--------------------------------------------
RDSs in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
EC2s in VPC vpc-07ef7f777429cfd82:
i-0c63874d77ea2ba78
i-043740f224015e69e
--------------------------------------------
Lambdas in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
Classic ELBs in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
ELBs V2 in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
NAT GWs in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
VPC EndPoints in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
IGWs in VPC vpc-07ef7f777429cfd82:
--------------------------------------------
ENIs in VPC vpc-07ef7f777429cfd82:
eni-079231232dc136305
eni-05ff227eca8341a08
eni-0c01b2871887ac3f7
eni-00e11d4f9590161b4
--------------------------------------------
Security Groups in VPC vpc-07ef7f777429cfd82:
sg-0b4554a65e1560745
sg-0f93574d6b180b263
--------------------------------------------
Routing tables in VPC vpc-07ef7f777429cfd82:
rtb-0694bdbdd696b2bed
rtb-072ec82a18d8a04ba
--------------------------------------------
ACLs in VPC vpc-07ef7f777429cfd82:
acl-0c0087eabf9335940
--------------------------------------------
Subnets in VPC vpc-07ef7f777429cfd82:
subnet-0b8cc1132727e5b5d
subnet-0e47ee92a9ca80280
subnet-0c25990d9a138616b
--------------------------------------------
You can try in AWS Config > Advanced queries and run below query :
All resources:
SELECT
resourceId,
resourceName,
resourceType
Resources directly associated to VPC:
SELECT
resourceId,
resourceName,
resourceType
WHERE
relationships.resourceId = 'vpc-02368dae78f1387e5'
Query can be further enhanced, see some example of preconfigured query.
VPCs mostly contain EC2 instances, RDS instances, Load Balancers and Lambda functions. Plus, things that use EC2 underneath, like Elasticache. These are the types of resources that connect into a VPC.
Some people suggest using the Tag Editor to find resources: Is there a way to list all resources in AWS.
I also like aws inventory, which simply runs in your browser and does a great job of showing resources. Just give it an Access Key and Secret Key to run.
There's no built in service to easily do this.
The best hope you'd have of find all resources is programatically looping over resources that support:
SubnetId
VpcId

Getting VPC-ID for specific VPC

after the VPC is created, how I can grep only 1 VPC-ID from specific VPC by aws ec2 describe-vpcs, so that VPC ID can be passed inside the script for the next step, I know I can see it manually from that command or from AWS console,
for example:
aws ec2 describe-vpcs --vpc-ids |grep VpcId
"VpcId": "vpc-00a0338c2f671a77c",
"VpcId": "vpc-0b3697513d5987516",
"VpcId": "vpc-061e25f5f78877798",
it gives me all of them, or:
aws ec2 describe-vpcs --vpc-ids |grep -i ansible
"Value": "ANSIBLE_VPC",
but I need only to get the VPC-ID for that specific VPC from command.
If you just issued a create-vpc command, then the VPC ID of that VPC would have been returned in response to that command:
Output:
{
"Vpc": {
"CidrBlock": "10.0.0.0/16",
"DhcpOptionsId": "dopt-5EXAMPLE",
"State": "pending",
"VpcId": "vpc-0a60eb65b4EXAMPLE", <-- This is the VPC ID
"OwnerId": "123456789012",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-07501b79ecEXAMPLE",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false,
"Tags": []
}
}
Thus, you could create the VPC and store its ID like this:
$ ID=`aws ec2 create-vpc --cidr-block 10.0.0.0/16 --query Vpc.VpcId --output text`
$ echo $ID
vpc-0fb4d08f9d6501e94
If, instead, you are seeking the VPC ID for a VPC given its Name tag, you could use:
$ ID=`aws ec2 describe-vpcs --filter Name=tag:Name,Values=ANSIBLE_VPC --query Vpcs[].VpcId --output text`
$ echo $ID
vpc-0fb4d08f9d6501e94
You can use just the aws cli for this, with filters and query:
aws ec2 describe-vpcs --filters Name=tag:Name,Values=ANSIBLE_VPC --query "Vpcs[].VpcId" --output text"
Or you can use a mix of the --filters command with grep to accomplish your task:
aws ec2 describe-vpcs --filters Name=tag:Name,Values=ANSIBLE_VPC | grep VpcId | grep -oh "vpc-\w*"

AWS CLI EMR get Master node Instance ID and tag it

I want to automate the running of a cluster and can use tags to get attributes of an EC2 instance like its instance-id.
The documentation on https://docs.aws.amazon.com/cli/latest/reference/emr/create-cluster.html states that
--tags (list)
A list of tags to associate with a cluster, which apply to each Amazon
EC2 instance in the cluster. Tags are key-value pairs that consist of
a required key string with a maximum of 128 characters, and an
optional value string with a maximum of 256 characters.
You can specify tags in key=value format or you can add a tag without
a value using only the key name, for example key . Use a space to
separate multiple tags.
So this applies tags to every EC2 instance including the master and slaves. How do I discern which instance is the master node?
Additional Info:
I am using the following command to get attributes from aws cli based on tags where you can replace the "Name" and "Prod" with your tags key-value pairs respectively.
aws ec2 describe-instances | jq '.Reservations[].Instances | select(.[].Tags[].Value | startswith("Prod") ) | select(.[].Tags[].Key == "Name") | {InstanceId: .[].InstanceId, PublicDnsName: .[].PublicDnsName, State: .[].State, LaunchTime: .[].LaunchTime, Tags: .[].Tags} | [.]' | jq .[].InstanceId
As you noted when you create an EMR cluster, the tags are the same for all nodes (Master, Slave, Task).
You will find that this process using the AWS CLI to be complicated. My recomendation is to review the examples below and then write a Python program to do this.
Process to add your own tags to the EC2 instances.
STEP 1: List your EMR Clusters:
aws emr list-clusters
This will output JSON:
{
"Clusters": [
{
"Id": "j-ABCDEFGHIJKLM",
"Name": "'MyCluster'",
"Status": {
"State": "WAITING",
"StateChangeReason": {
"Message": "Cluster ready after last step completed."
},
"Timeline": {
"CreationDateTime": 1536626095.303,
"ReadyDateTime": 1536626568.482
}
},
"NormalizedInstanceHours": 0
}
]
}
STEP 2: Make a note of the Cluster ID from the JSON:
"Id": "j-ABCDEFGHIJKLM",
STEP 3: Describe your EMR Cluster:
aws emr describe-cluster --cluster-id j-ABCDEFGHIJKLM
This will output JSON (I have truncated this output to just the MASTER section):
{
"Cluster": {
"Id": "j-ABCDEFGHIJKLM",
"Name": "'Test01'",
....
"InstanceGroups": [
{
"Id": "ig-2EHOYXFABCDEF",
"Name": "Master Instance Group",
"Market": "ON_DEMAND",
"InstanceGroupType": "MASTER",
"InstanceType": "m3.xlarge",
"RequestedInstanceCount": 1,
"RunningInstanceCount": 1,
"Status": {
"State": "RUNNING",
"StateChangeReason": {
"Message": ""
},
"Timeline": {
"CreationDateTime": 1536626095.316,
"ReadyDateTime": 1536626533.886
}
},
"Configurations": [],
"EbsBlockDevices": [],
"ShrinkPolicy": {}
},
....
]
}
}
STEP 4: InstanceGroups is an array. Find the entry where InstanceGroupType is MASTER. Make note of the Id.
"Id": "ig-2EHOYXFABCDEF",
STEP 5: List your cluster instances:
aws emr list-instances --cluster-id j-ABCDEFGHIJKLM
This will output JSON (I have truncated the output):
{
"Instances": [
....
{
"Id": "ci-31LGK4KIECHNY",
"Ec2InstanceId": "i-0524ec45912345678",
"PublicDnsName": "ec2-52-123-201-221.us-west-2.compute.amazonaws.com",
"PublicIpAddress": "52.123.201.221",
"PrivateDnsName": "ip-172-31-41-111.us-west-2.compute.internal",
"PrivateIpAddress": "172.31.41.111",
"Status": {
"State": "RUNNING",
"StateChangeReason": {},
"Timeline": {
"CreationDateTime": 1536626164.073,
"ReadyDateTime": 1536626533.886
}
},
"InstanceGroupId": "ig-2EHOYXFABCDEF",
"Market": "ON_DEMAND",
"InstanceType": "m3.xlarge",
"EbsVolumes": []
}
]
}
STEP 6: Find the matching InstanceGroupId ig-2EHOYXFABCDEF. This will give you the EC2 Instance ID for the MASTER: "Ec2InstanceId": "i-0524ec45912345678"
Step 7: Tag your EC2 instance:
aws ec2 create-tags --resources i-0524ec45912345678 --tags Key=EMR,Value=MASTER
The above steps might be simpler with CLI Filters and / or jq, but this should be enough information so that you know how to find and tag the EMR Master Instance.
Below can be used to directly get instance Id
aws emr list-instances --cluster-id ${aws_emr_cluster.cluster.id} --instance-
group-id ${aws_emr_cluster.cluster.master_instance_group.0.id} --query
'Instances[*].Ec2InstanceId' --output text
In an enviroinment where you does not have the aws cli, you can cat the following file:
cat /mnt/var/lib/info/job-flow.json
An example of the content is the following one:
{
"jobFlowId": "j-0000X0X0X00XX",
"jobFlowCreationInstant": 1579512208006,
"instanceCount": 2,
"masterInstanceId": "i-00x0xx0000xxx0x00",
"masterPrivateDnsName": "localhost",
"masterInstanceType": "m5.xlarge",
"slaveInstanceType": "m5.xlarge",
"hadoopVersion": "2.8.5",
"instanceGroups": [
{
"instanceGroupId": "ig-0XX00XX0X0XXX",
"instanceGroupName": "Master - 1",
"instanceRole": "Master",
"marketType": "OnDemand",
"instanceType": "m5.xlarge",
"requestedInstanceCount": 1
},
{
"instanceGroupId": "ig-000X0XXXXXXX",
"instanceGroupName": "Core - 2",
"instanceRole": "Core",
"marketType": "OnDemand",
"instanceType": "m5.xlarge",
"requestedInstanceCount": 1
}
]
NOTE: i've omitted the ID of the jobs using 0 where a number is expected and X where a ltter is expected.
You can do this programmatically in 3 lines of code, without having to copy-paste any of the specific information:
# get cluster id
CLUSTER_ID=$(aws emr list-clusters --active --query "Clusters[0].Id" --output text)
# get instance id
INSTANCE_ID=$(aws emr list-instances --cluster-id $CLUSTER_ID --instance-group-types MASTER --query "Instances[0].Ec2InstanceId" --output text)
# tag
aws ec2 create-tags --resources $INSTANCE_ID --tags Key=EMR,Value=MASTER
Below example is for Instance Fleet, it saves Cluster ID, Instance Fleet ID and Master IP as environment variables.
Replace cluster name "My-Cluster" to the actual cluster name.
export CLUSTER_ID=$(aws emr list-clusters --active --query 'Clusters[?Name==`My-Cluster`].Id' --output text)
export INSTANCE_FLEET=$(aws emr describe-cluster --cluster-id $CLUSTER_ID | jq -r '.[].InstanceFleets | .[] | select(.InstanceFleetType=="MASTER") | .Id')
export PRIVATE_IP=aws emr list-instances --cluster-id $CLUSTER_ID --instance-fleet-id $INSTANCE_FLEET --query 'Instances[*].PrivateIpAddress' --output text
"Cleanest" way:
aws emr list-clusters --active
Search for Master cluster ID (j-xxxxxxxxxxx), then
aws emr list-instances --region {your_region} --instance-group-types MASTER --cluster-id j-xxxxxxxxxxxxx
Immediately filters out the master instance(s) with it's information using --instance-group-types MASTER flag.
For tagging refers to the other answers with aws {resource} create-tags and --tag flag.

How to extract a particular Key-Value Tag from ec2 describe-instances

I've got the following from describe-instances:
{
"Reservations": [
{
"Instances": [
{
"PublicDnsName": "ec2-xxxxx.amazonaws.com",
"Tags": [
{
"Key": "Name",
"Value": "yyyyy"
},
{
"Key": "budget_cluster",
"Value": "zzzzz"
},
{
"Key": "poc",
"Value": "aaaaaaa"
}
]
}
]
}
]
}
For each instance, I would like to extract the PublicDnsName and the value of the "budget_cluster" tag key. How to do this either with ec2 describe-instances or with jq ?
Modifying Frédéric's answer:
aws ec2 describe-instances --output text --query \
'Reservations[].Instances[].[PublicDnsName, Tags[?Key==`budget_cluster`].Value | [0]]'
Would produce:
ec2-xxxxx.amazonaws.com zzzzz
ec2-bbbbb.amazonaws.com yyyyy
I've changed the output to text, which removes as much formatting as possible and selected the individual tag value with | [0] since there will only ever be one per instance anyway. Finally, I removed the [] at the end so that the resulting list isn't flattened. That way in text output each entry will be on its own line.
You can also make this more robust by only selecting instances that actually have that tag. You could do so with further modifications to the --query parameter, but it is better in this case to use the --filters parameter since it does service-side filtering. Specifically you want the tag-key filter: --filters "Name=tag-key,Values=budget_cluster"
aws ec2 describe-instances --output text \
--filters "Name=tag-key,Values=budget_cluster" --query \
'Reservations[].Instances[?Tags[?Key==`budget_cluster`]].[PublicDnsName, Tags[?Key==`budget_cluster`].Value | [0]]'
Would still produce:
ec2-xxxxx.amazonaws.com zzzzz
ec2-bbbbb.amazonaws.com yyyyy
But over the wire you would only be getting the instances you care about, thus saving money on bandwidth.
Using jq 1.5 or later, the simplest approach is to use from_entries.
After a minimal fix of the illustrative input, the following invocation:
$ jq '.Reservations[]
| .Instances[]
| [.PublicDnsName, (.Tags|from_entries|.budget_cluster)]' input.json
produces:
[
"ec2-xxxxx.amazonaws.com",
"zzzzz"
]
If you do not have jq 1.5 or later, the following should work:
$ jq1.4 '.Reservations[]
| .Instances[]
| [.PublicDnsName, (.Tags[]|select(.Key=="budget_cluster") | .Value)]' input.json
The answer of #peak is great and I keep learning from him on the jq part but again you can achieve quite a lot from the AWS CLI
aws ec2 describe-instances --query \
'Reservations[].Instances[].{PublicDnsName:PublicDnsName, Budget:Tags[?Key==`budget_cluster`].Value}'
would produce
[
{
"PublicDnsName": "ec2-xxxxx.amazonaws.com",
"Budget": [
"zzzz",
]
}
]
If you do not want to make a new strict JSon out of it, just take the values
aws ec2 describe-instances --query \
'Reservations[].Instances[].[PublicDnsName, Tags[?Key==`budget_cluster`].Value][]'
will produce
[
"ec2-xxxxx.amazonaws.com",
[
"zzzz"
]
]