Terraformで構築するAWS上のセッションマネージャーを用いたStreamlitアプリ開発環境

## 概要

s02_streamlit_aws_deployerは、AWS上でStreamlitアプリケーションを自動的にデプロイし、スケジュールに基づいて管理するための高度なTerraformスクリプトです。このサンドボックス環境は、より複雑なAWSインフラストラクチャを構築し、自動化された運用を実現します。

>こちらのTerraformのスクリプトは[LLMのためのTerraformスクリプト生成の要件定義書](https://github.com/Sunwood-ai-labs/aws-terraform-sandbox/blob/main/docs/REQUIREMENTS_DEFINITION.md)とClaude 3.5 Sonnetを組み合わせて作成したものです。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">LLMのためのTerraformスクリプト生成の要件定義書から生成したスクリプトで無事にセッションマネージャーを通じてSSH接続できた！！<br>こんなに簡単にできるとは。。。SSHキーの作成とIAMユーザーの設定だけでできるのめちゃ楽！！！ <a href="https://t.co/VKZBpyzmRJ">https://t.co/VKZBpyzmRJ</a> <a href="https://t.co/LRoXDX9BsA">pic.twitter.com/LRoXDX9BsA</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1822016355228643766?ref_src=twsrc%5Etfw">August 9, 2024</a></blockquote> 


## 主な特徴

1. **自動スケジューリング**: CloudWatchイベントを使用して、平日の朝8時に自動起動し、正午に自動停止します。
2. **セキュアなリモートアクセス**: AWS Systems Manager Session Managerを使用して、セキュアなリモートアクセスを提供します。
3. **カスタマイズ可能**: 変数を使用して、プロジェクト名、リージョン、インスタンスタイプなどを簡単にカスタマイズできます。
4. **包括的なネットワーク構成**: VPC、サブネット、インターネットゲートウェイ、ルートテーブルを含む完全なネットワークセットアップを提供します。

## 主要なAWSリソースとコード解説

### 1. VPCとネットワーキング

```hcl
resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support = true

  tags = {
    Name = "${var.project_name}-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = var.public_subnet_cidr
  availability_zone = "${var.aws_region}a"

  tags = {
    Name = "${var.project_name}-public-subnet"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "${var.project_name}-igw"
  }
}
```

このコードブロックでは、VPC、パブリックサブネット、インターネットゲートウェイを作成しています。VPCはプライベートなネットワーク空間を提供し、パブリックサブネットはインターネットからアクセス可能なリソースを配置します。インターネットゲートウェイはVPCとインターネットの接続を可能にします。

### 2. コンピューティング

```hcl
resource "aws_instance" "streamlit" {
  ami           = var.ami_id
  instance_type = var.instance_type
  key_name      = var.key_name
  subnet_id     = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.streamlit.id]
  associate_public_ip_address = true
  iam_instance_profile = aws_iam_instance_profile.ec2_profile.name

  user_data = <<-EOF
              #!/bin/bash
              apt-get update
              apt-get install -y python3-pip
              pip3 install streamlit
              echo "import streamlit as st" > app.py
              echo "st.title('Hello, Streamlit!')" >> app.py
              nohup streamlit run app.py --server.port 8501 --server.address 0.0.0.0 &
              EOF

  tags = {
    Name = "${var.project_name}-instance"
  }
}
```

このEC2インスタンスリソースは、Streamlitアプリケーションをホストします。`user_data`セクションでは、インスタンス起動時に自動的にStreamlitをインストールし、シンプルなアプリケーションを実行します。

### 3. セキュリティ

```hcl
resource "aws_security_group" "streamlit" {
  name        = "${var.project_name}-sg"
  description = "Security group for Streamlit app"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 8501
    to_port     = 8501
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "${var.project_name}-sg"
  }
}
```

このセキュリティグループは、EC2インスタンスへのアクセスを制御します。SSH（ポート22）とStreamlit（ポート8501）へのインバウンドトラフィックを許可し、すべてのアウトバウンドトラフィックを許可しています。

### 4. 自動化とモニタリング

```hcl
resource "aws_cloudwatch_event_rule" "start_instance" {
  name                = "${var.project_name}-start-instance"
  description         = "Start EC2 instance at 8:00 AM"
  schedule_expression = "cron(0 8 ? * MON-FRI *)"
}

resource "aws_cloudwatch_event_target" "start_instance" {
  rule      = aws_cloudwatch_event_rule.start_instance.name
  target_id = "StartInstance"
  arn       = "arn:aws:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:automation-definition/AWS-StartEC2Instance"
  role_arn  = aws_iam_role.cloudwatch_events.arn

  input = jsonencode({
    InstanceId = [aws_instance.streamlit.id]
  })
}
```

このCloudWatchイベントルールとターゲットは、平日の朝8時にEC2インスタンスを自動的に起動します。同様のルールが正午のインスタンス停止にも設定されています。

## 設定とカスタマイズ

`terraform.tfvars`ファイルを使用して、以下の主要な変数をカスタマイズできます：

```hcl
aws_region         = "ap-northeast-1"
project_name       = "streamlit-app"
vpc_cidr           = "10.0.0.0/16"
public_subnet_cidr = "10.0.1.0/24"
ami_id             = "ami-0d52744d6551d851e"  # Ubuntu 20.04 LTS in us-west-2
instance_type      = "t2.micro"
key_name           = "streamlit-terraform-keypair-tokyo-PEM"
```

これらの変数は`variables.tf`ファイルで定義されており、プロジェクトの主要な設定を簡単に変更できます。

## デプロイメントプロセス

1. 適切なディレクトリに移動: `cd s02_streamlit_aws_deployer`
2. Terraformの初期化: `terraform init`
3. 設定の確認: `terraform plan`
4. リソースのデプロイ: `terraform apply`
5. デプロイ完了後、出力されたパブリックIPアドレスを使用してStreamlitアプリにアクセス

## リモートアクセス

1. **Session Manager経由のSSH接続**:
   - Session Managerプラグインをインストール
   - SSH設定ファイルを更新
   - `ssh -i "path/to/your/key.pem" ubuntu@i-1234567890abcdef0`で接続

2. **直接SSH接続**（Elastic IP使用時）:
   - `ssh -i "path/to/your/key.pem" ubuntu@<Elastic_IP>`で接続

## 注意点

- コスト管理: 使用しないリソースは`terraform destroy`で削除
- セキュリティ: 本番環境では追加のセキュリティ設定が必要
- カスタマイズ: 必要に応じて`variables.tf`と`terraform.tfvars`を調整

## リポジトリ

https://github.com/Sunwood-ai-labs/aws-terraform-sandbox/tree/main/sandbox/s02_streamlit_aws_deployer

## まとめ

s02_streamlit_aws_deployerは、AWSでのStreamlitアプリケーションの自動デプロイと管理を学ぶための優れたサンドボックス環境です。自動スケジューリング、セキュアなアクセス、柔軟なカスタマイズオプションを提供し、実際のクラウドインフラストラクチャの構築と運用を体験できます。このスクリプトを通じて、Terraformを使用したAWSリソースの効率的な管理方法を学ぶことができます。

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>