web-dev-qa-db-ja.com

ELBグループからAWSインスタンスを正常にシャットダウンまたは削除する方法

ロードバランサーを使用してトラフィックを分散するサーバーインスタンスのクラウドがAmazonで実行されています。現在、ブラウザ側で接続エラーを発生させることなく、ネットワークを適切に縮小するための良い方法を探しています。

私の知る限り、インスタンスの接続は、ロードバランサーから削除されると無礼に終了します。

インスタンスがシャットダウンする1分前のようにインスタンスに通知する方法、またはロードバランサーが停止中のインスタンスへのトラフィックの送信を停止するようにする方法が必要ですが、インスタンスへの既存の接続は終了しません。

私のアプリは、Ubuntuで実行されているnode.jsベースです。また、いくつかの特別なソフトウェアを実行しているので、node.jsホスティングを提供する多くのPAASを使用したくありません。

ヒントをありがとう。

このアイデアは、ELBの機能を使用して、異常なノードを検出し、プールから削除しますが、以下の仮定で期待されるように動作するELBに依存しています。これは私が自分でテストするつもりでしたが、まだ時間がありませんでした。答えが更新されたら更新します。

プロセスの概要

次のロジックは、ノードをシャットダウンする必要があるときにラップして実行できます。

  1. NodeXへの新しいHTTP接続をブロックしますが、既存の接続は引き続き許可します
  2. アプリケーションへの既存の接続を監視するか、「安全な」時間を許可して、既存の接続がなくなるのを待ちます。
  3. EC2 APIを直接使用するか、抽象化されたスクリプトを使用して、nodeXEC2インスタンスのシャットダウンを開始します。

アプリケーションに応じて「安全」であり、一部のアプリケーションでは判断できない場合があります。

テストが必要な仮定

ELB プールから異常なインスタンスを削除する これは正常であると期待しているので、次のようになります。

  1. 最近閉じられたポートへの新しい接続は、プール内の次のノードに正常にリダイレクトされます
  2. ノードがBadとマークされている場合、そのノードへのすでに確立されている接続は影響を受けません。

可能なテストケース:

  • ELBでHTTP接続を起動し(たとえば、curlスクリプトから)、ノードのHTTPポートの1つを閉じるスクリプトを開いている間に結果をログに記録します。 ELBが常に状態の変化を判断できる許容可能な時間を見つけるために実験する必要があります。
  • 新しいHTTP接続をブロックしている間、長いHTTPセッション(ファイルのダウンロードなど)を維持します。長いセッションはうまくいけば継続するはずです。

1。 HTTP接続をブロックする方法

NodeXでローカルファイアウォールを使用して新しいセッションをブロックしますが、確立されたセッションは引き続き許可します。

例:IPテーブル:

iptables -A INPUT -j DROP -p tcp --syn --destination-port <web service port>
16
Ray Vahey

これは古い質問ですが、Amazonが最近connection drainingのサポートを追加したことに注意してください。つまり、インスタンスがロードバランサーから削除されると、インスタンスはインスタンスの前に進行中だったリクエストを完了します。ロードバランサーから削除されました。削除されたインスタンスに新しいリクエストがルーティングされることはありません。これらのリクエストにタイムアウトを指定することもできます。つまり、タイムアウトウィンドウより長く実行されたリクエストは、結局終了します。

この動作を有効にするには、ロードバランサーのInstancesタブに移動し、Connection Drainingの動作を変更します。

16
Jaap Haagmans

ELBからのトラフィックを分散するための推奨される方法は、複数のアベイラビリティーゾーンに同数のインスタンスを配置することです。例えば:

ELB

  • インスタンス1(us-east-a)
  • インスタンス2(us-east-a)
  • インスタンス3(us-east-b)
  • インスタンス4(us-east-b)

プログラムで(またはコントロールパネルを介して)インスタンスをデタッチできるようにする、2つの対象のELBAPIが提供されています。

  1. インスタンスの登録を解除する
  2. アベイラビリティーゾーンを無効にします(その後、そのゾーン内のインスタンスを無効にします)

ELB開発者ガイド には、アベイラビリティーゾーンを無効にした場合の影響について説明するセクションがあります。そのセクションの注記は特に興味深いものです。

ロードバランサーは常に、有効なすべてのアベイラビリティーゾーンにトラフィックを分散します。そのアベイラビリティーゾーンがロードバランサーに対して無効になる前に、アベイラビリティーゾーン内のすべてのインスタンスが登録解除または異常である場合、そのアベイラビリティーゾーンに送信されるすべてのリクエストは、DisableAvailabilityZonesForLoadBalancerがそのアベイラビリティーゾーンを呼び出すまで失敗します。

上記のメモで興味深いのは、DisableAvailabilityZonesForLoadBalancerを呼び出すと、ELBが利用可能なゾーンにのみリクエストの送信を即座に開始できることを意味する可能性があることです。無効なアベイラビリティーゾーンのサーバーでメンテナンスを実行している間、ダウンタイムが発生しない可能性があります。

上記の「理論」には、Amazonクラウドエンジニアによる詳細なテストまたは承認が必要です。

7
Faraz

ここにはすでに多くの回答があり、そのうちのいくつかは良いアドバイスをしているようです。しかし、一般的にあなたのデザインには欠陥があると思います。シャットダウン手順をどのように完璧に設計しても、サーバーをシャットダウンする前にクライアント接続が閉じられていることを確認してください。

  1. サーバーの電源が失われる可能性があります。
  2. ハードウェア障害により、サーバーに障害が発生します。
  3. ネットワークの問題により接続が閉じられる可能性があります。
  4. クライアントがインターネットまたはwifiを失います。

リストを続けることもできますが、私のポイントは、システムが常に正しく機能するように設計するのではなく、ということです。障害を処理するように設計します。サーバーの電力損失をいつでも処理できるシステムを設計すると、非常に堅牢なシステムが作成されます。これはELBの問題ではありません。これは、現在使用しているシステムアーキテクチャの問題です。

4
bwight

評判が悪い原因はコメントできません。これが私が作成したスニペットで、そこにいる誰かにとって非常に役立つかもしれません。これは、aws cliツールを利用して、インスタンスから接続が削除されたことを確認します。

ELBの背後に提供されたpythonサーバーを備えたec2-instanceが必要です。

from flask import Flask
import time

app = Flask(__name__)

@app.route("/")
def index():
    return "ok\n"

@app.route("/wait/<int:secs>")
def wait(secs):
    time.sleep(secs)
    return str(secs) + "\n"

if __name__ == "__main__":
    app.run(
        Host='0.0.0.0',
        debug=True)

次に、ローカルワークステーションからELBに向けて次のスクリプトを実行します。

#!/bin/bash

which jq >> /dev/null || {
   echo "Get jq from http://stedolan.github.com/jq"
}

# Fill in following vars
lbname="ELBNAME"
lburl="http://ELBURL.REGION.elb.amazonaws.com/wait/30"
instanceid="i-XXXXXXX"

getState () {
    aws elb describe-instance-health \
        --load-balancer-name $lbname \
        --instance $instanceid | jq '.InstanceStates[0].State' -r
}

register () {
    aws elb register-instances-with-load-balancer \
        --load-balancer-name $lbname \
        --instance $instanceid | jq .
}

deregister () {
    aws elb deregister-instances-from-load-balancer \
        --load-balancer-name $lbname \
        --instance $instanceid | jq .
}

waitUntil () {
    echo -n "Wait until state is $1"
    while [ "$(getState)" != "$1" ]; do
        echo -n "."
        sleep 1
    done
    echo
}

# Actual Dance
# Make sure instance is registered. Check latency until node is deregistered

if [ "$(getState)" == "OutOfService" ]; then
    register >> /dev/null
fi

waitUntil "InService"

curl $lburl &
sleep 1

deregister >> /dev/null

waitUntil "OutOfService"
2
Loa

既存の回答で説明されていない警告は、ELBが60秒のTTLを持つDNSレコードを使用して、複数のELBノード(それぞれに1つ以上のインスタンスが接続されている)間の負荷を分散することです。

これは、2つの異なるアベイラビリティーゾーンにインスタンスがある場合、おそらくAレコードに60s TTLのELB用の2つのIPアドレスがあることを意味します。そのようなアベイラビリティーから最終インスタンスを削除すると、ゾーンでは、クライアントは少なくとも1分間は古いIPアドレスを使用する可能性があります。障害のあるDNSリゾルバーの動作はさらに悪化する可能性があります。

ELBが複数のIPを使用して同じ問題を抱えているもう1つの場合は、単一のアベイラビリティーゾーンに非常に多くのインスタンスがあり、1つのELBサーバーでは処理できない場合です。その場合、ELBは別のサーバーを作成し、そのIPを60秒のTTLでAレコードのリストに追加します。

1
Evgeny