随着云计算技术的发展,越来越多的企业选择将业务部署在云端,阿里云作为国内领先的云服务提供商之一,为企业提供了丰富的云产品和服务。为了更好地管理这些资源,自动化工具变得尤为重要。本文介绍一个使用Python编写的自动化脚本,该脚本能够帮助我们收集阿里云上的弹性公网IP(EIP)、ECS实例及VPC等资源的信息,并将这些信息整合输出为易于阅读的格式,同时保存为Excel文件,便于后续的数据分析和管理。
脚本功能概述:
配置读取:从指定的配置文件中读取阿里云的访问密钥ID和密钥
客户端初始化:根据读取到的密钥信息,初始化VPC和ECS的客户端对象
地域信息获取:动态获取阿里云支持的所有地域信息
EIP信息收集:遍历所有地域,获取每个地域内的EIP信息,包括分配ID、名称、绑定的实例ID、实例类型和IP地址
ECS实例信息收集:对于每个绑定了EIP的ECS实例,收集其实例ID、名称和VPC ID
VPC信息收集:收集与ECS实例关联的VPC信息,包括VPC ID和名称
NAT网关信息收集:对于绑定到NAT网关的EIP,收集相关的VPC信息
数据整合与输出:将收集到的信息按照指定格式打印出来,并保存为Excel文件
技术要点:
多模块协作:脚本内部使用多个函数分别处理不同的任务,如读取配置、初始化客户端、获取不同类型的资源信息等,使得代码结构清晰且易于维护。
异常处理:虽然示例中没有具体展示异常处理逻辑,但在实际开发过程中,应当考虑对API请求失败等情况进行适当的错误处理。
API调用:利用阿里云SDK中的API接口,如DescribeEipAddresses、DescribeInstances、DescribeVpcs等,来获取所需的资源信息。
数据存储:利用Pandas库将收集到的数据整理为DataFrame格式,并使用openpyxl将数据导出至Excel文件,方便后续的数据分析工作。
设计思路
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 脚本名称: Global_EIPResource_info_from_aliyun_v1.0.1.py
# 用法: /usr/bin/python3 /data/python/aliyun/Global_EIPResource_info_from_aliyun_v1.0.1.py > /var/log/Global_EIPResource_info_from_aliyun_v1.0.1.py.log 2>&1
# 作者: 朱鹏飞(Richard) <zhupengfei@chagee.com>
# 日期: 2024年10月14日 09:35
# 更新:2024年10月15日 11:28
# SDK 安装命令:pip3 install alibabacloud_vpc20160428==6.9.3 -i https://pypi.org/simple && pip install alibabacloud_ecs20140526==4.4.3 -i https://pypi.org/simple && pip3 install --upgrade alibabacloud-vpc20160428 -i https://pypi.org/simple && pip3 install pandas openpyxl -i https://pypi.org/simple
# 注意事项:get_all_regions函数:使用DescribeRegions API动态获取所有可用的地域
####
### 设计可以通过以下方式实现:
## 1、调用DescribeEipAddresses接口获取EIP的详细信息,包括EIP的ID和绑定的实例ID。然后获取到相关绑定ECS实例ID
## 2、通过ECS实例ID,在调用调用DescribeInstances接口,获取ECS实例的名称和类型,以及它所在的VPC ID
## 3、用VPC ID调用DescribeVpcs接口,获取VPC的名称和详细信息
### 设计理想输出效果:
## 序号 实例ID/名称 IP地址 绑定实例类型/ID 专有网络
####
读取配置文件中的AK/SK
从配置文件中读取阿里云的Access Key ID和Access Key Secret,这是进行API调用的基础认证信息。通过configparser模块读取配置文件,确保了脚本能够安全地管理敏感信息
import configparser
def read_aksk_from_config():
config = configparser.ConfigParser()
config.read('/data/app/aliyun/aksk.ini')
access_key_id = config['it_zpf_w']['ALIBABA_CLOUD_ACCESS_KEY_ID']
access_key_secret = config['it_zpf_w']['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
return access_key_id, access_key_secret
初始化客户端
在各个阿里云产品间进行API调用,初始化了VPC和ECS两个客户端对象,它们将用于后续的资源查询操作。通过传递region_id参数,确保了客户端知道要操作哪个地域的资源
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_vpc20160428.client import Client as VpcClient
from alibabacloud_ecs20140526.client import Client as EcsClient
def init_client(region_id):
access_key_id, access_key_secret = read_aksk_from_config()
config = open_api_models.Config(
access_key_id=access_key_id,
access_key_secret=access_key_secret,
region_id=region_id
)
vpc_client = VpcClient(config)
ecs_client = EcsClient(config)
return vpc_client, ecs_client
获取所有可用地域
通过调用ECS产品的DescribeRegionsRequest来实现的
from alibabacloud_ecs20140526.models import DescribeRegionsRequest
def get_all_regions():
access_key_id, access_key_secret = read_aksk_from_config()
config = open_api_models.Config(
access_key_id=access_key_id,
access_key_secret=access_key_secret,
region_id='cn-shanghai'
)
ecs_client = EcsClient(config)
request = DescribeRegionsRequest()
response = ecs_client.describe_regions(request)
regions_info = response.body.to_map()
return [region['RegionId'] for region in regions_info['Regions']['Region']]
获取EIP信息
获取EIP信息是通过调用VPC产品的DescribeEipAddressesRequest实现的。这里使用了分页机制来确保可以获取所有的EIP信息
通过循环遍历直到获取不到新的数据为止,确保了所有EIP信息都被收集到
from alibabacloud_vpc20160428.models import DescribeEipAddressesRequest
def get_eip_info(vpc_client, region_id):
eips = []
page_number = 1
page_size = 50
while True:
request = DescribeEipAddressesRequest(
region_id=region_id,
page_number=page_number,
page_size=page_size
)
eip_response = vpc_client.describe_eip_addresses(request)
eip_info = eip_response.body.to_map()
eips.extend([
{
'AllocationId': eip['AllocationId'],
'Name': eip.get('Name', ''),
'InstanceId': eip.get('InstanceId', ''),
'InstanceType': eip.get('InstanceType', ''),
'IpAddress': eip['IpAddress']
}
for eip in eip_info['EipAddresses']['EipAddress']
])
if len(eip_info['EipAddresses']['EipAddress']) < page_size:
break
page_number += 1
return eips
获取ECS实例信息
获取ECS实例信息是通过调用ECS产品的DescribeInstancesRequest实现的。这里同样使用了分页机制来获取所有ECS实例的信息,并将结果存储在一个字典中
from alibabacloud_ecs20140526.models import DescribeInstancesRequest
def get_ecs_info(ecs_client, region_id):
ecs_instances = {}
page_number = 1
page_size = 50
while True:
request = DescribeInstancesRequest(
region_id=region_id,
page_number=page_number,
page_size=page_size
)
ecs_response = ecs_client.describe_instances(request)
ecs_info = ecs_response.body.to_map()
ecs_instances.update({
instance['InstanceId']: {
'InstanceId': instance['InstanceId'],
'Name': instance.get('InstanceName', ''),
'VpcId': instance['VpcAttributes']['VpcId']
}
for instance in ecs_info['Instances']['Instance']
})
if len(ecs_info['Instances']['Instance']) < page_size:
break
page_number += 1
return ecs_instances
获取VPC信息
通过调用VPC产品的DescribeVpcsRequest实现的。这段代码也是采用了分页机制来确保可以获取所有VPC的信息,并将其存储在一个字典中
from alibabacloud_vpc20160428.models import DescribeVpcsRequest
def get_vpc_info(vpc_client, region_id):
vpcs = {}
page_number = 1
page_size = 50
while True:
request = DescribeVpcsRequest(
region_id=region_id,
page_number=page_number,
page_size=page_size
)
vpc_response = vpc_client.describe_vpcs(request)
vpc_info = vpc_response.body.to_map()
vpcs.update({
vpc['VpcId']: {
'VpcId': vpc['VpcId'],
'VpcName': vpc.get('VpcName', '')
}
for vpc in vpc_info['Vpcs']['Vpc']
})
if len(vpc_info['Vpcs']['Vpc']) < page_size:
break
page_number += 1
return vpcs
获取NAT网关信息
通过调用VPC产品的DescribeNatGatewaysRequest实现的。这一部分也使用了分页机制来确保可以获取所有NAT网关的信息,并将结果存储在一个字典中
from alibabacloud_vpc20160428.models import DescribeNatGatewaysRequest
def get_nat_gateway_info(vpc_client, region_id):
nat_gateways = {}
page_number = 1
page_size = 50
while True:
request = DescribeNatGatewaysRequest(
region_id=region_id,
page_number=page_number,
page_size=page_size
)
nat_response = vpc_client.describe_nat_gateways(request)
nat_info = nat_response.body.to_map()
nat_gateways.update({
nat['NatGatewayId']: {
'VpcId': nat['VpcId'],
'VpcName': nat.get('VpcName', '')
}
for nat in nat_info['NatGateways']['NatGateway']
})
if len(nat_info['NatGateways']['NatGateway']) < page_size:
break
page_number += 1
return nat_gateways
整合信息并输出
获取所有可用的地域,然后针对每一个地域初始化VPC和ECS客户端,获取EIP信息、ECS实例信息、VPC信息以及NAT网关信息。最后,结合这些信息输出,并将数据保存为Excel文件
import pandas as pd
from datetime import datetime
def main():
all_regions = get_all_regions()
data = []
for region_id in all_regions:
vpc_client, ecs_client = init_client(region_id)
eips = get_eip_info(vpc_client, region_id)
ecs_instances = get_ecs_info(ecs_client, region_id)
vpcs = get_vpc_info(vpc_client, region_id)
nat_gateways = get_nat_gateway_info(vpc_client, region_id)
# 结合信息并输出
print(f"Region: {region_id}")
print("序号 实例ID/名称 IP地址 绑定实例类型/ID 专有网络")
for idx, eip in enumerate(eips, start=1):
instance_id = eip['InstanceId']
instance_type = eip['InstanceType']
vpc_id = ''
vpc_name = ''
if instance_type == 'EcsInstance':
vpc_id = ecs_instances.get(instance_id, {}).get('VpcId', '')
vpc_name = vpcs.get(vpc_id, {}).get('VpcName', '')
elif instance_type == 'Nat':
vpc_id = nat_gateways.get(instance_id, {}).get('VpcId', '')
vpc_name = vpcs.get(vpc_id, {}).get('VpcName', '')
print(f"{idx} {eip['Name'] or eip['AllocationId']} {eip['IpAddress']} {instance_type}/{instance_id} {vpc_id} {vpc_name}")
data.append({
"Region": region_id,
"序号": idx,
"实例ID/名称": eip['Name'] or eip['AllocationId'],
"IP地址": eip['IpAddress'],
"绑定实例类型/ID": f"{instance_type}/{instance_id}",
"专有网络": f"{vpc_id} {vpc_name}"
})
# 保存到Excel文件
df = pd.DataFrame(data)
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
filename = f"/data/tmp/global_resource_info_{timestamp}.xlsx"
df.to_excel(filename, index=False)
print(f"数据已保存到 {filename}")