Auto ScalingさせたEC2インスタンスのIPアドレスを固定しようとするのは止めよう

Auto ScalingさせたEC2インスタンスのIPアドレスを固定しようとするのは止めよう

無理やりできないことはないけど、本当にそれを実現する必要があるのか
Clock Icon2023.10.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

のっぴきならない事情でAuto ScalingするEC2インスタンスのIPアドレスを固定する必要がある

こんにちは、のんピ(@non____97)です。

皆さんはAuto ScalingさせたEC2インスタンスのIPアドレスを固定したいなと思ったことはありますか? 私はありません。

ここで言うIPアドレスの固定というのは、「このサーバーのIPアドレスは10.10.10.10を割り当てる」のようにサーバーとIPアドレスを1:1で紐づけることを指しています。

個人的にはEC2インスタンスのIPアドレスを固定にするのは好きではありません。単純なコンピューティングリソースとして使い、いわゆる「ペットではなく家畜」として扱うべきだと考えます。

使い捨て可能なリソースを使⽤する

抜粋 : AWS設計のベストプラクティスで最低限知っておくべき10のこと_20200617_rev.pdf

しかし、ファイアウォールでどうしても/24などレンジで開けるのがNGで、必ずホストアドレス(/32)で指定する必要があったり、連携するシステムの都合で事前にホスト名とIPアドレスを1:1でマッピングする必要があったりします。

要するに、Auto Scalingする場合でも以下記事でも紹介したように「のっぴきならない事情でEC2インスタンスに割り当てられるIPアドレスを固定にする必要がある」ということです。

Auto Scaling Groupや起動テンプレートには「指定した範囲のIPアドレスを上から順番に使用する」といった設定はありません。指定されたサブネットの中で自動で割り当てられます。

ただし、事前にセカンダリのENIを作成しておき、EC2インスタンス起動後にENIをアタッチすることで対応できなくはないです。「事前にIPアドレスをプールしておいて、必要にあったら割り当てる」といったイメージです。「プライマリIPアドレスを固定にする」といったことは、先述のとおりAuto Scalingの仕様上できません。

実際に試してみたので紹介します。

いきなりまとめ

  • 事前にセカンダリのENIを作成しておき、EC2インスタンス起動後にENIをアタッチすることで対応できなくはない
    • 最大キャパシティの数分だけENIを作成する
    • 最大キャパシティはAuto Scalingのサブネット数の倍数でなければ、セカンダリENIが割り当てられない可能性がある
  • AZの偏りがない場合、どのサブネットにデプロイされるかはランダムであるため、AZ間で一意なホスト名とIPアドレスをマッピングすることはできない
  • 送信元IPアドレスを固定にする必要がある場合はMetricを変更して、セカンダリENIのデフォルトルートをプライマリENIのデフォルトルートよりも優先度を高くする必要がある
  • IPアドレスを固定する要件があるのであれば、それはAuto Scalingさせるべきではない
    • サービスが想定していない使い方で無理やり運用に乗せると、いつか痛い目に合う
  • 設定ファイルに自身のIPアドレスを埋め込む必要があるのであれば、ユーザーデータを活用する

やってみる

仕組み

事前にセカンダリのENIを作成しておき、EC2インスタンス起動後にENIをアタッチします。

セカンダリENIの作成部分です。

ENIはAuto Scaling Groupで設定する最大キャパシティの数分だけデプロイします。

Auto Scaling Groupの最大キャパシティが8つの場合 ENIも8つ作成

セカンダリENIはAuto Scaling Groupで指定されている各サブネットに均等に作成します。セカンダリIPアドレスに割り当てるIPアドレスは各サブネットの先頭から順番に割り当てます。

また、セカンダリENIにはOSのホスト名用のタグHostNameを付与します。ホスト名は<プレフィックス>-<AZ名>-<AZ内での連番>.<ドメイン>です。

手動で作成することも考えましたが、面倒だったのでAWS CDKで作成しました。実際のコードは以下のとおりです。渡されたCIDRから割り当てるIPアドレスを計算するのが結構大変でした。

    // Generate IP Address
    const generateIpAddress = (cidr: string, index: number): string => {
      const [networkAddress, mask] = cidr.split("/");
      const networkAddressOctets = networkAddress.split(".").map(Number);
      const maskBit = Number(mask);
      const availableIpAddressesNumber = Math.pow(2, 32 - maskBit) - 5;
      const startIpAddressBit =
        networkAddressOctets.reduce(
          (accumulator, current, index) =>
            accumulator + (current << ((3 - index) * 8)),
          0
        ) + 4;

      if (index < 0 || index >= availableIpAddressesNumber) {
        return "Error: The provided index is out of range.";
      }

      const ipAddressBit = startIpAddressBit + index;

      const ipAddress = [3, 2, 1, 0]
        .map((shift) => (ipAddressBit >>> (shift * 8)) % 256)
        .join(".");

      return ipAddress;
    };

    // ENI
    const subnet = props.vpc.selectSubnets({
      subnetGroupName: "Public",
    }).subnets;

    for (let i = 0; i < maxCapacity; i++) {
      const subnetId = subnet[i % subnet.length].subnetId;
      const subnetCidr = subnet[i % subnet.length].ipv4CidrBlock;
      const availabilityZone = subnet[i % subnet.length].availabilityZone;

      new cdk.aws_ec2.CfnNetworkInterface(this, `Eni${i}`, {
        subnetId,
        groupSet: [this.asg.connections.securityGroups[0].securityGroupId],
        privateIpAddress: generateIpAddress(
          subnetCidr,
          Math.floor(i / subnet.length)
        ),
        tags: [
          {
            key: "HostName",
            value: `${hostname_prefix}-${availabilityZone}-${Math.floor(
              i / subnet.length
            )}.${hostname_domain}`,
          },
        ],
      });
    }

続いて、EC2インスタンスにセカンダリENIをアタッチする部分です。

こちらはユーザーデータで以下のような処理を行い、セカンダリENIのアタッチとOSホスト名の設定をします。

  1. メタデータから必要な情報を取得する
  2. ループで以下処理を行う
    1. EC2インスタンスと同じサブネットに属するENIで使用されていないものを、HostNameタグでソートして先頭のENI IDを取得する
    2. 条件に当てはまるENIが存在しない場合はランダムな秒数sleepしてcontinue
    3. 取得したENI IDを使用してEC2インスタンスにDeviceIndex : 1としてアタッチする
    4. ENIのアタッチが成功した場合はOSホスト名を設定し、ループを抜ける
    5. ENIのアタッチが失敗した場合はランダムな秒数sleepしてループ継続
  3. リトライ回数の上限回数に到達した場合はメッセージを出力する

実際のユーザーデータは以下のとおりです。

#!/bin/bash

set -u

# Redirect /var/log/user-data.log and /dev/console
exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1

declare -r max_retry_interval=8
declare -r max_retries=16

# Get my instance ID
token=$(curl \
  -s \
  -X PUT \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" \
  "http://169.254.169.254/latest/api/token"
)
instance_id=$(curl \
  -s \
  -H "X-aws-ec2-metadata-token: $token" \
  "http://169.254.169.254/latest/meta-data/instance-id"
)

# MAC Address
mac_address=$(curl \
  -s \
  -H "X-aws-ec2-metadata-token: $token" \
  "http://169.254.169.254/latest/meta-data/mac"
)

# Subnet ID
region=$(curl \
  -s \
  -H "X-aws-ec2-metadata-token: $token" \
  "http://169.254.169.254/latest/meta-data/placement/region"
)

# Subnet ID
subnet_id=$(curl \
  -s \
  -H "X-aws-ec2-metadata-token: $token" \
  "http://169.254.169.254/latest/meta-data/network/interfaces/macs/$mac_address/subnet-id"
)

for i in $(seq 1 $max_retries); do
  # Available ENI ID
  eni_id=$(aws ec2 describe-network-interfaces \
    --filters Name=subnet-id,Values=$subnet_id \
      Name=status,Values=available \
    --query 'sort_by(NetworkInterfaces[], &TagSet[?Key==`HostName`].Value | [0])[].NetworkInterfaceId | [0]' \
    --region $region \
    --output text
  )

  if [[ $eni_id == 'None' ]]; then
    retry_interval=$(($RANDOM % $max_retry_interval))

    echo "ENI not found, retrying in $retry_interval seconds..."
    sleep $retry_interval

    continue
  fi

  # Attach ENI
  aws ec2 attach-network-interface \
    --instance-id=$instance_id \
    --device-index=1 \
    --network-interface-id=$eni_id \
    --region $region

  if [[ $? == 0 ]]; then
    hostname=$(aws ec2 describe-network-interfaces \
      --network-interface-ids $eni_id \
      --query "NetworkInterfaces[].TagSet[?Key=='HostName'].Value" \
      --region $region \
      --output text
    )

    echo "Set HostName ${hostname}"

    aws ec2 create-tags \
      --resources $instance_id \
      --tags Key=HostName,Value=$hostname \
      --region $region

    hostnamectl set-hostname "${hostname}"

    echo "hostnamectl :
      $(hostnamectl)"

    break
  else
    retry_interval=$(($RANDOM % $max_retry_interval))

    echo "Failed to attach ENI, retrying in $retry_interval seconds..."
    sleep $retry_interval
  fi
done

# If the loop exhausted retries, fail and suggest manual assignment
if [[ $i == $max_retries ]]; then
  echo "Failed to allocate a unique hostname after $max_retries retries. Please manually assign a hostname."
fi

同時に10台起動してみる

実際に動作確認をしてみます。

動作確認を行う検証環境は全てAWS CDKでデプロイしました。使用したコードは以下リポジトリに保存しています。

構成図は以下のとおりです。4つのAZのサブネットにデプロイします。

Auto ScalingさせたEC2インスタンスのIPアドレスを固定しようとするのは止めよう-検証環境構成図

セカンダリENIは以下のように作成されます。

AZ IPアドレス HostName
us-east-1a 10.10.12.4 web-us-east-1a-0.corp.non-97.net
us-east-1a 10.10.12.5 web-us-east-1a-1.corp.non-97.net
us-east-1a 10.10.12.6 web-us-east-1a-2.corp.non-97.net
us-east-1b 10.10.12.36 web-us-east-1b-0.corp.non-97.net
us-east-1b 10.10.12.37 web-us-east-1b-1.corp.non-97.net
us-east-1b 10.10.12.38 web-us-east-1b-2.corp.non-97.net
us-east-1c 10.10.12.68 web-us-east-1c-0.corp.non-97.net
us-east-1c 10.10.12.69 web-us-east-1c-1.corp.non-97.net
us-east-1d 10.10.12.100 web-us-east-1d-0.corp.non-97.net
us-east-1d 10.10.12.101 web-us-east-1d-1.corp.non-97.net

デプロイ後、EC2インスタンスを確認します。

EC2インスタンスのHostNameが連番になっていることを確認

いずれのEC2インスタンスにも、AZに対応したHostNameタグが割り当てられていますね。

ユーザーデータのログを確認してみます。

$ cat /var/log/user-data.log
{
    "AttachmentId": "eni-attach-04903c39cfcbb7012"
}
Set HostName web-us-east-1a-0.corp.non-97.net
hostnamectl :
       Static hostname: web-us-east-1a-0.corp.non-97.net
       Icon name: computer-vm
         Chassis: vm 🖴
      Machine ID: ec27f46c24977a2f95ab0bad75b861f7
         Boot ID: 38c0b03439ce49098114b4a0e71efece
  Virtualization: amazon
Operating System: Amazon Linux 2023
     CPE OS Name: cpe:2.3:o:amazon:amazon_linux:2023
          Kernel: Linux 6.1.55-75.123.amzn2023.x86_64
    Architecture: x86-64
 Hardware Vendor: Amazon EC2
  Hardware Model: t3.nano
Firmware Version: 1.0
$ cat /var/log/user-data.log

An error occurred (InvalidParameterValue) when calling the AttachNetworkInterface operation: Network interface 'eni-0fdd6814816c56fb4' is currently in use.
Failed to attach ENI, retrying in 1 seconds...
{
    "AttachmentId": "eni-attach-015cdac966edd76a0"
}
Set HostName web-us-east-1a-2.corp.non-97.net
hostnamectl :
       Static hostname: web-us-east-1a-2.corp.non-97.net
       Icon name: computer-vm
         Chassis: vm 🖴
      Machine ID: ec2d7af447e72afb98a650dd40ba034f
         Boot ID: f5c2306450e7479982b4d3dc2a47848b
  Virtualization: amazon
Operating System: Amazon Linux 2023
     CPE OS Name: cpe:2.3:o:amazon:amazon_linux:2023
          Kernel: Linux 6.1.55-75.123.amzn2023.x86_64
    Architecture: x86-64
 Hardware Vendor: Amazon EC2
  Hardware Model: t3.nano
Firmware Version: 1.0

OS側でもホスト名の設定ができていそうです。また、ENIのアタッチができなかった場合はリトライしていますね。

それでは、各EC2インスタンスに設定されているOSホスト名と各セカンダリENIのIPアドレスを確認します。

AWS CLIの--queryで頑張ってIPアドレスの昇順で出力させます。

aws ec2 describe-instances \
  --filter Name=instance-state-name,Values=running \
  --query 'sort_by(Reservations[].Instances[].{HostName:Tags[?Key==`HostName`].Value | [0] , 
    SecondaryEniPrivateIpAddress:NetworkInterfaces[?Attachment.DeviceIndex==`1`].PrivateIpAddress[] | [0]},&SecondaryEniPrivateIpAddress)'
[
    {
        "HostName": "web-us-east-1d-0.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.100"
    },
    {
        "HostName": "web-us-east-1d-1.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.101"
    },
    {
        "HostName": "web-us-east-1b-0.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.36"
    },
    {
        "HostName": "web-us-east-1b-1.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.37"
    },
    {
        "HostName": "web-us-east-1b-2.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.38"
    },
    {
        "HostName": "web-us-east-1a-0.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.4"
    },
    {
        "HostName": "web-us-east-1a-1.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.5"
    },
    {
        "HostName": "web-us-east-1a-2.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.6"
    },
    {
        "HostName": "web-us-east-1c-0.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.68"
    },
    {
        "HostName": "web-us-east-1c-1.corp.non-97.net",
        "SecondaryEniPrivateIpAddress": "10.10.12.69"
    }
]

上手くAZ内でIPアドレスが連番で割り当てられていることが分かります。

なお、sort_by()は文字としてソートするので10.10.12.10010.10.12.36の前になっています。to_number()で頑張れば数値としてソートできそうですが気力が尽きました。気になる方はJMESPathのドキュメントを確認しながらチャレンジしてみてください。

最大キャパシティはAuto Scalingのサブネット数の倍数でなければ、セカンダリENIが割り当てられない可能性がある

ということでめでたし。

ではありません。何回か繰り返していると、HostNameタグが割り当てられないEC2インスタンスがありました。

EC2インスタンスの数がサブネットの数の倍数でなければHostNameが設定されない場合がある

このEC2インスタンスのユーザーデータのログを確認すると、リトライ上限までリトライしていました。

$ cat /var/log/user-data.log

An error occurred (InvalidParameterValue) when calling the AttachNetworkInterface operation: Network interface 'eni-0ac07c5954c1f0aea' is currently in use.
Failed to attach ENI, retrying in 3 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 6 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 7 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 0 seconds...
ENI not found, retrying in 5 seconds...
ENI not found, retrying in 0 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 1 seconds...
ENI not found, retrying in 3 seconds...
ENI not found, retrying in 0 seconds...
ENI not found, retrying in 1 seconds...
Failed to allocate a unique hostname after 16 retries. Please manually assign a hostname.

原因は同じサブネットの全てのENIが既に割当て済みだからです。

こちらのEC2インスタンスのAZはus-east-1cです。一方でus-east-1cにはENIを2つしか作成していません。Auto ScalingはAZ間でバランスをとろうとします。しかし、全てのAZで均等である場合に、どのAZからデプロイするかはランダム...と考えます。

というのも、以下AWS公式ドキュメントには「AZ内のどのサブネットにデプロイするかはランダム」とは記載ありますが、「AZ間で均等が取れている場合、どのAZのサブネットからデプロイするかはランダム」という記載はありませんでした。

インスタンスの分散

Amazon EC2 Auto Scaling は自動的に、有効化された各アベイラビリティーゾーン内で等しい数のインスタンスを維持しようと試みます。Amazon EC2 Auto Scaling は、インスタンス数が最も少ないアベイラビリティーゾーンで新しいインスタンスの起動を試みることによって、これを実行します。アベイラビリティーゾーンに対して複数のサブネットが選択されている場合、Amazon EC2 Auto Scaling はアベイラビリティーゾーンからサブネットをランダムに選択します。この試みが失敗した場合、Amazon EC2 Auto Scaling は成功するまで別のアベイラビリティーゾーンでのインスタンスの起動を試みます。

アベイラビリティーゾーンが異常、または利用不能な状況では、アベイラビリティーゾーン間でのインスタンスの分散が不均等になる可能性があります。アベイラビリティーゾーンが回復すると、Amazon EC2 Auto Scaling は Auto Scaling グループのバランスを自動的に再調整します。これは、インスタンス数が最も少ない有効なアベイラビリティーゾーンでインスタンスを起動し、その他のゾーンでインスタンスを終了することによって行われます。

Amazon EC2 Auto Scaling のメリット - Amazon EC2 Auto Scaling

気になったので実際に動かして確認します。

1台ずつ最小キャパシティを増やしていって、どのAZにEC2インスタンスが作成されるか確認します。

デプロイする環境を改めて確認します。

サブネットは以下のとおりです。PublicSubnet1us-east-1aPublicSubnet2us-east-1bとそれぞれ昇順で対応しています。

VPCのサブネット

AZ IDは以下のとおりです。「実はAZ IDの順番でデプロイされる」ということがあるのか確認するために見ておきます。

AZ一覧

サブネットIDを昇順に並べると以下のとおりです。「サブネットIDの昇順でデプロイされる」ということがあるかもしれないのでチェックしておきます。

サブネットIDで昇順

それでは1台づつデプロイしていきます。

1台目はus-east-1dでした。us-east-1aではないということからAZ名の昇順でデプロイされるという訳ではないことが分かります。また、us-east-1dのAZ IDはuse-az4なので、AZ IDの昇順でデプロイするという訳でもなさそうです。

1台目のEC2インスタンス

2台目はus-east-1aです。ここに来てサブネットIDの昇順でデプロイされる説が出てきました。

2台目のEC2インスタンス

3台目はus-east-1bです。us-east-1bのサブネットのIDは昇順でソートした時に4つある内の4つ目です。ということでサブネットIDの昇順でデプロイされるということではなさそうです。

3台目のEC2インスタンス

全台削除した時に、どのAZから作成されるのかも確認します。

1台目のEC2インスタンス_リトライ

us-east-1bでした。最初に1台目をデプロイした時のAZと異なるので、全てのAZで均等である場合に、どのAZからデプロイするかは確かにランダムでありそうです。

以上を鑑みると、「最大キャパシティはAuto Scalingのサブネット数の倍数でなければ、セカンダリENIが割り当てられない可能性がある」となります。

AZ間でもOSホスト名も連番にするには?

紹介した例では、OSホスト名がAZ内で連番となっていました。

では、AZ間でもOSホスト名も連番にするにはどうしたら良いでしょうか。

結論としては無理です。

以下のように問題が生じます。

  • 意図したとおり連番とならない可能性が高い
  • 仮に連番となったとしても、AZ障害で特定のAZにデプロイできなくなると、連番でなくなる。

「意図したとおり連番とならない可能性が高い」ですが、こちらは先述のとおり、全てのAZで均等である場合に、どのAZからデプロイするかはランダムであるためです。

us-east-1aに1号機用のENIを用意したとしても、1台目がus-east-1bからデプロイされる可能があります。

仮に運よく順番にデプロイされたとしても、AZ障害でそのAZ内にEC2インスタンスがデプロイされなくなるのであれば、そのENI = IPアドレスを割り当てることはできません。ホスト名もこのユーザーデータを使って割り当てるのであれば連番ではなくなってしまいます。

「じゃあセカンダリENIを1つのサブネットに集約すれば良いのでは?」と思われるかもしれませんが、それも基本的にできないと考えるのが良いでしょう。

前提としてEC2インスタンスは同じAZのENIしかアタッチできません。そのため、Single-AZのAuto Scalingでしか実現できません。AZ障害を許容する形となります。

もし、これでも連番としたい場合、そこまでして実装したいものとは何でしょうか。それはもはやAuto Scalingを使うべき環境ではないと思います。

セカンダリENIを割り当てた場合の送信元IPアドレスは?

それでは、セカンダリENIを割り当てた場合の送信元IPアドレスはどうなるでしょう。

答えとしては、基本的にプライマリENIとなります。

以下のようにENI毎にルートが設定されています。

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.12.1      0.0.0.0         UG    512    0        0 ens5
0.0.0.0         10.10.12.1      0.0.0.0         UG    522    0        0 ens6
10.10.12.0      0.0.0.0         255.255.255.224 U     512    0        0 ens5
10.10.12.0      0.0.0.0         255.255.255.224 U     522    0        0 ens6
10.10.12.1      0.0.0.0         255.255.255.255 UH    512    0        0 ens5
10.10.12.1      0.0.0.0         255.255.255.255 UH    522    0        0 ens6
10.10.12.2      0.0.0.0         255.255.255.255 UH    512    0        0 ens5
10.10.12.2      0.0.0.0         255.255.255.255 UH    522    0        0 ens6

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0e:1a:ea:ab:78:89 brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname eni-0f95d959b365fccb0
    altname device-number-0
    inet 10.10.12.13/27 metric 512 brd 10.10.12.31 scope global dynamic ens5
       valid_lft 3533sec preferred_lft 3533sec
    inet6 fe80::c1a:eaff:feab:7889/64 scope link
       valid_lft forever preferred_lft forever
3: ens6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0e:05:2b:84:1d:89 brd ff:ff:ff:ff:ff:ff
    altname enp0s6
    altname eni-0fdd6814816c56fb4
    altname device-number-1
    inet 10.10.12.4/27 metric 522 brd 10.10.12.31 scope global dynamic ens6
       valid_lft 3547sec preferred_lft 3547sec
    inet6 fe80::c05:2bff:fe84:1d89/64 scope link
       valid_lft forever preferred_lft forever

Destinationが重複する場合はMetricの値が小さい方が優先されます。今回の場合ens5ens6のいずれのDestinationも重複しておりMetricens5の方が小さいため、ens5であるプライマリENIからトラフィックは流れます。

もし、セカンダリENIのIPアドレスから送信したい場合は、以下2つの対応があると考えます。

  • 通信するときに送信元のインターフェイスやIPアドレスを指定する
  • ユーザーデータの中でENIアタッチ後、セカンダリENIのMetricの方を小さくする処理を行う

どちらの場合も都度指定するのが面倒 or 一筋縄ではできなさそうです。

無理やりできないことはないけど、本当にそれを実現する必要があるのか

Auto ScalingさせたEC2インスタンスのIPアドレスを固定させてみました。

結論としては、Auto ScalingするEC2インスタンスでも無理やりできないことはないですが、止めた方が良いです。

IPアドレスの固定はAuto Scalingというサービスが想定していない使い方です。無理やり運用に乗せると運用にしわ寄せが行き、いつか痛い目に合うでしょう。

運用負荷軽減のためにも、シンプルな運用を目指してオーバーエンジニアリングしないことがベターです。

そのため、まずは「本当にEC2インスタンスのIPアドレスを固定にする必要があるのか」を考えましょう。もし、それを実現する必要があるのであれば、少なくともEC2インスタンスAuto Scalingさせるべきではないと考えます。

ちなみに、自身のIPアドレスを何かしらの設定ファイルに埋め込む必要があるのであれば、その設定ファイルにIPアドレスを指定するためのプレースホルダーを記載しておいて、ユーザーデータで置換してあげることで対応できるでしょう。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.