Lambdaで天気情報を取得するツールのロジック修正とECRリポジトリを作成を行いました
AWS Lambdaを活用して、OpenWeatherMap APIから天気情報を取得するアプリケーションを作っています。
この記事では以下を行います。
Lambdaのロジック改善
Terraformを使ってECRリポジトリの作成
AWS CLIによるリソースの存在確認
1. Lambda用のロジックの改善
OpenWeatherMap APIから天気情報を取得するためのAPIキーを事前にAWSのParameter Storeに保存しており、そのAPIキーの取得方法について、boto3を使うか、TerraformでParameter Storeを定義するかを検討しました。
それぞれのメリット・デメリットは以下のようになると思います。
boto3
メリット:
動的にAPIキーを取得可能で、環境に依存せずに柔軟に運用できる。
デプロイ時の更新作業が不要で、変更が即時反映される。
ローカル開発と本番環境で同一のコードを使用可能。
デメリット:
追加のコードが必要で、依存ライブラリが増える。
Lambda実行時に毎回APIコールが発生し、わずかな遅延がある。
Terraform
メリット:
APIキーの管理が一元化され、インフラ全体の整合性を保ちやすい。
リソース管理がコードベースで行え、インフラの再現性が高い。
デメリット:
APIキーの変更には再デプロイが必要。
キーが環境変数に保存されるため、セキュリティリスクが高まる。
今回はローカル開発と本番環境の動作を統一しやすいboto3を採用しました。
Pythonのファイルは以下のようになっています。
import json
import requests
import boto3
from mypy_boto3_ssm import SSMClient
import os
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def get_weather(api_key, location):
url = f'https://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}&units=metric'
try:
response = requests.get(url)
response.raise_for_status()
weather_data = response.json()
temperature = weather_data['main']['temp']
weather_description = weather_data['weather'][0]['description']
return {
'temperature': temperature,
'description': weather_description
}
except requests.exceptions.RequestException as e:
return {'error': str(e)}
except Exception as e:
return {'error': str(e)}
def get_api_key():
profile_name = os.getenv('AWS_PROFILE')
session = boto3.Session(profile_name=profile_name)
ssm: SSMClient = session.client('ssm', region_name='ap-northeast-1')
response = ssm.get_parameter(
Name='/weather-checker/api-key',
WithDecryption=True
)
return response['Parameter']['Value']
def lambda_handler(event, context):
api_key = get_api_key()
location = 'Naha,Okinawa,JP' # 天気情報を取得したい場所。値は外部から受け取れるように変更予定
weather_info = get_weather(api_key, location)
if 'error' in weather_info:
logger.error(f"Failed to fetch weather data: {weather_info}")
return {
'statusCode': 500,
'body': json.dumps(weather_info)
}
logger.info(f"Successfully fetched weather data: {weather_info}")
return {
'statusCode': 200,
'body': json.dumps({
'location': location,
'temperature': weather_info['temperature'],
'description': weather_info['description']
})
}
if __name__ == "__main__":
result = lambda_handler(None, None)
print(result)
2. AWSで必要なリソースの確認
Lambdaを動作させるために必要なリソースとして、以下が必要になると考えています。
Lambda: メインのコードを実行するリソース。
ECRリポジトリ: Dockerイメージをホスティングするためのリソース。今回はLambdaをコンテナ形式で実行するため必要になる。
CloudWatch: 処理に関連するログを出力するロググループなどが必要になる想定。また、後からLambdaをスケジュール実行で動かす時はCloudWatch eventsが必要になる。
IAM関連: IAM Roleやポリシーなどで適切な権限設定を行う。
3. ECRリポジトリのTerraform構築
まず、簡単に作成できるECRリポジトリをTerraformで定義しました。Terraformコードでは、ECRに対してイメージのスキャンを有効にし、リポジトリの暗号化設定はデフォルトのままにしています。
resource "aws_ecr_repository" "weather_checker" {
name = "weather-checker"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = true
}
tags = {
Environment = "Production"
Project = "WeatherChecker"
}
}
`terraform plan`コマンドでリソースの内容に問題ないことを確認し、`terraform apply`で適用を行いました。
4. AWS CLIでリソース確認
`terraform apply`を実行してリソースをデプロイした後、以下のAWS CLIコマンドを使用してECRリポジトリの存在を確認しました。
aws ecr describe-repositories --repository-names weather-checker --region ap-northeast-1
CLIの出力結果で想定通りECRリポジトリが作成されていることが確認できました。
マネジメントコンソールからも以下のように確認できました。
[f:id:JunpeiNakasone:20240913152040p:plain]
5. この後、Lambdaを実行するために必要な作業の確認
次のステップとして、以下のような作業を行う予定です。
Lambdal、CloudWatch、IAMをTerraformで定義しapply
DockerfileからDockerイメージをビルドしECRにプッシュする仕組みを構築(local-execが使えるっぽい?)
Lambdaの実行確認
進めながら見落としなどに気づくかも知れませんが、少しずつ進めていきます。