CI/CDパイプラインを意図的に壊した話—Devinがどう修正したか(そしてどこで失敗したか)
私は3年間、AWS上で小規模なSaaSアプリケーションを運用してきました。私のCI/CDパイプラインは、GitHub Actions、Terraform、そして共同創業者が午前2時に書いたbashスクリプトが混在した、いわばフランケンシュタインのようなものでした。先週、誤って設定されたIAMポリシーにより、デプロイメントが6時間にわたって静かに失敗し続けました。そこで私は、AIソフトウェアエンジニアであるDevinを実際のDevOps業務でテストすることを決意しました。
Devinを3つの本番級DevOpsタスクに投入した結果をご紹介します:壊れたパイプラインのデバッグ、インフラストラクチャのプロビジョニング、データベースの移行です。結果は驚くべきものであり、苛立たしいものであり、最終的には有用なものでした。
DevOpsにおけるDevinの実際の機能(そして機能しないこと)
Devinは、コードの実行、ターミナルコマンドの実行、クラウドAPIとの連携が可能な自律型AIエージェントです。単なる高機能チャットボットではなく、独自のワークスペース、ブラウザ、シェルを持っています。しかし、重要な注意点があります:Devinはビジネスコンテキストを理解しません。本番データベースに50GBの顧客データがあることや、ステージング環境が5つのチームで共有されていることを知りません。
私はこれを痛い目で学びました。「デプロイメントパイプラインを修正して」とDevinに依頼したところ、「誤設定された」タスク定義を発見し、ECSクラスター全体を削除しようとしました。私が監視していて良かったです。
タスク1:壊れたGitHub Actionsパイプラインのデバッグ
問題: ECSにデプロイするためのGitHub Actionsワークフローが、terraform applyステップで不可解なエラーで失敗していました:Error: error reading ECS service: AccessDeniedException。
Devinに与えたもの: 失敗したGitHub Actions実行へのリンク、リポジトリURL、エラーメッセージ。
Devinのアプローチ:
- リポジトリをクローンし、ワークフローのYAMLファイルを読み取りました。
- ローカルで
terraform planを実行してエラーを再現しました。 - GitHub ActionsランナーにアタッチされたIAMロールを調査しました。
- ロールに
ecs:DescribeServices権限が欠けていることを特定しました。
修正: Devinは不足していたIAMポリシーステートメントをTerraformモジュールに追加し、PRを作成しました。
うまくいった点: Devinは2分以内に根本原因を正確に特定しました。なぜその権限が必要なのかを説明するコメントまで追加しました。
うまくいかなかった点: DevinはIAMロールが他のワークフローと共有されているかどうかを確認しませんでした。その修正により、同じロールがこのパイプラインで使用される特定のECSサービスのみでなく、すべてのECSサービスにアクセスできるようになっていました。ポリシーを特定のサービスARNにスコープする必要がありました。
教訓: Devinは権限エラーの絞り込みに優れていますが、変更の影響範囲を必ずレビューする必要があります。
タスク2:Terraformを使用したインフラストラクチャのプロビジョニング
問題: RDS PostgreSQLデータベース、ECS Fargateクラスター、Application Load Balancerを備えた新しいステージング環境を立ち上げる必要がありました。
Devinに与えたもの: 高レベルの説明:「us-east-1にPostgreSQLデータベース(db.t3.micro)、単一コンテナを実行するFargateクラスター、それを指すALBを備えたステージング環境を作成してください。」
Devinのアプローチ:
- ゼロから新しいTerraformモジュールを作成しました。
- VPC、サブネット、セキュリティグループ、インターネットゲートウェイを定義しました。
- 指定されたインスタンスクラスでRDSインスタンスを構成しました。
- ECSクラスターとタスク定義を設定しました。
- ALBがコンテナにトラフィックを転送するように配線しました。
出力: 最初のterraform applyで実際に動作した300行のTerraform構成。
うまくいった点: Devinはベストプラクティスに従いました—RDSとECSに別々のサブネットを使用し、ストレージ暗号化を有効にし、適切なヘルスチェックパスを設定しました。
うまくいかなかった点: 3つの問題:
- Devinはデータベースパスワードをデフォルト値のない変数としてハードコードしました。
terraform applyを実行したとき、変数が設定されていなかったため失敗しました。 - ステートファイル用のS3バケットを作成しましたが、バージョニングや暗号化を有効にしませんでした。
- ALBのセキュリティグループがポート80で
0.0.0.0/0に対して完全に開放されていました。
教訓: Devinのインフラストラクチャコードは構文的には正しいですが、セキュリティに無頓着です。デプロイ前に必ずネットワークルールと暗号化設定を監査してください。
タスク3:ダウンタイムゼロのデータベース移行
問題: PostgreSQLデータベースを単一のRDSインスタンスから、ダウンタイムなしで読み取りレプリカ構成に移行したいと考えていました。
Devinに与えたもの: 「読み取りレプリカをプライマリに昇格させ、アプリケーションの接続文字列を更新し、データ整合性を検証するスクリプトを作成してください。」
Devinのアプローチ:
boto3を使用して読み取りレプリカを昇格させるPythonスクリプトを作成しました。- Route53でRDSインスタンスのエンドポイントを更新するLambda関数を作成しました。
- サンプル行のチェックサムを実行する検証ステップを追加しました。
出力: エラーハンドリングとロギングを含む150行のスクリプト。
うまくいった点: Devinは昇格プロセスを正しく処理しました—レプリケーションを停止し、レプリカが追いつくのを待ってから昇格させました。Route53の更新はアトミックでした。
うまくいかなかった点: Devinのスクリプトは、アプリケーションがステートレスで、短時間の接続中断を処理できると想定していました。実際のアプリケーションには、失敗する長時間実行のデータベーストランザクションがありました。さらに重要なことに、Devinはアプリケーションのコネクションプールが古いプライマリへの古い接続を保持しているケースを考慮していませんでした。昇格後にアクティブな接続を強制終了するために、pg_terminate_backend呼び出しを追加する必要がありました。
教訓: Devinは移行スクリプトを作成できますが、アプリケーション固有の状態管理を理解していません。手動でコネクションプーリングとトランザクションタイムアウトを処理する必要があります。
DevOpsにおけるDevinの限界
3つのタスクを経て、私の正直な評価は以下の通りです:
得意なこと:
- 権限エラーの再現と診断
- ボイラープレートのTerraformやCloudFormationの生成
- 反復的なタスクのスクリプト作成(例:キーのローテーション、古いリソースのクリーンアップ)
- 既存のインフラストラクチャのドキュメント作成
苦手なこと:
- 人間のレビューなしでの本番環境の変更(物事を壊します)
- コストへの影響の理解(
m5.largeが必要かどうかを確認しません) - ステートフルサービスの処理(データベース、メッセージキュー、キャッシュ)
- セキュリティ強化(デフォルトで寛容な設定になります)
DevOpsでDevinを使用するための実践的なワークフロー
この実験の後、私は厳格なワークフローを採用しました:
Devinをサンドボックス環境に隔離する。 本番環境への読み取り専用アクセスとサンドボックスアカウントへのフルアクセスを持つIAMロールを持つ別のAWSアカウントを作成しました。
最初に詳細な仕様を書く。 Devinに明示的な制約を含むMarkdownファイルを与えます:「t3.mediumではなくt3.smallを使用。削除保護を有効に。すべてのリソースにProject:Stagingのタグを付ける。」
すべてのネットワークルールをレビューする。 Devinは一貫してポートを広く開けすぎます。現在は、Devinが生成したすべてのTerraformプランの後に、
0.0.0.0/0ルールにフラグを立てるカスタムスクリプトを実行しています。ロールアウト前にロールバックをテストする。 Devinはロールバックスクリプトを作成しません。作成スクリプトと一緒に破棄スクリプトも生成するよう依頼しています。
状態を決して信頼しない。 Devinは喜んで間違ったワークスペースで
terraform destroyを実行します。現在は、すべてのコマンドで明示的にワークスペース名を渡しています。
私が驚いたこと
Devinはログの読み取りに驚くほど優れています。失敗しているアプリケーションのCloudWatchログスニペットを与えたところ、問題がデータベースの問題ではなく、不足している環境変数であることを正確に特定しました。そして、ECSタスク定義を通じてその変数を追跡し、スペルミス(DATABASE_URL vs DATABASE_UR)を発見しました。これにより、手動でのログ調査の1時間が節約されました。
次のステップ
本番環境から始めないでください。以下をお勧めします:
- 50ドルのクレジットで使い捨てのAWSアカウントを作成する。
- Devinにシンプルな2層アプリケーション(Webサーバー+データベース)をプロビジョニングするタスクを与える。
- 意図的にインフラストラクチャを壊す—セキュリティグループルールを削除する、サブネットCIDRを変更する—そしてDevinが問題を診断できるか確認する。
- その後にのみ、APIキーのローテーションやCloudWatchアラームの更新など、実際の重要ではないタスクを与える。
DevinはDevOps作業を高速化しますが、新しい障害モードも作成します。それがツールであってエンジニアではないことを忘れた瞬間、本番環境がダウンします。
さあ、サンドボックスアカウントで何かを壊して、Devinに修正させてみてください。