シニアエンジニアとして、AWS Lambdaの依存関係の地雷原を歩く皆さん、お疲れ様です。今回は、非常に頻繁に遭遇するPythonのインポートエラー、特にurllib3に関連する厄介な問題に焦点を当てます。ローカルで動いていたPythonコードがLambdaにデプロイした途端に動かなくなる、あの時の絶望感を再現するようなエラーに遭遇しました。
何が起きたか(課題)
多くのAWS Lambdaユーザーが直面するのは、以下のエラーです。
Cannot import name 'default_ciphers' from 'urllib3.util.ssl'
このエラーが発生すると、requestsやboto3など、外部通信やAWS SDKに依存する処理がすべて停止します。具体的なリスクは以下の通りです。
- 外部APIへのHTTPS接続が失敗する
- AWSサービスへの認証や操作ができなくなる
- サービス全体がダウンする可能性がある
どう解決したか(概要)
この問題の根本原因は、ローカル開発環境(macOSやWindows)とAWS Lambdaの実行環境(Linux)間のバージョンミスマッチとOSの差異にあります。Lambdaランタイムにプリインストールされている古いバージョンのライブラリと、ユーザーが追加した新しいライブラリが競合することで、新しいバージョンで期待される機能が見つからなくなります。
恒久的な解決策は、依存関係をターゲットランタイム(Linux)に合わせて完全に再ビルドすることです。
構造的要因の理解
urllib3は通信の根幹であり、多くのライブラリが依存しています。この競合を避けるには、開発者が手動で環境を合わせる必要があります。シニアエンジニアの知見として、macOSやWindowsでビルドしたパッケージをそのまま使うと、バイナリ互換性の問題が必ず発生します。
解決アプローチの要点
- 環境統一: ローカルのPythonバージョンをLambdaランタイムに合わせる。
-
クリーンインストール: LambdaのLinux環境を模倣した環境(Docker推奨)で
pip install -t ./packageを実行し、依存関係をクリーンにビルドする。 -
パッケージング:
boto3などの標準ライブラリを除外し、ビルドした依存関係とハンドラコードをZIPにまとめる。
特に、IaCツールであるSAM(Serverless Application Model)を利用し、sam build --use-containerを実行することで、ビルドプロセス全体を自動化し、Linux環境でのビルドを強制するのが最も確実な手順です。
効果(Before/After)
対策前は、デプロイのたびにランタイムエラーに悩まされ、デバッグに膨大な時間を費やしていました。しかし、DockerやSAMを使用したLinux互換ビルドに移行した結果、この種のインポートエラーは完全に発生しなくなりました。
| 項目 | 対策前(ローカルビルド) | 対策後(Linux/Dockerビルド) |
|---|---|---|
| 安定性 | 低い(OS依存) | 非常に高い |
| エラー頻度 | 高(デプロイごとに再発) | ゼロ(ビルドプロセスで吸収) |
| 開発速度 | 低(トラブルシューティング優先) | 高(標準化されたプロセス) |
この手順により、Pythonコードの安定稼働とデプロイの信頼性が劇的に向上しました。
🚀 詳細な設定とコードはこちら
具体的なWAFのルール設定や、より詳細なログ解析データは元のブログで公開しています。