在 AWS Lightsail 管理中,隨著實例數量的增多,我們常常會遇到這樣一個問題:
“我知道某個公網 IP 地址,但不知道它關聯的是哪臺實例。”
或者:
“我有一批老舊的實例只知道 IP,需要一鍵定位并選擇刪除。”
如果你逐臺在 AWS 控制臺中點開每臺實例、查看其 IP,效率低下且極易出錯。本文將介紹如何通過 Python 腳本,批量查找綁定特定 IP 的實例,并可交互式地選擇是否刪除。該腳本支持自動遍歷多個區域、并發執行、異常處理,并可適應日常運維和資源審計場景。
?一、應用場景
-
批量清理使用特定 IP 的老舊實例
-
結合日志系統,從攻擊源 IP 快速定位實例
-
故障排查場景下,通過 IP 快速反查服務實例
-
IP 池資源回收后,核查哪些實例仍綁定老 IP
?二、技術準備
1. 安裝 boto3(AWS Python SDK)
pip install boto3
2. 配置 AWS 憑證
你需要準備一對具有 Lightsail:DeleteInstance
和 Lightsail:GetInstance
權限的 Access Key:
-
AWS_ACCESS_KEY_ID
-
AWS_SECRET_ACCESS_KEY
建議使用 IAM 用戶訪問密鑰,權限不要過大,避免誤刪其他資源。
📄 三、準備 IP 地址列表
創建一個 ip_list.txt
文件,每行一個目標 IP:
3.122.44.87
54.212.11.100
13.112.22.14
此列表中的 IP 是你想“反查”的 Lightsail 實例。
?四、腳本核心邏輯解析
腳本主要包含四個階段:
1. 并發遍歷所有支持的 Lightsail 區域
Lightsail 是按區域劃分的服務,實例只能出現在某個區域中,因此我們需要逐個區域去遍歷。腳本中使用了 ThreadPoolExecutor
提高并發效率,最多同時運行 15 個線程,快速查找。
2. 分頁獲取每個區域的所有實例
AWS 的 get_instances()
接口默認返回一頁,我們通過 nextPageToken
實現全量分頁拉取,避免遺漏任何實例。
3. 對每臺實例進行 IP 匹配
匹配邏輯基于實例的 publicIpAddress
字段,若 IP 存在且命中目標列表,即可視為命中。
4. 逐個提示用戶確認是否刪除
腳本找到目標實例后,會在終端提示你確認是否刪除該實例(y
執行刪除,其它跳過),確保人為決策參與,避免批量誤刪。
?五、完整腳本源碼
import boto3
from concurrent.futures import ThreadPoolExecutor, as_completed# AWS 憑證配置
AWS_ACCESS_KEY_ID = "你的AccessKey"
AWS_SECRET_ACCESS_KEY = "你的SecretKey"# 支持的 Lightsail 區域
lightsail_regions = ["us-east-1", "us-east-2", "us-west-2", "ca-central-1","eu-west-1", "eu-west-2", "eu-central-1","ap-south-1", "ap-northeast-1", "ap-northeast-2","ap-southeast-1", "ap-southeast-2"
]# 讀取 IP 列表
with open("ip_list.txt", "r", encoding="utf-8") as f:target_ips = set(line.strip() for line in f if line.strip())found_instances = {} # ip -> (name, region, state)# 分頁獲取實例
def get_all_instances_in_region(region):instances = []try:client = boto3.client("lightsail",region_name=region,aws_access_key_id=AWS_ACCESS_KEY_ID,aws_secret_access_key=AWS_SECRET_ACCESS_KEY)response = client.get_instances()instances.extend(response.get("instances", []))next_token = response.get("nextPageToken")while next_token:response = client.get_instances(pageToken=next_token)instances.extend(response.get("instances", []))next_token = response.get("nextPageToken")except Exception as e:print(f"[{region}] ? 獲取實例失敗:{e}")return instances# 匹配實例(并發線程任務)
def find_ip_in_region(region):results = []instances = get_all_instances_in_region(region)for ins in instances:ip = ins.get("publicIpAddress")if ip and ip in target_ips:results.append((ip, ins["name"], region, ins["state"]["name"]))return results# 多線程并發查找 IP 對應實例
with ThreadPoolExecutor(max_workers=15) as executor:futures = [executor.submit(find_ip_in_region, region) for region in lightsail_regions]for future in as_completed(futures):matches = future.result()for ip, name, region, state in matches:print(f"\n🔍 找到實例:")print(f" ? 實例名:{name}")print(f" ? 區域:{region}")print(f" ? 狀態:{state}")print(f" ? IP地址:{ip}")found_instances[ip] = (name, region, state)# 遍歷匹配結果,逐個確認是否刪除
for ip, (name, region, state) in found_instances.items():choice = input(f"\n?? 是否要刪除實例【{name}】(IP: {ip}, 區域: {region})?[y/N]: ").strip().lower()if choice == 'y':try:client = boto3.client("lightsail",region_name=region,aws_access_key_id=AWS_ACCESS_KEY_ID,aws_secret_access_key=AWS_SECRET_ACCESS_KEY)client.delete_instance(instanceName=name)print(f"? 實例 {name} 刪除成功")except Exception as e:print(f"? 刪除實例 {name} 失敗:{e}")else:print(f"?? 跳過實例 {name}")# 輸出未找到的 IP
for ip in target_ips:if ip not in found_instances:print(f"? 未找到 IP {ip} 對應的實例")
六、安全注意事項
-
刪除操作不可恢復,使用前務必確認 IP 與實例綁定關系準確
-
推薦先執行“只查找”版本腳本,確認命中目標后再啟用刪除邏輯
-
可將刪除部分封裝為函數,或加入
--dry-run
模式增強安全性 -
若大批量刪除建議加入備份(如自動創建快照)操作