EFS マウント接続を修復する

AWSBeginner
オンラインで実践に進む

はじめに

A は共有アップロードを読めますが、B は同じ EFS に接続できません。失敗した接続を診断して B のマウントを復旧し、対象のアプリケーションだけにアクセスを許可します。

先に前の 2 つの EFS 実験を完了してください。この新環境には既存ファイルシステム、アクセス・ポイント、元のファイル、ホストが用意されています。設定済み AWS CLI、SSH、AWS View を使います。前の VM のリソースや個人の AWS アカウントは不要です。

認定試験との関連

認定 試験タスク 実践
Cloud Practitioner (CLF-C02) Task 3.5; Task 3.6 ファイル接続と VPC セキュリティグループを関連付け、ストレージの利用可能状態とネットワーク到達性を区別する。

概要

概念図です。識別子は新しい環境で確認してください。

NFS ネットワーク規則を診断して修復する

このステップでは、失敗している層を特定してストレージのセキュリティグループを修復します。

/home/labex/project で作業します。resources.json にストレージとアプリケーションの識別子があります。

cd /home/labex/project
aws sts \
  get-caller-identity
FS_ID=$(jq -r .fault.filesystem_id resources.json)
MOUNT_TARGET_ID=$(jq -r .fault.mount_target_id resources.json)
AP_ID=$(jq -r .fault.access_point_id resources.json)
EFS_GROUP_ID=$(jq -r .fault.storage_group_id resources.json)
APP_GROUP_ID=$(jq -r .application_group_id resources.json)
APP_A_IP=$(jq -r '.clients["application-a"].ip' resources.json)
echo "$FS_ID"
echo "$MOUNT_TARGET_ID"
echo "$AP_ID"
echo "$EFS_GROUP_ID"
echo "$APP_GROUP_ID"
echo "$APP_A_IP"

両アプリケーションから既存アップロードを読みます。

curl -i http://127.0.0.1:8081/uploads/original-upload.txt
curl -i http://127.0.0.1:8082/uploads/original-upload.txt

A は 200 OK と Original upload from application A、B は 404 Not Found を返します。マウントを確認します。

ssh -F ssh_config application-a 'findmnt -t nfs4 /srv/shared'
ssh -F ssh_config application-b 'findmnt -t nfs4 /srv/shared'

A には NFS マウントがあり、B にはありません。B の findmnt は状態 1 を返します。パスや権限を変える前に、B が接続先へ到達できるか確認します。

MOUNT_IP=$(aws efs \
  describe-mount-targets \
  --mount-target-id "$MOUNT_TARGET_ID" \
  --query 'MountTargets[0].IpAddress' --output text)
echo "$MOUNT_IP"
ssh -F ssh_config application-b "nc -zvw2 $MOUNT_IP 2049"

接続は失敗します。nc はマウントせず TCP 到達性を確認します。アクセス・ポイントのルートや POSIX ID の誤りは接続後のファイル操作を妨げますが、この TCP 失敗の原因ではありません。

ターゲットが利用可能か、どのグループが付いているか確認します。

aws efs \
  describe-mount-targets \
  --mount-target-id "$MOUNT_TARGET_ID" \
  --query 'MountTargets[].{ID:MountTargetId,State:LifeCycleState,Subnet:SubnetId}'
aws efs \
  describe-mount-target-security-groups \
  --mount-target-id "$MOUNT_TARGET_ID"
aws ec2 \
  describe-security-groups \
  --group-ids "$EFS_GROUP_ID" \
  --query 'SecurityGroups[].IpPermissions'

NFS ルールは /32 CIDR で A のプライベートアドレスだけに TCP 2049 を許可しています。B は含まれません。アプリケーショングループの規則に置き換えます。

aws ec2 \
  revoke-security-group-ingress \
  --group-id "$EFS_GROUP_ID" \
  --protocol tcp \
  --port 2049 \
  --cidr "$APP_A_IP/32"

グループの両メンバーに許可します。

aws ec2 \
  authorize-security-group-ingress \
  --group-id "$EFS_GROUP_ID" \
  --ip-permissions "IpProtocol=tcp,FromPort=2049,ToPort=2049,UserIdGroupPairs=[{GroupId=$APP_GROUP_ID}]"
ssh -F ssh_config application-b "nc -zvw2 $MOUNT_IP 2049"

新しい接続は成功します。0.0.0.0/0 に開放したりファイルシステムを交換したりせず、ネットワークを修復しました。

B のアクセス・ポイントマウントを復旧する

このステップでは、A のデータを置き換えず B を既存の共有ディレクトリに接続します。

マウント前に既存ポイントを確認します。

aws efs \
  describe-access-points \
  --access-point-id "$AP_ID" \
  --query 'AccessPoints[].{ID:AccessPointId,Root:RootDirectory.Path,User:PosixUser}'

ルートは /uploads、数字 ID は準備済みアプリケーションユーザーのものです。同じアップロードを共有するため、両アプリケーションは同じポイントを選びます。新しいファイルシステムや B のローカルコピーを作らないでください。

公式ヘルパーと TLS で B にマウントします。

ssh -F ssh_config application-b \
  "sudo mkdir -p /srv/shared && sudo mount -t efs -o tls,stunnel,lookupcache=positive,accesspoint=${AP_ID} ${FS_ID}:/ /srv/shared"
ssh -F ssh_config application-b 'findmnt -t nfs4 /srv/shared'

lookupcache=positive は、別のアプリケーションがファイルを作成すると以前存在しなかった名前を再問い合わせします。短い実験で結果を確認できます。本番のキャッシュ調整では性能を別途評価してください。Linux NFS キャッシュ設定を参照できます。

B は /srv/shared に NFS 4 を表示します。アプリケーションはこのパスを使用する設定なので、次のリクエストで EFS を直接読みます。

curl -i http://127.0.0.1:8082/uploads/original-upload.txt
ssh -F ssh_config application-a 'stat -c "%i %u:%g" /srv/shared/original-upload.txt'
ssh -F ssh_config application-b 'stat -c "%i %u:%g" /srv/shared/original-upload.txt'

B は元の内容を返し、両ホストの inode と所有者は一致します。別のコピーではなく既存ファイルへのアクセスを復旧しました。

新しいアップロードとアクセス境界を確認する

このステップでは、B の共有書き込みと無関係なクライアントの除外を確認します。

B から新規ファイルをアップロードし A から読みます。

curl -i -X PUT --data-binary 'Shared upload after connection repair' \
  http://127.0.0.1:8082/uploads/shared.txt
curl -i http://127.0.0.1:8081/uploads/shared.txt

B は 201 Created、A は同じ内容で 200 OK を返します。AWS View の両カードで shared.txt を読みます。

参照サーバーは別のグループです。新しい NFS 接続ができないことを確認します。

ssh -F ssh_config reference-c "nc -zvw2 $MOUNT_IP 2049"

この接続はゼロ以外の終了状態で失敗するはずです。これは意図した境界であり、別のアプリケーション障害ではありません。参照サーバー独自のアップロードを確認します。

curl -i http://127.0.0.1:8083/uploads/reference.txt

200 OK と Unrelated reference upload remains unchanged を返します。修復済みアプリケーションと参照サービスのネットワーク範囲は異なります。

AWS View の復旧したアップロード

両アプリケーションが新しい共有アップロードを読みます。識別子は環境ごとに異なります。

ストレージを解放する

このステップでは、修復確認後に一時ストレージを削除し、ホストとネットワークを残します。

両アプリケーションをローカルディレクトリに戻しアンマウントします。

ssh -F ssh_config application-a \
  'printf "{\"upload_directory\":\"/srv/uploads\"}\n" | sudo tee /etc/uploads-app/config.json'
ssh -F ssh_config application-b \
  'printf "{\"upload_directory\":\"/srv/uploads\"}\n" | sudo tee /etc/uploads-app/config.json'
ssh -F ssh_config application-a 'sudo umount /srv/shared'
ssh -F ssh_config application-b 'sudo umount /srv/shared'

resources.json の識別子に一致するリソースだけを削除します。ポイントとマウントターゲットから始めます。

aws efs \
  delete-access-point \
  --access-point-id "$AP_ID"
aws efs \
  delete-mount-target \
  --mount-target-id "$MOUNT_TARGET_ID"
aws efs \
  describe-mount-targets \
  --file-system-id "$FS_ID"

MountTargets が空になったらファイルシステムと専用グループを削除します。

aws efs \
  delete-file-system \
  --file-system-id "$FS_ID"
aws ec2 \
  delete-security-group \
  --group-id "$EFS_GROUP_ID"

成功した空の応答を確認します。

aws efs \
  describe-file-systems \
  --query 'FileSystems[?Name==`fs03-shared-uploads`].FileSystemId'
aws ec2 \
  describe-security-groups \
  --filters Name=group-name,Values=fs03-efs-access \
  --query 'SecurityGroups[].GroupId'

ストレージのリストは空になるはずです。サーバー、元のグループ、サブネット、参照ファイルは残します。許可された問い合わせができる間に削除チェックを実行します。

まとめ

リソース状態、TCP 到達性、マウント選択、ファイル権限を区別して診断しました。アプリケーショングループで規則を修復し、B の元のファイルへのアクセスと新規共有アップロードを確認し、参照クライアントを除外したままにしました。最後に依存順でストレージを削除しました。

詳しくは、AWS 公式ドキュメントを参照してください:クライアントとマウントターゲットのネットワークルール; マウントのタイムアウトとアクセス失敗を診断する。