NLBでプライベートなAuto Scaling GroupのEC2をIPアドレスで登録する

ウィスキー、シガー、パイプをこよなく愛する大栗です。

先日NLBでIPアドレスをターゲットとして登録することで、インターネットへ出られないプライベートなEC2やAWSリソースを登録できることをご紹介しました。

NLBでプライベートなEC2やRDSの負荷分散が可能に!

NLBのターゲットグループをIPアドレスターゲットにするとEC2がインターネットに接続できなくても登録が可能です。

NLB3

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

概要

EC2の起動時

EC2が起動する時には以下の流れでNLBに登録します。

  1. Auto Scalingでインスタンス起動成功
  2. CloudWatch AlarmがLambdaを起動
  3. NLBにEC2を登録

Launch-EC2

EC2の終了時

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

そのため以下の流れでNLBから登録を削除します。

  1. CloudWatch Eventsが毎分Lambdaを起動
  2. ターゲットグループのHealthyの状況を確認
  3. NLBからEC2を登録解除
  4. EC2の削除

Terminate-EC2

試してみる

と言うことで作ってみました。

asg-registerer-with-nlb

事前準備

Serverless Frameworkでデプロイするためインストールしておきます。こちらの記事を参考に環境を構築してください。

今から始めるServerless Frameworkで簡単Lambda開発環境の構築

NLBとAuto Scaling Groupも動作するように以下の記事を参考に準備しておきましょう。

NLBでプライベートなEC2やRDSの負荷分散が可能に!

NLBのターゲットグループは、IPアドレスのターゲットになっています。

EC2_Management_Console

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

EC2_Management_Console

デプロイ

リポジトリからクローンしてきます。

$ 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個作られます。

Lambda_Management_Console

この状態でAuto Scaling Groupのインスタンス数を0台から2台にしてみます。

しばらく経つとEC2が起動して、ターゲットグループに登録されます。

EC2_Management_Console

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

CloudWatch_Management_Console

CloudWatch_Management_Console

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

http-nlb-4989faab42bf4239_elb_ap-northeast-1_amazonaws_com_index_html

次に起動したEC2のhttpdを停止してUnhealthyにしてみます。

$ ssh 10.100.200.195 "sudo service httpd stop"
Stopping httpd: [  OK  ]

しばらくするとUnhealthyになります。

EC2_Management_Console

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

EC2_Management_Console

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

EC2_Management_Console

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

EC2_Management_Console

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

CloudWatch_Management_Console

さいごに

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

NLBのIPターゲットのエントリでRDSの負荷分散について触れていましたが、こちらの登録/解除やIPアドレスが変わった場合の更新などが必要です、こちらの自動化もそのうちやってみようと思います。