EC2インスタンスの自動起動および停止システムを設定する方法

クラウドコンピューティングサービス（例えばAWS）を使用する場合、コストを管理してリソースを最適化することが重要です。予約インスタンスとは異なり、EC2インスタンスは使用した分だけ課金されるため、インスタンスがアクティブである時間はすべて課金されます。

EC2インスタンスは24時間365日稼働するため、積極的に管理しないとコストがすぐに高くなります。不要な費用を避けるためには、必要な時にのみこれらのインスタンスを起動し、使用が終了したらすぐに停止するシステムを導入することが推奨されます。

:::note info
これは特に開発サーバー、テストサーバー、ステージングサーバーに当てはまります。これらを24時間365日稼働させるのではなく、業務時間中のみ稼働させるべきです。そうしないと、無駄な費用がかかってしまいます！
:::

このプロセスを自動化することで、インスタンスが不要に稼働し続けないようにし、必要な時に確実に利用可能になるようにします。例えば、プロジェクト管理や会計などのサービスを管理するためにLaravelアプリケーションを使用している企業では、従業員が出社する際にこのアプリケーションを起動し、退社時に停止するようにスケジュールすることが可能です。

この自動化にはいくつかの利点があります：

1. **コスト削減:** インスタンスが使用されていないときに停止することで、クラウド料金の大幅な節約が可能です
2. **リソースの最適化:** クラウドリソースをより効率的に利用できるため、予算を他のプロジェクトに割り当てることができます
3. **簡単で効率的:** プロセスを自動化することで、インスタンスが必要な時に常に利用可能であり、人為的なミスのリスクを減らし、運用効率を向上させます


# AWS Lambda でEC2の起動・停止を行う

この記事では、AWS Amazonを使用してこれを実現する方法を紹介しますが、同じことをAWS CDKやAWS CLIなどを使用しても実行できます。

### インスタンスを起動する

```javascript
const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();

exports.handler = async (event, context) => {
    const instanceId = 'your-instance-id';
    await ec2.startInstances({ InstanceIds: [instanceId] }).promise();
    return 'Instance starting';
};
```

### インスタンスを停止する

```javascript
const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();

exports.handler = async (event, context) => {
    const instanceId = 'your-instance-id';
    await ec2.stopInstances({ InstanceIds: [instanceId] }).promise();
    return 'Instance stopping';
};
```

# Lambda関数をスケジュールするためのCloudWatch Eventsルールを作成する方法

特定の時間にインスタンスを操作するために、CloudWatch Eventsを使用します。

:::note info
サーバー上に独自のcronタブを作成することでほぼ同じことができますが、CloudWatch Eventsの方が適しています。
:::

## インスタンスの自動起動と停止をスケジュールする方法

例えば、月曜日から金曜日まで毎日、朝9時にインスタンスを起動し、夕方17時30分に停止するようにスケジュールしたいとします。

### インスタンスを9時に起動する (週末を除く毎日)

- CloudWatchに移動 > Rules > Create ruleを選択
- Event Source: Event Source > Schedule > Cron expression: 0 9 ? * MON-FRI *
- Target: Lambda function > インスタンスを起動するLambda関数を選択


### インスタンスを17時30分に停止する (週末を除く毎日)

- CloudWatchに移動 > Rules > Create ruleを選択
- Event Source: Event Source > Schedule > Cron expression: 30 17 ? * MON-FRI *
- Target: Lambda function > インスタンスを停止するLambda関数を選択

## 非アクティブ状態が5分続いた後に自動で停止する方法

コストをさらに削減するために、EC2インスタンスが5分間非アクティブ状態が続いた場合に自動的に停止するように設定します。

### 非アクティブ状態が5分続いた場合にEC2インスタンスを停止するLambda関数を作成する

```javascript
const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();
const cloudwatch = new AWS.CloudWatch();

exports.handler = async (event, context) => {
    const instanceId = 'your-instance-id';

    const metrics = await cloudwatch.getMetricStatistics({
        Period: 300,
        StartTime: new Date(Date.now() - 600000),
        EndTime: new Date(),
        MetricName: 'NetworkIn',
        Namespace: 'AWS/EC2',
        Statistics: ['Sum'],
        Dimensions: [{ Name: 'InstanceId', Value: instanceId }]
    }).promise();

    if (metrics.Datapoints.length > 0 && metrics.Datapoints[0].Sum === 0) {
        await ec2.stopInstances({ InstanceIds: [instanceId] }).promise();
        return 'Instance stopping for inactivity';
    } else {
        return 'Instance active';
    }
};
```

### Lambda関数を5分ごとに実行するためのCloudWatch Eventsルールを作成する

- CloudWatchに移動 > Rules > Create ruleを選択
- Event Source: Event Source > Schedule > Fixed rate of 5 minutesを選択
- Target: Lambda function > 非アクティブ状態を確認するLambda関数を選択