白いカードに、六角形の輪郭と小さな円で終わる回路の線からなる白い線描きの脳を配したティール色の角丸正方形のAmazon Bedrockのアイコンと、濃紺のAmazon Bedrockの文字

Bedrockのナレッジベースが削除できない — 先にOpenSearchコレクションを消すとDELETE_UNSUCCESSFULで詰む

OpenSearch Serverlessのコレクションを先に削除したため、Amazon Bedrockのナレッジベース2つがDELETE_UNSUCCESSFULで止まりました。dataDeletionPolicyをRETAINにする対処法まで。

目次

はじめに

個人のAWSアカウントで古いAmazon Bedrockのリソースを整理していたところ、2つのナレッジベースがどうしても消えませんでした。どちらもDELETE_UNSUCCESSFULのまま止まっており、コンソールはその状態を表示するだけで理由を教えてくれません。もう一度削除を押しても、3度目の同じ状態が返るだけでした。厄介だったのは、原因がすでに過去にあったことです。2つのナレッジベースが参照していたOpenSearch Serverlessのコレクションは、先に削除されていました。そして各データソースは、削除時にそのコレクションからベクトルを消す設定になっていました。何度実行しても、削除が完了することはありえなかったのです。

本記事では、この状態をCLIからどう切り分けたか、ベクトルストアがないとなぜ削除が恒久的に詰むのか、dataDeletionPolicy: RETAINという対処法、2度目の失敗を招いたUpdateDataSourceのドキュメント記載どおりの落とし穴、そしてそのすべてを避けるための削除順序を整理します。

コンソールが説明してくれないこと

ListKnowledgeBasesを実行すると、問題の形はすぐに見えます。ap-northeast-1に3つのナレッジベースがあり、うち2つが止まっています。

ターミナルウィンドウ
aws bedrock-agent list-knowledge-bases --region ap-northeast-1 --output table
knowledgeBaseId name status
ZZ01BJIIZ3 knowledge-base-quick-start-handson-classic DELETE_UNSUCCESSFUL
PUVPB8DGEL internal-assistant-knowledge-base-test DELETE_UNSUCCESSFUL
GXPMI2WL6Q knowledge-base-rag-handson DELETING

理由はもう1階層深く、一覧ビューには含まれないfailureReasons配列にあります。GetKnowledgeBaseがそれを返します。

ターミナルウィンドウ
aws bedrock-agent get-knowledge-base \
--region ap-northeast-1 --knowledge-base-id ZZ01BJIIZ3
"failureReasons": [
"Unable to delete data from vector store for data source with ID JLLYIBTATA. Check your vector store configurations and permissions and retry your request. If the issue persists, consider updating the dataDeletionPolicy of the data source to RETAIN and retry your request.",
"Unable to delete data from vector store for data source with ID JLLYIBTATA. Check your vector store configurations and permissions and retry your request. If the issue persists, consider updating the dataDeletionPolicy of the data source to RETAIN and retry your request."
]

同じ文が2回、失敗した試行ごとに1つずつ入っています。もう一方のナレッジベースも、自身のデータソースID0NRPHQMCCNに対してまったく同じメッセージを返しました。このエラーは最後の節で自分の対処法を名指ししています。しかし「権限を確認せよ」のほうを本題だと読んでしまうと、そのまま読み飛ばしてしまいます。

ベクトルストアは本当に到達可能だったのか

どちらのナレッジベースもOpenSearch Serverlessのコレクションを指していました。そのコレクションは、どちらも存在しませんでした。

ターミナルウィンドウ
aws opensearchserverless batch-get-collection --region ap-northeast-1 \
--ids rkulz4az4wngr17bmm67 6uu4dp3q3f2qqjkd2iqk
{
"collectionDetails": [],
"collectionErrorDetails": [
{ "id": "rkulz4az4wngr17bmm67", "errorMessage": "The specified Collection is not found.", "errorCode": "NOT_FOUND" },
{ "id": "6uu4dp3q3f2qqjkd2iqk", "errorMessage": "The specified Collection is not found.", "errorCode": "NOT_FOUND" }
]
}

ListCollectionsの結果も一致し、"collectionSummaries": []が返りました。アカウントにはOpenSearch Serverlessのコレクションが1つも残っていません。それにもかかわらず、2つのナレッジベースはそこを指すARNを保持したままでした。

これで、エラーを権限の問題として読む線は消えます。コレクションにアクセスできないロールと、そもそも存在しないコレクションは、よく似た失敗を出します。しかしIAMを直して解決するのは、そのうち片方だけです。

コレクションがないとなぜ削除が詰むのか

ナレッジベースの削除は2つのフェーズに分かれており、単なる帳簿上の処理なのは後半だけです。

フェーズ1はデータプレーンの操作です。データソースがdataDeletionPolicy: DELETEを持つとき、Bedrockはベクトルストアに接続し、そのデータソースが取り込んだベクトルを削除します。フェーズ2は、削除ボタンを押した人が思い浮かべているほうのコントロールプレーンの操作、つまりナレッジベースとデータソースのレコード自体を消す処理です。

フェーズ1には生きたコレクションが必要です。コレクションが失われていれば接続先がなく、呼び出しは失敗し、リソースはDELETE_UNSUCCESSFULに着地します。フェーズ2は一度も試行されません。

フェーズ 1 で止まるナレッジベースの削除DeleteKnowledgeBase のリクエストが 2 つのフェーズに分かれる。フェーズ 1 のベクトル削除は、破線で描かれ NOT_FOUND と記された OpenSearch Serverless コレクションへ右向きに伸びており、その矢印には失敗と付いている。破線が下のフェーズ 2、メタデータ削除へ続くが、こちらは灰色で「到達しない」と記されている。結果のステータスは DELETE_UNSUCCESSFUL。DeleteKnowledgeBase1フェーズ 1・ベクトル削除データプレーン。ベクトルストアに接続し、取り込み済みのベクトルを削除する。失敗OpenSearch ServerlessコレクションNOT_FOUND到達しない2フェーズ 2・メタデータ削除コントロールプレーン。ナレッジベースとデータソースのレコードを削除する。結果のステータスDELETE_UNSUCCESSFUL
削除はフェーズ1で止まります。コレクションが失われているため消す対象がなく、フェーズ2が消すはずだったメタデータはそのまま残ります。

再試行が効かないのはこのためです。削除済みのコレクションは、試行の間に何も変わりません。したがって再試行は、前提条件が恒久的に偽である呼び出しをもう一度実行するだけです。DELETINGDELETE_UNSUCCESSFULが同じstatusフィールドに並んでいるので一時的な状態に見えますが、前者は途中経過、後者は終着点です。

どちらのデータソースもポリシーを裏づけていました。

ターミナルウィンドウ
aws bedrock-agent get-data-source --region ap-northeast-1 \
--knowledge-base-id ZZ01BJIIZ3 --data-source-id JLLYIBTATA
{ "dataDeletionPolicy": "DELETE", "status": "DELETE_UNSUCCESSFUL" }

DELETEはコンソールのクイックスタートが作る既定値です。ウィザードをクリックして作ったナレッジベースは、誰も選んでいないのにこの設定を持っています。

対処法: dataDeletionPolicyをRETAINにする

RETAINは、取り込んだデータをそのまま残すようBedrockに指示します。これでフェーズ1が飛ばされ、フェーズ2が実行できます。エラー文面からそのまま提案したのはエージェントで、削除の実行を承認したのは私です。ナレッジベースごとの手順は、更新、データソースの削除、ナレッジベースの削除の順です。

ターミナルウィンドウ
aws bedrock-agent update-data-source \
--region ap-northeast-1 \
--knowledge-base-id PUVPB8DGEL --data-source-id 0NRPHQMCCN \
--name knowledge-base-quick-start-6vf5c-data-source \
--data-source-configuration '{"type":"S3","s3Configuration":{"bucketArn":"arn:aws:s3:::internal-assistant-docs"}}' \
--vector-ingestion-configuration '{"chunkingConfiguration":{"chunkingStrategy":"HIERARCHICAL","hierarchicalChunkingConfiguration":{"levelConfigurations":[{"maxTokens":1500},{"maxTokens":512}],"overlapTokens":60}}}' \
--data-deletion-policy RETAIN
aws bedrock-agent delete-data-source --region ap-northeast-1 \
--knowledge-base-id PUVPB8DGEL --data-source-id 0NRPHQMCCN
aws bedrock-agent delete-knowledge-base --region ap-northeast-1 \
--knowledge-base-id PUVPB8DGEL

ここでRETAINが何を諦めているのかは、はっきり書いておく価値があります。データ損失のように聞こえますが、そうではありません。AWSのドキュメントによれば、DELETEは「データソースを削除するときにすべてのデータを削除しますが、ベクトルストア自体は削除しません」であり、さらに**「データソースまたはナレッジベースを削除しても、ベクトルストア自体は削除されません」**と明記されています。RETAINが残すのは、ストアの中にあるベクトルだけです。そのストアがすでに破棄されているなら、取り残されるものは何もありません。

落とし穴: UpdateDataSourceはPATCHではなくPUT

最初の試みは失敗しました。しかも、エージェントが先に着手したほうのナレッジベースで失敗しました。指定しなかったフィールドは変更されないフィールドである、という一見もっともらしい前提で、--vector-ingestion-configuration引数を省いたためです。

aws: [ERROR]: An error occurred (ValidationException) when calling the UpdateDataSource operation: vectorIngestionConfiguration.chunkingConfiguration cannot be updated once created.

このAPIはPUT /knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}です。つまり省略したフィールドは、そのままにしたいフィールドではなく、消そうとしているフィールドとして扱われます。リファレンスもリクエスト構文の上の注意書きでそう述べています。「データソースコネクタの作成後にchunkingConfigurationを変更することはできません。既存のchunkingConfigurationを指定してください」。リソースを読み、1つのフィールドだけを変え、全体をそろえて送り返します。

この失敗は、時間を食うタイプの静かな失敗でした。更新コマンドは非ゼロで終了したのに、その後ろの2つの削除コマンドはそのまま実行され、どちらもDELETINGを返したのです。これは成功のように読めます。約4分後、ナレッジベースは新しいタイムスタンプとともにDELETE_UNSUCCESSFULに戻っていました。ポリシーがDELETEのままだったので、以前とまったく同じフェーズ1の失敗をたどったわけです。既存の階層チャンク設定を含めて更新を送り直すと"dataDeletionPolicy": "RETAIN"が返り、そこで削除が完了しました。

**前提条件の失敗は、後続のコマンドを止めてくれません。**削除コマンド自体の終了コードを見るのではなく、削除を投げる前にポリシーが実際にRETAINになっていることを確認してください。

検証

2つのナレッジベースは消えました。最初の一覧の時点から削除中だった3つ目も、あわせて消えています。

ターミナルウィンドウ
aws bedrock-agent list-knowledge-bases --region ap-northeast-1 --output json
{
"knowledgeBaseSummaries": []
}

DELETINGだったGXPMI2WL6Qは、手を加えなくても自力で完了しました。こちらもコレクションは失われていたため、同じ失敗に陥る可能性がそもそもあったのかどうかは、このセッションでは確認できていません。

削除後には、IAMのサービスロールが2つ残りました。どちらもAmazonBedrockExecutionRoleForKnowledgeBase_<suffix>という形式で、末尾はコンソールが付けたランダムな文字列です。ナレッジベースを削除しても、コンソールがそのために作成した実行ロールは消えません。

依存関係の順に削除する: ナレッジベース、次にOpenSearch、最後にS3

今回の一件は、次の一般則の一例です。**他に依存しているリソースを、依存される側より先に削除する。**Bedrockのナレッジベースは自分が所有していない2つのものの上に乗っており、自身の削除を完了するには、そのうち1つが生きている必要があります。

ナレッジベースの削除順序2 つの列が並ぶ。左は誤った順序で、OpenSearch Serverless コレクションを先に削除したため、続くナレッジベースの削除はフェーズ 1 に削除対象がなく DELETE_UNSUCCESSFUL で終わる。右は正しい順序で、データソースを含むナレッジベース、OpenSearch Serverless コレクションとアクセスポリシー、S3 バケットの順に、各ステップが完了する。誤った順序1OpenSearch Serverlessコレクションを先に削除2ナレッジベースDELETE_UNSUCCESSFULフェーズ 1 に削除対象がなく、削除は完了しない。再試行しても同じ失敗が返るだけ。正しい順序1ナレッジベースデータソースを含めて削除2OpenSearch Serverlessコレクションと各種ポリシー3S3 バケット取り込み元のドキュメント各ステップが完了する。Bedrock はベクトルストアもバケットも削除しない。
ここでほかのリソースが生きていないときれいに削除できないのは、ナレッジベースだけです。コレクションを先に消すことが、ナレッジベースを取り残す原因になります。
  1. まずナレッジベース、データソースも含めて削除します。生きた依存関係を持つのはこのステップだけです。フェーズ1がベクトルストアに手を伸ばすため、コレクションはまだ存在している必要があります。
  2. 次にOpenSearch Serverless。コレクションと、あわせて作成されたセキュリティ、ネットワーク、データアクセスの各ポリシーを削除します。Bedrock側でこれらを消してくれるものはなく、ドキュメントにもそう明記されています。コレクションはコスト面でも中心で、クエリ量に関係なくOCU時間で課金されます。
  3. 最後にS3。バケットは取り込み時にしか読まれないので、削除の妨げにはなりません。最後に回すのは、これが元ドキュメントの控えだからです。削除が早すぎたと後で判断した場合、再取り込みが最も安く済む復旧手段になります。

コンソールはこの順序を強制しませんし、ナレッジベースがまだ指しているコレクションを削除しようとしても警告は出ません。理由は先ほど引用したドキュメントに表れています。Bedrockはベクトルストアを利用者のものとして扱い、決して削除せず、したがってナレッジベースのライフサイクルの一部ともみなしません。設計としては妥当で、その結果として順序の管理が完全に利用者側に委ねられているわけです。

まとめ

2つのナレッジベースがDELETE_UNSUCCESSFULで止まっていたのは、参照先のOpenSearch Serverlessコレクションが先に削除されており、dataDeletionPolicy: DELETEのデータソースが、もう存在しないストアからベクトルを消そうとし続けていたからです。各データソースにdataDeletionPolicy: RETAINを設定することでその処理が飛ばされ、どちらの削除も完了しました。

覚えておく価値があるのは次の3点です。

  • **DELETE_UNSUCCESSFULは終着点であって、一時的な状態ではありません。**再試行する前にGetKnowledgeBasefailureReasonsを読み、IAMに手を付ける前にベクトルストアがまだ存在するかどうかを確かめてください。
  • **UpdateDataSourceはリソースを置き換えます。**既存のchunkingConfigurationを送り直し、それに依存する削除を実行する前に、変更したかったフィールドが実際に変わったことを確認してください。
  • **依存関係の順に削除してください。**ナレッジベース、次にOpenSearch Serverless、最後にS3です。強制する仕組みはなく、最初の2つを逆にしたのが、ここまで説明してきた失敗です。

参考リンク

この記事をシェア