
NLBでプライベートなAuto Scaling GroupのEC2をIPアドレスで登録する
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
ウィスキー、シガー、パイプをこよなく愛する大栗です。
先日NLBでIPアドレスをターゲットとして登録することで、インターネットへ出られないプライベートなEC2やAWSリソースを登録できることをご紹介しました。
NLBのターゲットグループをIPアドレスターゲットにするとEC2がインターネットに接続できなくても登録が可能です。

しかしNLBのターゲットグループをIPアドレスターゲットにするとAuto Scaling Groupを登録できません。登録と解除を個別のEC2 インスタンスとして行う必要があるため自動化するスクリプトを書いてみました。NLBを絡めた自動化スクリプトの習作です。
概要
EC2の起動時
EC2が起動する時には以下の流れでNLBに登録します。
- Auto Scalingでインスタンス起動成功
- CloudWatch AlarmがLambdaを起動
- NLBにEC2を登録

EC2の終了時
初めはCloudWatchでターゲットグループのUnHealthyHostCountにアラームを登録してLambdaを起動してUnHealthyなインスタンスを解除して削除しようと思っていました。しかしCloudWatchのアラームは条件に合致した最初しか通知が行われないためUnHealthyになるタイミングによってはうまく動かないと思い、毎分ターゲットグループのステータスを確認する方法を取りました。
そのため以下の流れでNLBから登録を削除します。
- CloudWatch Eventsが毎分Lambdaを起動
- ターゲットグループのHealthyの状況を確認
- NLBからEC2を登録解除
- EC2の削除

試してみる
と言うことで作ってみました。
事前準備
Serverless Frameworkでデプロイするためインストールしておきます。こちらの記事を参考に環境を構築してください。
NLBとAuto Scaling Groupも動作するように以下の記事を参考に準備しておきましょう。
NLBのターゲットグループは、IPアドレスのターゲットになっています。

Auto Scaling Groupにはロードバランサーは設定されていません。正確にはIPアドレスターゲットであるためAuto Scaling Groupで設定できません。

デプロイ
リポジトリからクローンしてきます。
$ git clone git@github.com:maroon1st/asg-registerer-with-nlb.git
/conf/environment.ymlに環境の情報を設定します。
| 項目 | 値 | 備考 | 
|---|---|---|
| STAGE | dev | Serverless FrameworkのStage | 
| AWS_REGION | ap-northeast-1 | ここでは東京リージョンとしています | 
| ASG_NAME | httpd-nlb | Auto Scaling Groupの名前を入力します | 
| TARGET_GROUP | arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/nlb-target/a1b2c3d4e5f6g7h8 | Target GroupのARNを入力します | 
STAGE: dev AWS_REGION: ap-northeast-1 ASG_NAME: httpd-nlb TARGET_GROUP: arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/nlb-target/a1b2c3d4e5f6g7h8
sls deployコマンドでデプロイします。Lambda Functionが2個作られます。
$ sls deploy Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Creating Stack... Serverless: Checking Stack create progress... ..... Serverless: Stack create finished... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service .zip file to S3 (7.09 KB)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... .................................... Serverless: Stack update finished... Service Information service: nlb-asg stage: dev region: ap-northeast-1 stack: nlb-asg-dev api keys: None endpoints: None functions: launch_ec2: nlb-asg-dev-launch_ec2 unhealthy_ec2: nlb-asg-dev-unhealthy_ec2
Lambda Functionが2個作られます。

この状態でAuto Scaling Groupのインスタンス数を0台から2台にしてみます。
しばらく経つとEC2が起動して、ターゲットグループに登録されます。

CloudWatch LogsでLambdaのログを確認してみます。2台同時に増えたためLambdaの起動も重なりログストリームが別々に出たようです。


NLB経由でEC2にアクセスできます。

次に起動したEC2のhttpdを停止してUnhealthyにしてみます。
$ ssh 10.100.200.195 "sudo service httpd stop" Stopping httpd: [ OK ]
しばらくするとUnhealthyになります。

もう少し待つとdrainingになります。

対象のEC2インスタンスもTerminatedになっています。

すぐに新しいインスタンスが起動してきます。

CloudWatch LogsでUnhealthyの時のLambdaのログを確認します。httpdを停止した10.100.200.195が対象としてターゲットスループの登録解除とEC2インスタンスの削除を行っています。

さいごに
セキュリティポリシー上インターネットに出られない場所に配置することという場合もあります。一応そのような場面では対応できる内容でした。デプロイや監視、管理の手間を減らすためにAWSサービスを使用するためにはインターネット接続が必要になるので、正直言ってほとんど実用的ではない内容でした。IPアドレスターゲットの登録と解除を自動化するための習作なので仕方がないかなという所です。
NLBのIPターゲットのエントリでRDSの負荷分散について触れていましたが、こちらの登録/解除やIPアドレスが変わった場合の更新などが必要です、こちらの自動化もそのうちやってみようと思います。













