2
0
paiza×Qiita記事投稿キャンペーン「プログラミング問題をやってみて書いたコードを投稿しよう!」

【AWS】EC2内部でIPアドレスを変更するソフトウェアへの対応方法

Last updated at Posted at 2024-08-22

はじめに

 現場で、オンプレの内部でIPアドレスを変更する仕組みを持つメールサーバをAWSのEC2に移行する際、大きな問題点がありましたので解決策とともに紹介します。

対象読者

  • AWSを使用する現場に従事している方
  • AWSの資格勉強をしている方
  • AWSに興味がある方

1. 問題点

AWSでは内部でのIPアドレス変更に対応できない

内部でプライベートIPアドレスを変更した場合でも、AWS側のネットワークインターフェースのIPアドレスは変わらないのでインスタンス同士が通信できなくなります。

今回の現場では、複数のEC2インスタンスでクラスターを作り、ソフトウェアのIPアドレス変更で障害時に自動でフォールバックするようなシステムにて問題が起きました。

2. 解決策

CloudWatchとLambdaを使用して対応

AWSでは内部でのIPアドレス変更を検知できないので、内部ソフトウェアのトリガーとなるものをAWS側(CloudWatch)で監視し、Lambdaを使ってIPアドレスを付け替える必要がありました。
image.png

3. CloudWatch

今回のソフトウェアの場合、プライマリサーバーの停止をトリガーにすればよかったのでプライマリサーバーの状態を監視するEventBridgeルールを作成しました。

{
    "source": ["aws.ec2"],
    "detail-type": ["EC2 Instance State-change Notification"],
    "detail": {
        "state": ["stopped", "terminated"],
        "instance-id": ["アクティブサーバー用EC2インスタンスのインスタンスID"]
    }
}

3-1. sourceフィールド

"source": ["aws.ec2"]
ここでイベントのソースを指定します。この場合、Amazon EC2からのイベントを監視しています。

3-2. detail-type:

"detail-type": ["EC2 Instance State-change Notification"]
ここで特定のイベントタイプを指定します。ここでは、EC2インスタンスの状態変更に関する通知を監視しています。

3-3. detail:

このフィールドはイベントの詳細をフィルタリングするために使用されます。

3-3-1. state:

"state": ["stopped", "terminated"]
監視するインスタンスの状態を指定します。ここでは、インスタンスが「stopped(停止)」または「terminated(終了)」状態になったときルールがトリガーされるようにしています。

3-3-2. instance-id:

"instance-id": ["アクティブサーバー用EC2インスタンスのインスタンスID"]
特定のEC2インスタンスを指定します。このフィールドには監視対象のインスタンスIDが入ります。このインスタンスIDに一致するインスタンスのみが対象となります。

4. Lambda

CloudWatchをトリガーに起動するLambdaを作成しました。
SNSでの通知もLambdaで行います。

import boto3

ec2 = boto3.client('ec2')
sns = boto3.client('sns')

def lambda_handler(event, context):

    # アクティブサーバーのセカンダリ IP アドレスを解放
    ec2.unassign_private_ip_addresses(
        NetworkInterfaceId='アクティブサーバーのインターフェースID', 
        PrivateIpAddresses=['10.0.0.5'] # セカンダリIPアドレスを設定
    )

    # セカンダリサーバーにセカンダリ IP アドレスをアタッチ
    ec2.assign_private_ip_addresses(
        NetworkInterfaceId='セカンダリサーバーのインターフェースID',
        PrivateIpAddresses=['10.0.0.5']  # セカンダリIPアドレスを設定
    )

    # メール本文用の変数を設定
    str1 = "アクティブサーバーの停止が検出されました。"
    str2 = "セカンダリサーバーにIPアドレスを付け替える処理を実行しました。"
    # %sは文字列指定子(str1,2,...と順に改行されて挿入される)
    message1 = "%s \n %s " %(str1,str2)

    response = sns.publish(
        # SNSトピックのARN
        TopicArn = '作成したSNSトピックのARNを設定',
        # 件名
        Subject = 'フェイルオーバーが起動されました。',
        # 本文
        Message = message1,
    )
    return response

4-1. インポートとクライアントの設定

import boto3

ec2 = boto3.client('ec2')
sns = boto3.client('sns')

import boto3でAWS SDK for Pythonをインストールします。
boto3.client('ec2')でEC2サービスにアクセスするためのクライアントを作成します。
boto3.client('sns')でSNSサービスにアクセスするためのクライアントを作成します。

4-2. Lambda関数の定義

def lambda_handler(event, context):

lambda_handlerはAWS Lambda関数のエントリーポイントです。イベントが発生したときにこの関数が呼び出されます。
引数のeventはイベントデータを含む辞書、contextは実行時情報を提供するオブジェクトです。

4-3. アクティブサーバーのセカンダリIPアドレスを解放

ec2.unassign_private_ip_addresses(
    NetworkInterfaceId='アクティブサーバーのインターフェースID', 
    PrivateIpAddresses=['10.0.0.5'] # セカンダリIPアドレスを設定
)

unassign_private_ip_addressesメソッドは、指定されたネットワークインターフェースからプライベートIPアドレスを解放します。
変数NetworkInterfaceIdには、アクティブサーバーのネットワークインターフェースのIDを設定します。
変数PrivateIpAddressesは解除するプライベートIPアドレスのリストです。

4-4. セカンダリサーバーにセカンダリIPをアタッチ

ec2.assign_private_ip_addresses(
    NetworkInterfaceId='セカンダリサーバーのインターフェースID',
    PrivateIpAddresses=['10.0.0.5']  # セカンダリIPアドレスを設定
)

assign_private_ip_addressesメソッドは、指定されたネットワークインターフェースにプライベートIPアドレスを割り当てます。
NetworkInterfaceIdには、セカンダリサーバーのネットワークインターフェースのIDを設定します。
PrivateIpAddressesは割り当てるプライベートIPアドレスのリストです。

4-5. SNS通知の設定と送信

str1 = "アクティブサーバーの停止が検出されました。"
str2 = "セカンダリサーバーにIPアドレスを付け替える処理を実行しました。"
message1 = "%s \n %s " %(str1,str2)

response = sns.publish(
    TopicArn = '作成したSNSトピックのARNを設定',
    Subject = 'フェイルオーバーが起動されました。',
    Message = message1,
)

変数str1str2には通知メッセージの内容を設定しています。
変数message1にはstr1str2を組み合わせ、最終的なメッセージを設定します。
sns.publishメソッドは、SNSトピックにメッセージを送信するメソッドです。
TopicArnにはSNSトピックのARN(Amazon Resource Name)を設定します。
Subjectには通知の件名を設定します。
Messageは通知の本文です。

4-6. 応答の返却

return response

これでsns.publishメソッドの応答を返します。ロギングやデバッグで使用します。

4-7. まとめ

以上のようなスクリプトを作成することで、内部IPアドレスを変更する仕組みを持ったソフトウェアもAWSに移行することができます。

現場でも、このような仕組みでシステムを実際にお客様にも使用していただいております
実際に自分が作ったシステムを、お客様に使用していただいているのを見るととてもうれしく思います。

おわりに

Lambdaは万能

今回は、EC2内部でIPアドレスを変更するソフトウェアの移行を紹介しました。
Lambdaを実務で使ったのは初めてですが、このような特殊なパターンにも対応できる万能なサービスだと感じました
今後も機会があればLambdaをどんどん使っていきたいと思いました。

基本的にはIPアドレスはAWS側で管理するのが好ましいですが、今回のソフトウェアのような特殊なものを移行する際には、参考にしていただければ幸いです。

2
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
2
0