0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS東京リージョンのVPC内に閉域網プライベートRAG(Qdrant + Llama-3)をTerraformで構築する完全手順

0
Posted at

AWS東京リージョンのVPC内に閉域網プライベートRAG(Qdrant + Llama-3)をTerraformで構築する完全手順

Feature(179).png

はじめに

こんにちは、NKKTech Global 技術チームです。

社内規定やコンプライアンス上の制約から、「機密文書を一切インターネットに触れさせずにLLMで検索・回答させたい」という相談を数多くいただきます。
これを満たすアーキテクチャが、**「完全閉域網(Isolated VPC)構成のプライベートRAG」**です。

インターネットゲートウェイ(IGW)やNATゲートウェイを配置せず、社内閉域網(Direct Connect / VPN)またはAWS Systems Manager(SSM)経由でのみアクセス可能なVPC内に、以下のコンポーネントを構築します。

  • LLM推論基盤: Llama-3-8B-Instruct on NVIDIA A10G (EC2 g5.2xlarge) + vLLM
  • ベクトルデータベース: Qdrant(オンプレ同等の完全ローカルインスタンス)
  • プライベート接続: VPCエンドポイント(S3 / ECR / SSM)による完全アウトバウンド遮断

本記事では、この強固なインフラを再現可能にするTerraformコード一式と、閉域網特有のプロビジョニングの勘所を公開します。


1. アーキテクチャ設計図


2. Terraformによるインフラ定義

① 閉域VPCとVPCエンドポイント (vpc.tf)

外部インターネットへの出口(IGW/NAT)を一切作成せず、AWS内部サービスへの通信のみをVPCエンドポイントで開通させます。

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

# 1. VPCの作成
resource "aws_vpc" "rag_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "private-rag-vpc"
  }
}

# 2. 完全プライベートサブネット (IGWルートなし)
resource "aws_subnet" "private_subnet" {
  vpc_id            = aws_vpc.rag_vpc.id
  cidr_block        = "10.0.10.0/24"
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "private-rag-subnet"
  }
}

# 3. ルートテーブル
resource "aws_route_table" "private_rt" {
  vpc_id = aws_vpc.rag_vpc.id
  tags   = { Name = "private-rag-rt" }
}

resource "aws_route_table_association" "private_assoc" {
  subnet_id      = aws_subnet.private_subnet.id
  route_table_id = aws_route_table.private_rt.id
}

# 4. S3 ゲートウェイエンドポイント (モデル重み配置用)
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.rag_vpc.id
  service_name      = "com.amazonaws.ap-northeast-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [aws_route_table.private_rt.id]
}

# 5. SSM接続用インターフェースエンドポイント (SSM, EC2Messages, SSMMessages)
locals {
  ssm_services = ["ssm", "ec2messages", "ssmmessages"]
}

resource "aws_vpc_endpoint" "ssm_endpoints" {
  for_each            = toset(locals.ssm_services)
  vpc_id              = aws_vpc.rag_vpc.id
  service_name        = "com.amazonaws.ap-northeast-1.${each.value}"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.private_subnet.id]
  security_group_ids  = [aws_security_group.endpoint_sg.id]
  private_dns_enabled = true
}

② セキュリティグループとIAMロール (security.tf)

パブリックIPを持たないインスタンスに対し、SSM接続のみを許可する最小権限IAMロールと通信制御です。

# VPCエンドポイント用セキュリティグループ
resource "aws_security_group" "endpoint_sg" {
  name        = "vpce-sg"
  vpc_id      = aws_vpc.rag_vpc.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.rag_vpc.cidr_block]
  }

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

# RAGクラスタ内部通信用セキュリティグループ
resource "aws_security_group" "rag_cluster_sg" {
  name        = "rag-cluster-sg"
  vpc_id      = aws_vpc.rag_vpc.id

  # 同一セキュリティグループ内の全通信を許可 (Qdrant 6333, vLLM 8000)
  ingress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"
    self      = true
  }

  # SSMエンドポイント(443)へのアウトバウンドを許可
  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.rag_vpc.cidr_block]
  }

  # S3エンドポイントへのアクセス
  egress {
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    prefix_list_ids = [aws_vpc_endpoint.s3.prefix_list_id]
  }

  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"
    self      = true
  }
}

# SSM接続用IAMロール
resource "aws_iam_role" "instance_role" {
  name = "private-rag-instance-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "ssm_attach" {
  role       = aws_iam_role.instance_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_iam_role_policy_attachment" "s3_read_attach" {
  role       = aws_iam_role.instance_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}

resource "aws_iam_instance_profile" "instance_profile" {
  name = "private-rag-profile"
  role = aws_iam_role.instance_role.name
}

③ Qdrant & GPU推論インスタンスの構築 (compute.tf)

# 1. ベクトルDB: Qdrant インスタンス (Ubuntu / t3.large)
resource "aws_instance" "qdrant_server" {
  ami                  = "ami-0b20f552f63953f0e" # Ubuntu 22.04 LTS (東京)
  instance_type        = "t3.large"
  subnet_id            = aws_subnet.private_subnet.id
  vpc_security_group_ids = [aws_security_group.rag_cluster_sg.id]
  iam_instance_profile = aws_iam_instance_profile.instance_profile.name

  root_block_device {
    volume_size = 100
    volume_type = "gp3"
    encrypted   = true
  }

  tags = { Name = "qdrant-vector-db" }
}

# 2. LLM推論: Llama-3用 GPUインスタンス (g5.2xlarge / A10G 24GB)
resource "aws_instance" "llm_server" {
  ami                  = "ami-0a56114eb37ad4e3e" # Deep Learning OSS AMI with GPU (Ubuntu 22.04)
  instance_type        = "g5.2xlarge"
  subnet_id            = aws_subnet.private_subnet.id
  vpc_security_group_ids = [aws_security_group.rag_cluster_sg.id]
  iam_instance_profile = aws_iam_instance_profile.instance_profile.name

  root_block_device {
    volume_size = 200 # モデル重み + キャッシュ領域
    volume_type = "gp3"
    encrypted   = true
  }

  tags = { Name = "llama3-vllm-inference" }
}

3. 閉域網プロビジョニングの勘所:モデル重みの搬入

インターネットが存在しないVPCでは、huggingface-cli download や docker pull が外部から直接行えません。以下の手順でモデルとコンテナを搬入します。

  1. S3バケットへの事前ステージング:
    管理端末側から、社内許可済みのLlama-3モデル重み(SafeTensors形式)をプライベートS3バケットへアップロードしておきます。
  2. S3 Gateway Endpoint経由の高速転送:
    閉域網内EC2から、通信料無料のS3エンドポイント経由で直接ローカルSSDへ高速同期します。
    aws s3 sync s3://my-private-model-bucket/Meta-Llama-3-8B-Instruct/ /opt/models/llama3/
    
  3. vLLM推論エンジンのオフライン起動:
    ローカルに展開した重みを指定し、OpenAI互換サーバーとして起動します。
    python3 -m vllm.entrypoints.openai.api_server \
        --model /opt/models/llama3/ \
        --host 0.0.0.0 \
        --port 8000 \
        --gpu-memory-utilization 0.90 \
        --max-model-len 8192
    

4. 閉域網内でのRAG実行検証(Python)

同一サブネット内のアプリケーションサーバーから、プライベートIPを用いてQdrantとLlama-3を連携させる検証スクリプトです。

import requests
from qdrant_client import QdrantClient
from openai import OpenAI

QDRANT_PRIVATE_IP = "10.0.10.XX" # Qdrant EC2のプライベートIP
LLM_PRIVATE_IP    = "10.0.10.YY" # GPU EC2のプライベートIP

# 1. Qdrantクライアント接続 (閉域内通信)
qdrant = QdrantClient(host=QDRANT_PRIVATE_IP, port=6333)

# 2. vLLM (OpenAI互換) クライアント接続
client = OpenAI(
    base_url=f"http://{LLM_PRIVATE_IP}:8000/v1",
    api_key="none-needed-in-private-vpc"
)

def run_private_rag(query: str):
    # ① ベクトル検索 (Qdrant)
    # ※ 埋め込み表現は閉域内ローカルモデル(bge-m3等)で生成
    search_results = qdrant.search(
        collection_name="internal_docs",
        query_vector=[...], # 埋め込みベクトル
        limit=3
    )
    
    contexts = "\n".join([hit.payload["text"] for hit in search_results])
    
    # ② Llama-3へのプロンプト投入
    response = client.chat.completions.create(
        model="/opt/models/llama3/",
        messages=[
            {"role": "system", "content": "以下の社内機密資料のみに基づいて回答してください。"},
            {"role": "user", "content": f"資料:\n{contexts}\n\n質問: {query}"}
        ],
        temperature=0.1
    )
    return response.choices[0].message.content

print(run_private_rag("当社の2026年度セキュリティ規程におけるパスワード要件は?"))

5. 運用とコスト最適化のベストプラクティス

  1. EC2 Instance Connect Endpoint (EIC) / SSMの併用:
    パブリック踏み台サーバー(Bastion Host)を完全撤廃し、IAMロールベースで一時的なポートフォワーディングを行うことで、セキュリティ監査(SOC2 / ISO27001)を容易にクリアします。
  2. 夜間・休日のインスタンス自動停止:
    g5.2xlarge は常時稼働で月額約100,000円〜150,000円程度発生します。社内利用時間が平日の日中に限定される場合、AWS EventBridgeとLambdaで夜間に停止・朝に起動するスケジュールを組むことで、インフラコストを約60%削減できます。
  3. EBS最適化と暗号化:
    モデル保存用のEBSボリュームは必ずKMS(カスタマー管理キー: CMK)で暗号化し、物理的なデータ漏洩リスクをゼロにします。

まとめ:真のエンタープライズAIは「閉域網」に宿る

LLMを業務システムへ深く組み込むほど、「データの主権(Data Sovereignty)」と「物理的な通信隔離」の要求は高まります。

AWS東京リージョン内の閉域VPCに、オープンソース最高峰の推論エコシステム(Qdrant + Llama-3 + vLLM)をIaC(Terraform)で展開することで、「オンプレミスの安全性」と「クラウドの俊敏性」を両立した最高強度のAI基盤が完成します。

NKKTech Globalでは、金融・公共・製造業に向けた閉域網AI基盤の設計・構築から、セキュアなMLOpsパイプラインの運用までを一貫してご支援しています。


お問い合わせ先

自社専用プライベートLLM/RAG基盤の構築、Terraformによるインフラ自動化、クラウドセキュリティ設計に関するご相談は、下記よりお気軽にお問い合わせください。

著者:NKKTech Global 技術チーム
私たちは、強固なクラウドセキュリティと最先端のAIエンジニアリングで、エンタープライズのDXをグローバルに支えます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?