1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CDK で Amazon Lightsail にロードバランサーを追加してみた!

1
Posted at

はじめに

前回 Amazon Lightsail(以降:Lightsail)にディストリビューションを追加し、キャッシュを利用することで負荷テストの結果にどのぐらい違いが出るか確認してみました。
今回は Lightsail にロードバランサーを追加し負荷テストの結果を比較してみました。
※2026年3月時点の情報を元に作成しています。

対象読者

  • AWS CDK を試してみたい方
  • WordPress を手軽に始めてみたい方
  • Lightsail のスペックや月額料金を知りたい方

おことわり

構成図や構成図の注意点は前回の記事をご参照ください。

ロードバランサーの月額料金

  • 18 USD

ターゲットとして利用したいインスタンスをあらかじめ作成し、ロードバランサーにアタッチしておく必要があります。
別途起動したインスタンス数の Lightsail 料金がかかります。

CDK を試してみました

事前準備

実行環境は前回のとおりです。

ステップ 5 の「CDK環境の初期化(ブートストラップ)」まで終わっていることを想定しています。


ステップ1:CDK ファイル作成とデプロイ

1-1. 作業ディレクトリの作成

lightsail-alb-wordpress というディレクトリを作成しています。
お好きな名前に変更してください。

> mkdir lightsail-alb-wordpress && cd lightsail-alb-wordpress
lightsail-alb-wordpress>

1-2. CDK プロジェクトの作成

lightsail-alb-wordpress> cdk init app --language=typescript
lightsail-alb-wordpress> npm install dotenv --save

※成功すると lightsail-alb-wordpress 内にいろいろファイルが作られます。


1-3. スタック(Stack)の修正

lightsail-alb-wordpress/lib/lightsail-alb-wordpress-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lightsail from 'aws-cdk-lib/aws-lightsail';

export interface LightsailAlbWordPressStackProps extends cdk.StackProps {
  /**
   * インスタンス名
   */
  lightsailInstanceName: string;
  /**
   * インスタンスのスペック(BundleId)
   */
  lightsailBundleId: string;
  /**
   * WordPressのバージョン
   */
  lightsailBlueprintId: string;
  /**
   * 自動スナップショットの時間 (UTC, HH:00) (オプション)
   */
  lightsailAutoSnapshotTime?: string;
  /**
   * ロードバランサー名
   */
  lightsailLoadBalancerName?: string;
  /**
   * インスタンス数
   */
  lightsailInstanceCount?: number;
  /**
   * ロードバランサーのヘルスチェックパス
   */
  lightsailHealthCheckPath?: string;
  /**
   * ロードバランサーのヘルスチェックポート
   */
  lightsailHealthCheckPort?: number;
}

export class LightsailAlbWordPressStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: LightsailAlbWordPressStackProps) {
    super(scope, id, props);

    if (!props) {
      throw new Error('LightsailAlbWordPressStackProps must be provided');
    }

    const instanceName = props.lightsailInstanceName || 'WordPressAlbInstance';
    const bundleId = props.lightsailBundleId || 'small_3_0';
    const bluePrintId = props.lightsailBlueprintId || 'wordpress';
    const snapshotTime = props?.lightsailAutoSnapshotTime || '18:00';
    const loadBalancerName = props.lightsailLoadBalancerName || 'WordPressLoadBalancer';
    const instanceCount = props.lightsailInstanceCount || 2;
    const healthCheckPath = props.lightsailHealthCheckPath || '/';
    const healthCheckPort = props.lightsailHealthCheckPort || 80;

    // 1. ファイアウォールルールの定義
    const firewallRules: lightsail.CfnInstance.PortProperty[] = [
      { fromPort: 80, toPort: 80, protocol: 'tcp', accessFrom: 'Anywhere (Internet)', accessType: 'public' },
      { fromPort: 443, toPort: 443, protocol: 'tcp', accessFrom: 'Anywhere (Internet)', accessType: 'public' },
      { fromPort: 22, toPort: 22, protocol: 'tcp', cidrListAliases: ['lightsail-connect', 'lightsail-setup-ipv4'], accessType: 'public' },
    ];

    // 2. 複数の Lightsail インスタンスを作成
    const wpInstances: lightsail.CfnInstance[] = [];
    const instanceNames: string[] = [];

    for (let i = 0; i < instanceCount; i++) {
      const currentInstanceName = `${instanceName}-${i + 1}`;
      instanceNames.push(currentInstanceName);

      const wpInstance = new lightsail.CfnInstance(this, `WordPressInstance${i + 1}`, {
        instanceName: currentInstanceName,
        blueprintId: bluePrintId,
        bundleId: bundleId,
        availabilityZone: this.availabilityZones[i % this.availabilityZones.length],
        networking: {
          ports: firewallRules,
        },
        addOns: [
          {
            addOnType: 'AutoSnapshot',
            autoSnapshotAddOnRequest: { snapshotTimeOfDay: snapshotTime },
          },
        ],
      });

      wpInstances.push(wpInstance);

      // スタティック IP を作成
      const staticIpName = `${currentInstanceName}-static-ip`;
      const staticIp = new lightsail.CfnStaticIp(this, `WordPressStaticIp${i + 1}`, {
        staticIpName: staticIpName,
        attachedTo: wpInstance.instanceName,
      });

      staticIp.addDependency(wpInstance);

      // 出力
      new cdk.CfnOutput(this, `LightsailInstanceName${i + 1}`, {
        value: wpInstance.instanceName,
        description: `Lightsailのインスタンス名 (${i + 1})`,
      });

      new cdk.CfnOutput(this, `LightsailStaticIpAddress${i + 1}`, {
        value: staticIp.attrIpAddress,
        description: `Lightsailのスタティック IP アドレス (${i + 1})`,
      });
    }

    // 3. Lightsail ロードバランサーの作成
    const loadBalancer = new lightsail.CfnLoadBalancer(this, 'WordPressLoadBalancer', {
      loadBalancerName: loadBalancerName,
      instancePort: healthCheckPort,
      healthCheckPath: healthCheckPath,
      sessionStickinessEnabled: true, // ログイン状態を維持するため、スティッキーセッション (Sticky Session)を有効
      sessionStickinessLbCookieDurationSeconds: '86400', // 24時間
      tags: [
        {
          key: 'Name',
          value: loadBalancerName,
        },
      ],
    });

    // 注:CDKの現在のバージョンではLoadBalancerTargetGroupが完全にサポートされていないため、
    // 以下のコメント部分を参考に、AWS CLIまたはコンソールでインスタンスをアタッチしてください

    // AWS CLI コマンド例:
    // aws lightsail attach-instances-to-load-balancer \
    //   --load-balancer-name WordPressLoadBalancer \
    //   --instance-names WordPressInstance-1 WordPressInstance-2 \
    //   --region ap-northeast-1

    // 出力
    new cdk.CfnOutput(this, 'LightsailLoadBalancerName', {
      value: loadBalancer.loadBalancerName,
      description: 'Lightsailロードバランサー名',
    });

    new cdk.CfnOutput(this, 'LightsailLoadBalancerArn', {
      value: loadBalancer.attrLoadBalancerArn,
      description: 'Lightsailロードバランサー ARN',
    });

    new cdk.CfnOutput(this, 'InstanceAttachmentCommand', {
      value: `aws lightsail attach-instances-to-load-balancer --load-balancer-name ${loadBalancerName} --instance-names ${instanceNames.join(
        ' '
      )} --region ${this.region}`,
      description: '実行必須: インスタンスをロードバランサーにアタッチするコマンド',
    });
  }
}

1-4. アプリ(App)

lightsail-alb-wordpress/bin/lightsail-alb-wordpress.ts
import * as cdk from 'aws-cdk-lib';
import { LightsailAlbWordPressStack } from '../lib/lightsail-alb-wordpress-stack';
import * as dotenv from 'dotenv';

dotenv.config(); // .envファイルを読み込む

const app = new cdk.App();

const lightsailInstanceName = process.env.LIGHTSAIL_INSTANCE_NAME;
const lightsailBundleId = process.env.LIGHTSAIL_BUNDLE_ID;
const lightsailBlueprintId = process.env.LIGHTSAIL_BLUEPRINT_ID;
const lightsailAutoSnapshotTime = process.env.LIGHTSAIL_AUTO_SNAPSHOT_TIME;
const lightsailLoadBalancerName = process.env.LIGHTSAIL_LOAD_BALANCER_NAME;
const lightsailInstanceCount = parseInt(process.env.LIGHTSAIL_INSTANCE_COUNT || '2', 10);
const lightsailHealthCheckPath = process.env.LIGHTSAIL_HEALTH_CHECK_PATH || '/';
const lightsailHealthCheckPort = parseInt(process.env.LIGHTSAIL_HEALTH_CHECK_PORT || '80', 10);
const cdkDefaultAccount = process.env.CDK_DEFAULT_ACCOUNT;
const cdkDefaultRegion = process.env.CDK_DEFAULT_REGION || 'ap-northeast-1';

// 必須の環境変数のチェック
if (!lightsailInstanceName || !lightsailBundleId || !lightsailBlueprintId) {
  throw new Error(
    '以下の環境変数が.envファイルに設定されていません: LIGHTSAIL_INSTANCE_NAME, LIGHTSAIL_BUNDLE_ID, LIGHTSAIL_BLUEPRINT_ID'
  );
}

new LightsailAlbWordPressStack(app, 'LightsailAlbWordPressStack', {
  // 環境変数から設定値を読み込む
  lightsailInstanceName: lightsailInstanceName,
  lightsailBundleId: lightsailBundleId,
  lightsailBlueprintId: lightsailBlueprintId,
  lightsailAutoSnapshotTime: lightsailAutoSnapshotTime,
  lightsailLoadBalancerName: lightsailLoadBalancerName,
  lightsailInstanceCount: lightsailInstanceCount,
  lightsailHealthCheckPath: lightsailHealthCheckPath,
  lightsailHealthCheckPort: lightsailHealthCheckPort,
  env: {
    account: cdkDefaultAccount || process.env.CDK_DEFAULT_ACCOUNT,
    region: cdkDefaultRegion || process.env.CDK_DEFAULT_REGION,
  },
});

app.synth();

1-5. 環境変数

lightsail-alb-wordpress/.env
# AWS Configuration
CDK_DEFAULT_ACCOUNT=
CDK_DEFAULT_REGION=

# Lightsail Configuration
LIGHTSAIL_INSTANCE_NAME=WordPressAlbInstance

# 指定できる値は下記コマンドよりご確認ください。
# aws lightsail get-bundles --region ap-northeast-1 --query 'bundles[].{price:price,cpuCount:cpuCount,ramSizeInGb:ramSizeInGb,diskSizeInGb:diskSizeInGb,bundleId:bundleId,instanceType:instanceType,supportedPlatforms:supportedPlatforms[0]}' --output table
LIGHTSAIL_BUNDLE_ID=medium_3_0

# 指定できる値は下記コマンドよりご確認ください。
# aws lightsail get-blueprints --region ap-northeast-1 --query 'blueprints[].{blueprintId:blueprintId,name:name,group:group,productUrl:productUrl,platform:platform}' --output table
LIGHTSAIL_BLUEPRINT_ID=wordpress

# 自動スナップショットの時間 (HH:00 形式、UTC時間)
# 日本時間 (JST) 03:00 に実行したい場合は UTC 18:00
LIGHTSAIL_AUTO_SNAPSHOT_TIME=18:00

# ロードバランシング設定
# ロードバランサー名
LIGHTSAIL_LOAD_BALANCER_NAME=WordPressLoadBalancer

# インスタンス数(ロードバランシング対象)
LIGHTSAIL_INSTANCE_COUNT=2

# ロードバランサーのヘルスチェック設定
LIGHTSAIL_HEALTH_CHECK_PATH=/
LIGHTSAIL_HEALTH_CHECK_PORT=80

環境に合わせて変更してください。
SSH の接続は WordPress の管理者パスワード確認時に利用します。

1-6. デプロイ

lightsail-alb-wordpress> cdk deploy

時間がかかりますので気長に待ちましょう!

1-7. ロードバランサーにアタッチ

CDK では LoadBalancerTargetGroup が完全にサポートされていないため、以下 AWS CLI でインスタンスをアタッチしてください。

lightsail-alb-wordpress> aws lightsail attach-instances-to-load-balancer --load-balancer-name [ロードバランサー名] --instance-names [Lightsail インスタンス名] --region [デプロイリージョン]

例:ap-northeast-1 にデプロイされた Lightsail インスタンス名:「WordPressAlbInstance-1」「WordPressAlbInstance-2」「WordPressAlbInstance-3」をロードバランサー名:WordPressLoadBalancer にアタッチする

> aws lightsail attach-instances-to-load-balancer --load-balancer-name WordPressLoadBalancer --instance-names WordPressAlbInstance-1 WordPressAlbInstance-2 WordPressAlbInstance-3 --region ap-northeast-1

ステップ2:WordPress へのアクセス方法

  1. AWSマネジメントコンソールにログイン

  2. Lightsail サービスにアクセス
    Lightsail サービス

  3. 「Instances」から作成したインスタンス名(例「WordPressAlbInstance-1」)をクリック
    画面キャプチャはアタッチされたインスタンス数 2 つの場合です。
    Instances

  4. Networking をクリック
    Networking

  5. ロードバランサー名(例「WordPressLoadBalancer」)をクリック
    ロードバランサー名

  6. DNS name をコピー
    DNS name

  7. DNS name の URL をブラウザに入力すると、WordPress の初期画面が表示されました!
    WordPress の初期画面


負荷テスト

Lightsail と WordPress の前提条件

  • ディストリビューションは有効にしていません。
  • WordPress は初期インストール状態のままです。プラグインも設定していません。
  • 負荷テストは Apache 標準の Apache Bench (ab) コマンドを使用します。

本番環境で負荷テストは行わないでください。

負荷テストの不合格判定基準やシナリオなどは前回と一緒です。


負荷テスト結果

アタッチしたインスタンス数 2 の場合

インスタンス ウォームアップ (c=1) フェーズ 1 (c=5) フェーズ 2 (c=10) フェーズ 3 (c=20) フェーズ 4 (c=50) フェーズ 5 (c=100)
nano_3_0 × (3.4s) × (16.1s) × (30.6s)
micro_3_0 × (5.5s) × (8.4s)
small_3_0 × (1.8s)
medium_3_0 × (6.7s)
large_3_0 × (5.3s)

アタッチしたインスタンス数 3 の場合

インスタンス ウォームアップ (c=1) フェーズ 1 (c=5) フェーズ 2 (c=10) フェーズ 3 (c=20) フェーズ 4 (c=50) フェーズ 5 (c=100)
nano_3_0 × (4.7s) × (11.5s) × (6.6s)
micro_3_0 × (5.3s) × (8.4s)
small_3_0 × (2.97s) × (4.8s)
medium_3_0 × (6.73s)
large_3_0 × (4.06s)

○: 基準をクリア(合格)、×: 基準を超過(不合格、括弧内は応答時間)

本記事に基づき作成した環境での参考値です。
開発する際は、作った環境で改めて確認してみてください。


負荷テストの結果

アタッチされたインスタンス数を 2 つから 3 つに増やしたが、むしろ悪化(small_3_0 のフェーズ 4 が NG)した。
どうやらインスタンス毎に適切なチューニングを行う必要がありそうです。
チューニングについては次回記事にまとめたいと思います。

後始末

  1. 以下のコマンドを実行します。
lightsail-alb-wordpress> cdk destroy
  1. 削除されました!

まとめ

今回は CDK で Lightsail にロードバランサーを設定し負荷テストを試してみました。
Lightsail の場合、予めターゲットグループで起動したいインスタンス数を起動し、ロードバランサーにアタッチしておく必要がありました。
また、インスタンスのチューニングを適切に行わないと同時接続数などがボトルネックになっているようでした。
この後、調べて次回記事にしてみます。

この記事が、誰かのお役に立てば幸いです。

参考サイト

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?