ネットワーク不備があるものを含めた複数の接続を設定したGlue Jobのフェイルオーバーを確認する
データ事業本部の鈴木です。
Glue JobはGlue接続を設定することで、VPC内にENIを作成し、プライベートサブネットにあるJDBCソースに接続できます。
ただし、ENIを作成する際にはAZごとに作成されるため、AZ障害の影響を受ける仕組みです。
Glue Jobには複数の接続を設定できるため、仕組み上はAZ障害時にフェイルオーバーができます。
この挙動についてはインターネットを探してもあまり情報が多くなかったため、今回限定的な条件ではありますが動作検証をしてみました。
フェイルオーバーの挙動について
先に記載したトラブルシュートのガイドでは、記事執筆時点で以下のように記載されています。(私が意訳しているので厳密には原文を確認してください)
- 実行試行ごとに、ジョブに設定された順序で接続の健全性をチェックする。使用可能な接続が見つかるまでこれを繰り返す
- AZに障害が発生した場合、チェックに失敗となり、その接続はスキップされる
- 検証は以下の観点でされる
- VPC IDとサブネットが有効か
- NATゲートウェイまたはVPCエンドポイントがあるか
- 0より多いIPアドレスが割り当てられているか
- AZに問題がないか
- 再試行が設定されている場合、AWS Glueは同じ接続で再試行する
原文の英語の解釈が難しいですが、以下は私の解釈です。
GetJobなどを確認すると分かりますが、Jobは設定された接続を順番を割り当てて保持しており、その順で検証・使用するようです。
「VPC IDとサブネットが有効か」は接続に設定されたVPCとサブネットがまだ使えるかを確認すると理解しています。削除していたりすると検証でスキップされるはずです。
「0より多いIPアドレスが割り当てられているか」はIPが割り当て可能な状態であれば使うと考えられます。
再試行設定時の挙動については、Glue Jobはリトライが設定できるため、実行時にAZ障害が発生した場合には、再実行で前回の障害は回復したものとして同じ接続を使うという認識です。
以上のように、接続の選択にはいくつかの判断条件があります。
ネットワーク設定不備によるフェイルオーバーの挙動を確認する
AZ障害時やIPアドレス枯渇時の挙動の検証は準備が大変そうだったので、今回は「NATゲートウェイまたはVPCエンドポイントがあるか」を試してみました。
AZ障害時の挙動はAWS FISを使う、IPアドレス枯渇時の挙動は小さめのサブネットを作り全IPを使った状態が再現するなどすれば検証可能かなと思います。
1. 有効な接続の作成
今回は検証したい内容にあまり関係ないためそのような接続を作ったのだなとご認識ください。
事前にVPCとAuroraデータベースを作成しておきました。
AuroraデータベースはPostgreSQLをエンジンにServerless v2で作成し、データベースとユーザーも作成しておきました。
Glue接続はAuroraデータベースのあるサブネットを設定します。もちろんデータベースに接続できるセキュリティグループも指定しました。この接続を使えばGlue JobはAuroraデータベースのデータを取得できます。

2. NATゲートウェイ・VPCエンドポイントがないサブネットのみのVPCへの接続の作成
NATゲートウェイおよびVPCエンドポイントが利用できないサブネットを作成したいため、プライベートサブネットのみのVPCを新規で作成しました。

このVPC向けに接続を作成しました。このサブネットで1と同じConnection URLを指定しました。

テスト接続してももちろん接続はできません。

3. Glue Jobへの設定
1,2で作成した接続を設定したGlue Jobを作成しました。
以下のような実装です。(Glue Studioで作成したものを少し修正しました)
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)
# Script generated for node Relational DB
RelationalDB_node = glueContext.create_dynamic_frame.from_options(
connection_type = "postgresql",
connection_options = {
"useConnectionProperties": "true",
"dbtable": "users",
"connectionName": "nayuts-sample-connection",
},
transformation_ctx = "RelationalDB"
)
job.commit()
なお、Jobのワーカー数は2にしてあります。(後に載せるCloudTrailイベントの理解に必要になります)
コンソールのJob detailsから以下のように接続を設定しました。

以降にも記載しますが、接続はこの上から順番に使用されるようでした。
少し脱線しますが、glueContext.create_dynamic_frame.from_optionsでは有効な方の接続の名前を指定しました。Glue Jobのランタイム内で自分がどの接続を使っているかは別途取得が必要です。ランタイム環境変数で使用している接続名を取得する方法は分かりませんでした。そもそもAZ障害の影響を受けるのはENIを作成するときのため、ユーザー・パスワード情報の取得は同じ接続で問題ない可能性があります。
4. Jobを実行する
Jobのセットアップが終わったので実行してみました!
最初にNATゲートウェイ・VPCエンドポイントがないサブネットへの接続を指定しているため、なにかしらの検証を経て2つ目の接続を使用してJobが実行されます。
ちなみに私は「初回実行で無効な接続を使用して失敗した後、リトライ時にもう一つの接続を使用し直す」と予想していましたが、実行してみると初回でふつうに成功しました。

Glue Jobの実行時に渡されている接続と使用された接続は/aws-glue/jobs/errorに出力されたログに記載されました。--connection-names nayuts-sample-connection,nayuts-private-only-connectionというようにふたつの接続が渡っていることは確認できましたが、いつのまにかnayuts-sample-connectionの方が使われるようになっていました。


「設定を間違えたかな?」と思いましたが、もう少し詳しく挙動を調べるためCloudTrailを確認するとヒントが得られました。
イベント履歴でユーザー名がGlueJobRunnerSessionのイベントを表示すると、以下のように接続を検証する様子が確認できました。
タイムスタンプから、接続ごとの検証はほぼ同時に行なっているようです。

例えば、最初のDescribeVpcEndpointsのイベントを開くと、確かに無効な接続で設定したVPCのVPCエンドポイントを検証していました。

2つ目のDescribeVpcEndpointsのイベントを開くと、有効な接続で設定したVPCのVPCエンドポイントを検証していました。

以上から、ジョブの実行時に毎回設定している接続の有効性をチェックして、どの接続を使うか決めていることが分かりました。
実際のロジックは分かりませんが、「VPC IDとサブネットが有効か」と「NATゲートウェイまたはVPCエンドポイントがあるか」と「0より多いIPアドレスが割り当てられているか」はCloudTrailイベントに記録されたAPI操作で確認していると想像されます。
特に「0より多いIPアドレスが割り当てられているか」はDescribeSubnetsのレスポンスにavailable-ip-address-countがあるため、これを元にENIが作成可能か判定していると思いました。
「AZに問題がないか」は判定方法が分かりませんでした。DescribeAvailabilityZonesでAZの状態が分かりますが、このAPIを実行しているイベントはなかったため、AZ障害はジョブを実行してみて判断となるのかもしれません。DescribeSubnetsのレスポンスにstateがありますが、あくまでもそのサブネットが利用可能かという情報のようでした。
そのため、AZ障害時にはAZ障害時にたまたまJobを実行した際にどのような挙動になるかは今回の検証結果からはなんとも言えません。冒頭のトラブルシュートでは「In the case of an Availability Zone (AZ) failure, the connections from that AZ will fail the check and will be skipped.」とあるので同様に検証時にスキップされると予想されますが、心配であれば別途検証するのがよさそうです。
なお、何度か実行しているとごく稀に無効な接続を最初に使うときもありました。タイミングによってはNAT・VCPエンドポイントがないという条件だと使われることもあるのかもしれません。AZ障害時の考慮も含めて、ジョブのリトライは設定しておいた方が無難かなと思いました。

最後に
この記事ではネットワーク不備があるものを含めた複数の接続をGlue Jobに設定してみて、どのようにフェイルオーバーされるかを確認しました。
今回は順番が先の接続がスキップされる様子をみたかったため、NATゲートウェイもVCPエンドポイントもないサブネットの接続をわざわざ用意しましたが、そこにこだわらなければGlue Jobに複数の接続を設定して動かしてみるだけでもCloudTrailイベントから様子が確認できると思います。気になる方は見てみてください。







