lightsail 批量开启端口及检测实例状态

494 阅读3分钟

关于lightsail

  • Amazon Lightsail 以经济实惠的月度价格提供易于使用的虚拟专用服务器 (VPS) 实例、容器、存储、数据库等。
  • lightsail 和国内公有云厂商的轻量应用服务器类似,都是通过 计算+存储+网络 的方式以套餐的方式进行售卖。相比云服务器而言,多出了一些应用镜像,价格相对较低,可以说是对开发者相当友好了。

需求背景

  • 如果只是一台机器的话,很多操作大家都可以在aws的lightsail控制台完成。但是如果是多台,甚至几百台机器的话管理上就是一个大问题了。
  • 本文会描述两个场景:创建机器的时候需要开服务器的端口,lightsail不支持多台机器共用一个端口规则,如果是多台机器的话需要一台一台的去设置。各位,请不要质疑我的判断。这个过程会非常痛苦,亲身经历一个小时大概只能设置几十台。不仅考验手速,也很考验大家的网络质量。

具体实现

  • 如果只是设置几十台机器也还好,搞一个小时就能过去。但是如果是几百甚至上千台,这个真的要把人搞奔溃了。而且除了改端口的规则之外,还有有一个新的需求:aws的lightsail 虽然和国内云服务商的轻量应用服务器很类似,但是cpu这里是不太一样的,国内 阿里云、腾讯云 都保证cpu是100%性能,但是lightsail 的cpu并不是100%,它会有一个基准的cpu性能,具体取决于 lightsail 的规格,超出的时候会消耗cpu积分,如果cpu积分消耗殆尽机器很容易死机。要从几百台机器中找到死机的机器也是一件很痛苦的事情了。
  • 好在aws有提供api接口,我们可以借助api批量去开通lightsail实例的端口,以及检测它们的运行状态。

环境准备

  • 这里使用aws提供的python工具包Boto3,python版本需要是3.7或以上。

  • 还需要安装aws configure用来配置AK,AK可以在aws的控制台去创建。

用到的接口

  • GetInstances:用来获取账号下对应地域的实例列表,当实例列表大于20个时,需要注意下响应的 nextPageToken 这个分页参数
  • OpenInstancePublicPorts:用于开启lightsail实例的端口
  • RebootInstance:用于重启指定机器
import boto3
import json
from botocore.config import Config
import telnetlib

def get_config(region_name):
    return Config(region_name=region_name)

def get_client(region_name):
    return boto3.client('lightsail', config=get_config(region_name))

def open_ports(client, instance_name):
    client.open_instance_public_ports(
        portInfo={
            'fromPort': 1024,
            'toPort': 65535,
            'protocol': 'tcp',
            'cidrs': [
                '0.0.0.0/0',
            ],
            'ipv6Cidrs': [
                '::/0',
            ]
        },
        instanceName=instance_name
    )

    client.open_instance_public_ports(
        portInfo={
            'fromPort': 1024,
            'toPort': 65535,
            'protocol': 'udp',
            'cidrs': [
                '0.0.0.0/0',
            ],
            'ipv6Cidrs': [
                '::/0',
            ]
        },
        instanceName=instance_name
    )

    client.open_instance_public_ports(
        portInfo={
            'fromPort': -1,
            'toPort': -1,
            'protocol': 'icmp',
            'cidrs': [
                '0.0.0.0/0',
            ]
        },
        instanceName=instance_name
    )

def get_instances_list(client, result, instances):
    if('nextPageToken' in result):
        instances += result['instances']
        result = client.get_instances(pageToken = result['nextPageToken'])
        return get_instances_list(client, result, instances)
    else:
        return instances + result['instances']

def reboot_instace(client, instance_name):
    client.reboot_instance(instanceName=instance_name)

def check_ssh_port(instace_ip):
    try:
        telnetlib.Telnet(host=instace_ip, port="22", timeout=3)
        return True
    except:
        return False



if __name__ == '__main__':

    regions = [
               # 'eu-west-1',
               # 'eu-west-2',
               # 'eu-west-3',
               # 'eu-central-1',
               # 'ca-central-1',
               # 'us-east-1',
               # 'eu-north-1',
               # 'us-east-2',
               # 'ap-south-1',
               # 'us-west-2',
               # 新加坡
               'ap-southeast-1',
               # 首尔
               # 'ap-northeast-2',
               # 东京
               # 'ap-northeast-1',
               # 'ap-southeast-2'
    ]

    count = 0
    for i in range(0, len(regions)):
        client = get_client(regions[i])
        result = client.get_instances()
        instances = get_instances_list(client, result, [])
        count += len(instances)
        for i in  range(0, len(instances)):
            instance_name = instances[i]['name']
            instance_ip = instances[i]['publicIpAddress']
            # print(instance_name)
            print(instance_ip)

            # 判断实例22端口状态,如果不通就重启服务器
            # status = check_ssh_port(instance_ip)
            # print('端口状态: '+ str(status))
            # if(status == False):
            #     reboot_instace(client, instance_name)

            # 打开实例指定端口
            open_ports(client, instances[i]['name'])

    print('账号下一共 '+str(count) +' 个实例')
  • 相关链接:
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lightsail.html
https://docs.aws.amazon.com/lightsail/2016-11-28/api-reference/Welcome.html