
NLB と Auto Scaling グループで Fivetran SSH トンネルの自動復旧を試してみた
はじめに
Fivetran ではデータソースへの接続オプションとして SSH トンネルをサポートしています。
特にデータソースがデータベースなど、プライベートなネットワークに存在する場合にこのオプションを使用できます。SSH トンネルの場合、SSH 接続用の踏み台サーバーを構築することになるので、何らかのトラブルでサーバーが停止した場合はデータ更新が止まってしまいます。
Auto Scaling グループを使用しこの復旧を自動化してみましたので、本記事で検証内容をまとめてみます。
前提条件
検証環境
以下の環境で検証しました。
- Destination:Snowflake
- データソース
- Amazon RDS for SQL Server
- エディション: SQL Server Express Edition
- インスタンスタイプ:db.t3.micro
- バージョン:SQL Server 2019 (15.00.4430.1.v1)
- Amazon RDS for SQL Server
- 接続方法:SSH トンネル
- SSH サーバー
- OS:Amazon Linux 2023
- AMI ID:ami-09e6f87a47903347c
- インスタンスタイプ:t2.micro
- OS:Amazon Linux 2023
詳細は後述しますが、下図の構成です。
Fivetran における宛先設定とデータソース側の設定(サンプルデータ作成、Fivetran接続用ユーザーの作成)は完了済みとしています。設定手順は以下の記事をご参照ください。
検証手順
設定した Auto Scaling グループの動作は以下の手順で確認しました。
- 初期状態
- Auto Scaling グループの Desired Capacity を 0 に設定しておく
- NLB 配下に SSH サーバー を構築し、GUI(Fivetran ダッシュボード)で Fivetran のコネクションを作成
- Fivetran コネクションのステータスが「Active」であることを確認
- Auto Scaling グループのテスト
- 既存の SSH サーバーを削除
- Fivetran コネクションで同期を実行しステータスが「Error」となることを確認
- Auto Scaling グループの Desired Capacity を 1 に変更
- 新しいインスタンスが起動されることを確認
- 再度同期を実行し、Fivetran コネクションのステータスが再び「Active」となることを確認
- 宛先にデータが正常に転送されていることを確認
構成時の考慮事項
SSH 公開鍵の取得
SSH トンネルによるコネクション構成時は、Fivetran 側で接続先ごとに SSH 公開鍵が生成されます。そのため Auto Scaling グループで起動したインスタンスが公開鍵を取得できる必要があります。ここでは Systems Manager Parameter Store に公開鍵を登録し取得します。
サーバー ホストの認証
Fivetran 側の処理サーバーからの SSH 接続時に、Fivetran 側で SSH サーバーのホストキーの指紋(fingerprint)が取得されるので、正しいサーバーであることを承認する必要があります。Fivetran が提供する API を使用してこのホスト認証を行います。インスタンスの起動テンプレートでは、起動時にこの API を呼び出すスクリプトを実行するよう設定しています。上図で NAT Gateway が配置されているのは、プライベートサブネット内のインスタンスから Fivetran API へのアウトバウンド通信を可能にするためです。
構成手順
起動テンプレートの作成
起動テンプレートは以下の内容で作成しました。特に記載のない部分はデフォルト設定となります。
- AMI ID:ami-09e6f87a47903347c
- インスタンスタイプ:t2.micro
- キーペア:無し
- セキュリティグループ:SSH サーバー用のセキュリティグループを関連付け
- NLB からのインバウンド通信(ポート22)を許可
- インスタンスプロファイルを設定
- IAM ロールのポリシーには AmazonSSMManagedInstanceCore をアタッチ
- Systems Manager 経由での OS 接続
- Systems Manager Parameter Store 経由でのパラメータ取得
- IAM ロールのポリシーには AmazonSSMManagedInstanceCore をアタッチ
- ユーザーデータ
- ここでは簡単に API キーとシークレットをテキストとしてパラメータストアに保管し取得している点にご注意ください
#!/bin/bash
# ログファイルの設定
LOGFILE="/var/log/fivetran-setup.log"
echo "Starting Fivetran setup process at $(date)" > ${LOGFILE}
# グループを作成
echo "Creating fivetran group..." >> ${LOGFILE}
groupadd fivetran
# ユーザーを作成
echo "Creating fivetran user..." >> ${LOGFILE}
useradd -m -g fivetran fivetran
# .ssh ディレクトリを作成
echo "Setting up SSH directory..." >> ${LOGFILE}
mkdir -p /home/fivetran/.ssh
chmod 700 /home/fivetran/.ssh
# パラメータストアから公開鍵を取得
echo "Retrieving SSH public key from Parameter Store..." >> ${LOGFILE}
SSH_PUBLIC_KEY=$(aws ssm get-parameter --name "/ssh/fivetran/public-key" --query "Parameter.Value" --output text)
# 公開鍵を authorized_keys に追加
echo "${SSH_PUBLIC_KEY}" > /home/fivetran/.ssh/authorized_keys
chmod 600 /home/fivetran/.ssh/authorized_keys
chown -R fivetran:fivetran /home/fivetran/.ssh
echo "SSH public key installed for fivetran user" >> ${LOGFILE}
# パラメータストアからAPI認証情報を取得
echo "Retrieving Fivetran API credentials from Parameter Store..." >> ${LOGFILE}
API_KEY=$(aws ssm get-parameter --name "/fivetran/api_key" --with-decryption --query "Parameter.Value" --output text)
API_SECRET_KEY=$(aws ssm get-parameter --name "/fivetran/api_secret" --with-decryption --query "Parameter.Value" --output text)
CONNECTION_ID=$(aws ssm get-parameter --name "/fivetran/connection_id" --query "Parameter.Value" --output text)
# APIキーとシークレットを結合してBase64エンコード
AUTH_HEADER=$(echo -n "${API_KEY}:${API_SECRET_KEY}" | base64)
echo "API credentials retrieved and encoded" >> ${LOGFILE}
# フィンガープリントハッシュを取得
echo "Generating SSH fingerprint hash..." >> ${LOGFILE}
HASH=$(ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub | awk '{print $2}' | sed 's/SHA256://g')
echo "Fingerprint hash: ${HASH}" >> ${LOGFILE}
# ホスト公開鍵を取得
HOST_PUBLIC_KEY=$(cat /etc/ssh/ssh_host_ecdsa_key.pub)
echo "Host public key retrieved" >> ${LOGFILE}
# API リクエストを送信
echo "Sending API request to Fivetran..." >> ${LOGFILE}
RESPONSE=$(curl -s --request POST \
--url "https://api.fivetran.com/v1/connections/${CONNECTION_ID}/fingerprints" \
--header "Accept: application/json" \
--header "Authorization: Basic ${AUTH_HEADER}" \
--header "Content-Type: application/json" \
--data "{
\"hash\": \"${HASH}\",
\"public_key\": \"${HOST_PUBLIC_KEY}\"
}")
# レスポンスをログに記録
echo "API Response: ${RESPONSE}" >> ${LOGFILE}
# 成功したかどうかを確認
if echo "${RESPONSE}" | grep -q "Success"; then
echo "SSH fingerprint successfully approved at $(date)" >> ${LOGFILE}
echo "Fivetran setup completed successfully" >> ${LOGFILE}
else
echo "ERROR: Failed to approve SSH fingerprint at $(date)" >> ${LOGFILE}
echo "Please check the API response for details" >> ${LOGFILE}
fi
ターゲットグループの作成
以下の設定でターゲットグループを作成しました。
- ターゲットタイプ:インスタンス
- プロトコル:22
NLB の作成
- スキーム:インターネット向け
- リスナー
- TCP:22
- 転送先:上記のターゲットグループ
- セキュリティグループ
- Fivetran サーバーからのポート22経由のインバウンドアクセスを許可
Auto Scaling グループの作成
上記の起動テンプレートを使用する Auto Scaling グループを作成します。基本的な設定はデフォルトのままですが、以下を変更しています。
- ロードバランサーターゲットグループ
- 上記のターゲットグループを指定
Desired Capacity は Auto Scaling グループの作成時点ではゼロにしておきました。検証手順の「Auto Scaling グループのテスト」内の項目で変更します。
その他、動的スケーリングポリシーなども設定していません。
Fivetran:APIキーの取得
Fivetran ダッシュボードで「ユーザー名 > API キー」から「Generate API key」をクリックしキーを生成します。Fivetran API の基本的な操作は以下の記事をご参照ください。
コネクションの作成
初期状態のために、はじめの SSH サーバーを別途構築し、予め Fivetran コネクションを作成します。この際、接続方法として SSH トンネルを指定すると公開鍵が生成されるのでこの値を控えておきます。
その他の設定項目は以下をご参照ください。
パラメータの作成
各種パラメータをパラメータストアに登録します。ここでは下図の通り登録しました。簡単な検証用に API キーやシークレットも通常の文字列としている点にご注意ください。
ここまでで設定は完了です。
動作確認
初期状態
前提条件に記載の通り、先に FIvetran コネクションが作成済みである状態(初期状態)を構成します。
はじめは Auto Scaling グループの Desired Capacity を 0 に設定しておいた状態で手動で SSH サーバーを起動します(上記の「コネクションの作成」の内容です)。通常と異なる点として、NLB が間にあるので SSH Host には NLB の DNS 名を指定します。
この状態で接続テスト、初期同期を実行しコネクションのステータスが「Active」であることを確認します。
Auto Scaling グループのテスト
既存の SSH サーバーをここでは削除してみます。
この状態で同期を実行すると SSH サーバーがないのでエラーとなります。
Auto Scaling グループのサイズを下図の通り変更します。
すると起動テンプレートを使用するインスタンスが立ち上がります。
インスタンス起動後の同期は問題なく実行されました。
宛先側のレコードも更新されます。
出力したログは以下のようになっていました。
$ sudo cat /var/log/fivetran-setup.log
Starting Fivetran setup process at Wed Jun 18 08:25:09 UTC 2025
Creating fivetran group...
Creating fivetran user...
Setting up SSH directory...
Retrieving SSH public key from Parameter Store...
SSH public key installed for fivetran user
Retrieving Fivetran API credentials from Parameter Store...
API credentials retrieved and encoded
Generating SSH fingerprint hash...
Fingerprint hash: xxxxx
Host public key retrieved
Sending API request to Fivetran...
API Response: {"code":"Success","message":"The fingerprint has been approved.","data":{"id":"xxxxx","hash":xxxxx","public_key":"ecdsa-sha2-nistp256 xxxxx xxxxx.ec2.internal","validated_date":"2025-06-18T08:25:14.986000Z","validated_by":"xxxxx"}}
SSH fingerprint successfully approved at Wed Jun 18 08:25:14 UTC 2025
Fivetran setup completed successfully
サーバーホストの認証がない場合
API 経由で実施しているサーバー ホストの認証がない場合の動作をみておきます。起動テンプレートの API による認証部分を無くして、インスタンスを停止します。
この場合 Auto Scaling グループによる起動後に、同期が実行されると下図のエラーとなります。
サーバーが変わったことで、指紋認証が必要というメッセージです。この場合、追加の対応が必要です。ダッシュボード上では対象のコネクションの設定画面にて再度「Save & Test」を実行し指紋を認証できます。
API の場合、以下で認証できます。
AUTH_HEADER=$(echo -n "$API_KEY:$API_SECRET_KEY" | base64)
CONNECTION_ID="xxxxx" # connectionIdを設定
# フィンガープリントハッシュを取得
HASH=$(sudo ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub | awk '{print $2}' | sed 's/SHA256://g')
curl --request POST \
--url "https://api.fivetran.com/v1/connections/${CONNECTION_ID}/fingerprints" \
--header "Accept: application/json" \
--header "Authorization: Basic ${AUTH_HEADER}" \
--header "Content-Type: application/json" \
--data "{
\"hash\": \"${HASH}\",
\"public_key\": \"${PUBLIC_KEY}\"
}"
コネクションIDはダッシュボードの場合、コネクションの「Setup」タブから確認できます。
さいごに
NLB と Auto Scaling グループで Fivetran SSH トンネルの自動復旧環境を構築してみました。
ここでは SSH サーバーをプライベートサブネットに構築しましたが、パブリックサブネットに構築することで、NAT Gateway そのものを不要にしてもよいと思いました。
こちらの内容が何かの参考になれば幸いです。