重新启动网站上的EC2实例不可用

时间:2018-08-10 11:47:00

标签: amazon-web-services amazon-ec2

我在EC2服务器上托管了一个网站。如果网站在特定时间段(例如60秒)内不可用,我想监视网站端点并重新启动EC2实例。 我在AWS中使用什么工具?如何实现?

3 个答案:

答案 0 :(得分:2)

这不是推荐的方法。

首先,如果网站不可用,您可能想调查原因,而不仅仅是重启实例。您的目标应该是通过消除问题的根本原因来运行稳定的系统,而不是通过始终重新启动来忽略问题。

建议的设计应在高度可用配置中运行,并带有:

  • 该应用程序在至少两个可用区域的至少两台服务器上运行(如果AZ失败)。这不一定会比较昂贵,因为每个服务器都可以比单个大型服务器小。
  • 实例前面的负载均衡器,用于将流量分配给实例。负载均衡器还会执行连续的运行状况检查,并停止向运行状况检查失败的服务器发送请求
  • 一个 Auto Scaling组,它可以终止运行状况不佳的实例并自动启动替换服务器。如果可用区出现故障,这也很好。

在此设计中,不健康的实例将被终止(终止并销毁),并使用预定义的磁盘映像和启动脚本创建一个新实例。或者,您可以选择将不良实例移出Auto Scaling组以调查问题,然后启动新实例代替它。

如果您的应用程序需要数据库,则数据库应在实例外部,以便所有实例都可以连接到数据库,并且替换应用程序实例不会造成任何数据丢失。

关于在服务器上发现问题的速度,负载平衡器可以每隔几秒钟执行一次检查。另一方面,Amazon CloudWatch至少需要一分钟来检测问题(由于指标是在一段时间内计算的,而不是“现在”的指标,因此可能需要更长的时间)。

答案 1 :(得分:2)

约翰的方法是正确的,但最简单的方法是

  • 编写一个可以查询您的网站的lambda函数,以查看其是否正在运行,以及是否没有该lambda函数来重新启动实例。
  • 设置以您确定的调用lambda函数的频率运行的cloudwatch事件规则

我将留给您编写确定网站是否正常运行的代码并重新启动服务器的工作-但这很简单。您可以在lambda函数中使用python,java,node,go或.net核心-在这种情况下,我认为python是最简单的,但这是一种看法。

答案 2 :(得分:1)

很明显,这不是AWS的最佳做法,但可以说是有道理-例如您正在运行一个需求低的小型个人Web服务器,而可用性比成本要少。

至少那是我为其构建自动化的原因。

图表 enter image description here

lambda代码

import json
import os
import boto3
import time

env_vars = [
    'ALARM_NAME',
    'REGION',
    'INSTANCE_ID',
    'OUTPUT_SNS_ARN'
    ]

ENV = {}

for env_var in env_vars:
    ENV[env_var] = os.environ.get(env_var, None)
    if not ENV[env_var]:
        raise Exception(f"Environment variable {env_var} must be set!")


def reboot_instance(instanceID, regionName) -> "instanceID":
    """
    InstanceID
    instanceID - ID of instance
    regionName - name of region

    return InstanceID or False in case of exception
    """
    ec2 = boto3.resource('ec2', region_name=regionName)
    instance = ec2.Instance(instanceID)

    try:
        instance.stop()
        time.sleep(30)
        instance.stop(Force=True)
    except:
        pass

    for i in range(180): # wait 3 minutes
        instance = ec2.Instance(instanceID)
        if instance.state['Code'] == 80:
            break
        time.sleep(1)
    else:
        raise Exception('Unable to stop instance')

    instance.start()
    return instanceID


def notify_about_reboot(instanceID, snsarn) -> True:
    """
    Put SNS message about reboot to snsarn
    """
    client = boto3.client('sns', region_name='us-east-1')
    client.publish(TopicArn=snsarn, Message=f'EC2 instance {instanceID} was rebooted!')
    return True


def lambda_handler(event, context) -> "status about reboot":
    """
    event: see events/event.json 
    """
    print('EVENT:')
    print(event)
    for record in event.get('Records', None):
        sns = record.get('Sns', None)
        message = json.loads(sns.get('Message', None))
        msgalarm =  message.get('AlarmName', None)
        msgstatus = message.get('NewStateValue', None)

        if not all([sns,message,msgalarm,msgstatus]):
            continue

        if (msgalarm == ENV['ALARM_NAME']) and (msgstatus == 'ALARM'):
            notify_about_reboot(reboot_instance(ENV['INSTANCE_ID'], ENV['REGION']), ENV['OUTPUT_SNS_ARN'])
            return 'rebooting'
        else:
            return 'nothing to do'

    return 'no sns record found'

我已经在https://github.com/koss822/misc/tree/master/Aws/route53-healthcheck-instance-reboot

上发布了带有SAM模板和安装说明的经过全面测试的自动化