- 1 §1 なぜ IoT Vol1 か — IoT アーキテクチャ 4層 + 第19軸目起点 + 全シリーズナビ
- 2 §2 IoT Core 本番運用 — MQTT × Device Shadow × Rules Engine × Thing Registry × Certificate × Job
- 3 §3 Greengrass 本番運用 — Edge runtime × Component × Lambda × ML Inference × Stream Manager ★山場1
- 3.1 3-1. Greengrass v1 と v2 の違い — 本記事は v2 (2020年 GA) を前提とする
- 3.2 3-2. Greengrass Core (GGC) の構成と IoT Core 接続
- 3.3 3-3. Component 設計 — レシピ × アーティファクト × Lifecycle
- 3.4 3-4. Lambda Component — Edge での Lambda Function 実行
- 3.5 3-5. ML Inference — DLR / TFLite / ONNX Component × ローカル推論パイプライン
- 3.6 3-6. Stream Manager — IoT SiteWise / S3 / Kinesis へのストリームルーティング
- 3.7 3-7. Deployment 設定 — フリート展開 × バージョン固定 × ロールバック
- 4 §4 SiteWise 本番運用 — Asset Modeling × Gateway × OPC-UA × Industrial data × Portal
- 4.1 4-1. OPC-UA 最低知識補足 — Tag / Server / Client を理解する
- 4.2 4-2. SiteWise 概要 — 産業 IoT データの構造化
- 4.3 4-3. Asset Modeling — Asset Model / Property 4 種 / Hierarchy
- 4.4 4-4. OPC-UA Gateway 構成 — Greengrass Connector × OPC-UA Connector
- 4.5 4-5. SiteWise Edge — エッジ処理とオフライン耐性
- 4.6 4-6. Portal — SiteWise Monitor × ダッシュボード × アラーム設定
- 4.7 4-7. Terraform 構成例
- 5 §5 Device Defender 本番運用 — Audit × Detect × ML Detect × Mitigation × 異常検知 ★山場2
- 6 §6 詰まりポイント7選 図解 (Mermaid01 判断ツリー)
- 6.1 詰まり1: Device Certificate 期限切れ → Thing 認証失敗
- 6.2 詰まり2: Thing Group 設計ミス → Job ターゲット誤配布
- 6.3 詰まり3: IoT Rules SQL WHERE 句の罠 (NULL 値 / 型変換)
- 6.4 詰まり4: Greengrass Component version 固定忘れ → 本番更新でブレーキ解放
- 6.5 詰まり5: SiteWise Asset hierarchy 設計誤り → Metric 計算の親子依存崩壊
- 6.6 詰まり6: Device Defender ML Detect FP (誤検知) → Sensitivity 設定最適化
- 6.7 詰まり7: IoT Job Rollout 設定ミス → 全デバイス同時更新でサービス停止
- 7 §7 アンチパターン → 正解パターン変換演習 (5問)
- 7.1 Q1: 個別 Certificate 手動管理 → AWS Private CA 連携 + 自動ローテーション
- 7.2 Q2: Pull-based Polling → IoT Rules Engine + Event-driven
- 7.3 Q3: Edge 処理なし → Greengrass ML Inference (レイテンシ削減 + 帯域最適化)
- 7.4 Q4: 手動異常検知 → Device Defender ML Detect (自動化 + スケーラブル)
- 7.5 Q5: フラット構造 Thing 管理 → Thing Group + Billing Group (コスト可視化 + Job 管理)
- 8 §8 まとめ + 第19軸目 IoT 起点 + 45記事化告知 + 全軸クロスリンクナビ
§1 なぜ IoT Vol1 か — IoT アーキテクチャ 4層 + 第19軸目起点 + 全シリーズナビ
製造業の工場センサー、物流の冷凍コンテナ追跡、スマートシティの交通制御——いずれも AWS IoT サービス群を本番運用の基盤として採用する事例が急増している。しかし「IoT は SRE の仕事か?」という問いに対し、コンテナ・サーバーレス畑のプラットフォームエンジニアは曖昧な表情をすることが多い。
本記事は AWS 本番運用シリーズ第19軸目「IoT」の起点記事として、その問いに正面から答える。1万台のデバイスが同時接続する MQTT ブローカーの設計から、エッジでリアルタイム推論を走らせる Greengrass の運用、OPC-UA ゲートウェイ経由で工場ラインデータを収集する SiteWise の構築、そしてデバイスの異常挙動を自動検知する Device Defender の設定まで、AWS IoT の4本柱を一気に習得できる構成とした。
IoT アーキテクチャ 4層モデル
AWS IoT の全体像を把握するには、以下の4層モデルが有効だ。
Layer 1: Edge 層 (デバイス / センサー)
デバイス、センサー、産業機器が存在する物理世界。マイコン (ESP32/Raspberry Pi) からPLC (プログラマブルロジックコントローラー) まで、通信プロトコルは MQTT / HTTPS / WebSocket / OPC-UA / Modbus など多様。Greengrass をエッジ側に配置することで、クラウド接続なしでもローカル推論・データ集約・フィルタリングが可能になる。
Layer 2: Network 層 (MQTT / HTTPS)
デバイスからクラウドへのトランスポート層。AWS IoT Core は TLS 1.2+ 必須の MQTT ブローカーとして機能し、X.509 証明書による相互認証 (mTLS) を強制する。低帯域・高レイテンシ環境向けには MQTT QoS 1 (At-least-once) を選択し、Persistent Session でオフライン期間のメッセージを保持する。
Layer 3: Cloud 層 (IoT Core 処理)
AWS IoT Core が担う処理。受信したメッセージは Rules Engine で SQL ライクなクエリによりルーティング・変換される。Device Shadow はデバイスの「あるべき状態 (Desired)」と「現在の状態 (Reported)」の Delta を管理し、断続的接続のデバイスとのステート同期を保証する。Thing Registry は証明書・ポリシー・グループ・タグを管理するデバイス台帳として機能する。
Layer 4: Application 層 (分析 / 可視化)
IoT データを活用するアプリケーション群。Lambda 関数、DynamoDB、Kinesis Data Streams、S3、SNS、SiteWise などへ Rules Engine 経由でルーティングされ、QuickSight や Grafana で可視化、SageMaker で異常検知モデルを学習するパイプラインへと繋がる。
4本柱の位置付け
本シリーズ Vol1 が扱う4サービスは、IoT アーキテクチャの各層に対応している。
| サービス | 主担当層 | 役割 |
|---|---|---|
| IoT Core | Layer 2-3 | MQTT ブローカー / Device Shadow / Rules Engine / Thing Registry / Certificate 管理 / Job |
| Greengrass | Layer 1-2 | エッジランタイム / Component / Lambda Edge / ML 推論 / Stream Manager |
| SiteWise | Layer 3-4 | 産業 IoT / Asset Modeling / OPC-UA Gateway / Portal / Metric 計算 |
| Device Defender | Layer 3 | デバイスセキュリティ監査 / 異常検知 / ML Detect / Mitigation |
既存18軸との接続
AWS 本番運用シリーズはこれまで Container / Security / Network / IAM / Observability / Serverless / Storage / Database / Edge-CDN / Analytics / Migration / DevOps / AI-ML / Step Functions など18軸を横断してきた。IoT は独立した第19軸ではなく、これら既存軸と密接に連携する。
- Container × IoT: Greengrass は Docker コンテナを Component として実行できる。EKS で構築したマイクロサービスと IoT データパイプラインをシームレスに統合できる (Container Vol1-3 参照)。
- AI-ML × IoT: Greengrass ML Inference で SageMaker トレーニング済みモデルをエッジデプロイ。クラウドに送信せずリアルタイム推論を実現 (AI-ML Vol1-3 参照)。
- Security × IoT: Device Certificate は ACM Private CA と統合して自動ローテーション可能。IoT ポリシーは IAM ポリシーと異なる独自構文を持つ (Security Vol1-3 参照)。
- Observability × IoT: IoT Core のメトリクスは CloudWatch に自動エクスポート。Rules Engine で Kinesis → OpenSearch の分析パイプラインを構築 (Observability Vol1-2 参照)。
- Serverless × IoT: IoT Rules Engine から直接 Lambda を呼び出せる。Step Functions と組み合わせてデバイスの多段ワークフロー制御も可能 (Serverless Vol1-2 参照)。
IoT 本番運用の3つの根本課題
コンテナ・サーバーレス本番運用の延長線上で IoT に踏み出すと、いきなり以下3つの壁にぶつかる。
課題1: スケール特性が違う (1万〜数十万デバイスの同時接続)
ALB の背後に Lambda が並ぶようなウェブアプリと違い、IoT は「常時接続を維持しながら断続的に小さいメッセージを送る」デバイスが大量に並ぶ。MQTT ブローカーは TCP コネクション数で課金されることが多く、HTTP REST API の感覚で設計すると即座にコスト破綻する。本シリーズでは IoT Core の Connection / Message / Rule 課金モデルを §2 で詳述する。
課題2: エッジ処理の必要性 (帯域・レイテンシ・ローカル法規制)
工場の生産ラインや車両のテレマティクスでは「クラウドに全データを送る」設計が成立しない。帯域が足りず、レイテンシが許容できず、地域によってはデータ越境が法規制対象になる。エッジで前処理・推論・フィルタリングを完結させ、必要なデータだけクラウドに送る Greengrass の運用パターンを §3 で解説する。
課題3: セキュリティモデルが独自 (デバイス証明書 / IoT ポリシー / Just-in-Time Provisioning)
IAM ロール・SSO・OIDC で慣れたチームが IoT に踏み込むと、デバイス証明書 (X.509)・IoT 専用ポリシー構文・Just-in-Time Provisioning といった独自の認証認可モデルに戸惑う。一万台のデバイスを個別管理するのは現実的でなく、証明書のローテーションと階層的なポリシー設計が必須だ。§2 後半および §5 Device Defender でセキュリティ運用パターンを示す。
産業 IoT vs コンシューマ IoT — 本記事のスコープ
IoT を「家庭用スマートホーム」と「工場の生産設備」で同じものとして語ると設計を誤る。
| 観点 | コンシューマ IoT (例: スマートホーム) | 産業 IoT (例: 工場 / 物流) |
|---|---|---|
| デバイス数 | 数台〜数百台 | 数千〜数十万台 |
| データ頻度 | 1分〜1時間に1回 | 100ms〜1秒に1回 |
| プロトコル | MQTT / HTTPS | MQTT + OPC-UA / Modbus |
| 可用性要求 | ベストエフォート | 99.9%以上 (生産停止コスト大) |
| セキュリティ | TLS 中心 | TLS + デバイス証明書 + 監査ログ必須 |
| エッジ処理 | 任意 | 必須 (帯域・レイテンシ制約) |
本記事のスコープは産業 IoT 中心だが、コンシューマ IoT (Greengrass on Raspberry Pi 等) でも本質的なパターンは共通する。
読了後に獲得できる能力
本 Vol1 を読み終えた読者は、以下5つを実装できる状態を目指す。
- IoT Core で 1万台規模のデバイス管理: Thing Registry の階層設計 + 証明書 PCA 連携 + Rules Engine ルーティングで本番運用基盤を構築
- Greengrass v2 で エッジ ML 推論: SageMaker で学習したモデルを Component として配布し、現場でリアルタイム推論
- SiteWise で 産業データ統合: OPC-UA Gateway で PLC データを収集し、Asset Hierarchy で Metric を計算
- Device Defender で 異常検知自動化: ML Detect で統計的異常パターンを学習し、Mitigation Action で自動隔離
- Job 機能で OTA アップデート: Continuous Rollout 設定により本番デバイス群へ段階的にファームウェア配布
本記事の読み方ガイド (4本柱の優先順位)
時間が限られている読者は以下の優先順位で読み進めると効率的だ。
- すぐ実装したい人: §2 (IoT Core 必須) → §5 (Device Defender セキュリティ) → §6 (詰まり7選で本番リスク把握)
- エッジ ML が主眼の人: §1 → §3 (Greengrass) → §5 → §6
- 産業 IoT (工場) の人: §1 → §2 → §4 (SiteWise) → §5 → §6 → §7
- シリーズ全体俯瞰したい人: §1 → §8 (全軸ナビ) → 興味のある §2〜§5 → §6 → §7
1. デバイス台帳の階層化: Thing / Thing Type / Thing Group / Billing Group を最初から設計せよ。1万台フラット構造は破綻する
2. 証明書の自動ローテーション: Private CA + Just-in-Time Provisioning + 期限監視で運用コストを削減
3. エッジで完結する処理を最大化: Cloud に送るのは「集計済み」「異常検知済み」「フィルタ済み」のデータだけ
4. デバイスから来るデータを信頼しない: Device Defender Audit + Detect で異常挙動を自動検知
5. デプロイは段階的に: IoT Job の Rollout 設定で本番デバイスに一斉更新を防ぐ
45記事化の起点として
本記事の公開により、当シリーズは44記事から 45記事へと到達する。第19軸目の IoT シリーズは Vol1 (本記事) を起点として、後続 Vol ではより深いトピック (IoT Events / TwinMaker / FleetWise / IoT Analytics) を扱う予定だ。
本記事の位置付け: IoT 本番運用 Vol1 — AWS本番運用シリーズ第19軸目の起点記事 (全45記事化達成)
§2以降のロードマップ:
・§2 IoT Core 本番運用 — MQTT設計・Device Shadow・Rules Engine・Thing Registry・Certificate管理・Job
・§3 Greengrass 本番運用 — エッジランタイム・Component・Lambda Edge・ML Inference・Stream Manager
・§4 SiteWise 本番運用 — Asset Modeling・OPC-UA Gateway・Industrial data・Portal
・§5 Device Defender 本番運用 — Audit・Detect・ML Detect・Mitigation・異常検知
・§6 詰まりポイント7選 (Mermaid 判断ツリー付き)
・§7 アンチパターン→正解パターン変換演習 (5問)
・§8 まとめ + 第19軸全景 + 全軸クロスリンクナビ
対象読者: コンテナ・サーバーレス本番運用経験のある SRE / プラットフォームエンジニアで、製造業・物流・スマートシティ向け IoT システムの設計・運用に踏み出す方
§2 では IoT Core の MQTT ブローカー設計から始め、Device Shadow・Rules Engine・Thing Registry・Certificate 管理・Job の順に本番運用パターンを解説する。
§2 IoT Core 本番運用 — MQTT × Device Shadow × Rules Engine × Thing Registry × Certificate × Job
AWS IoT Core は、数百万台のデバイスが同時接続できるフルマネージド MQTT ブローカーだ。EC2 や ECS で動かす OSS ブローカー (Mosquitto / EMQX) と比べ、スケーリング・証明書管理・ルーティングが AWS サービスとしてネイティブ統合されている点が本質的な違いだ。

MQTT 本番運用設計
QoS 選定
IoT Core が対応する QoS は 0 と 1 の2段階だ (QoS 2 は未対応)。
| QoS | 保証レベル | 使いどころ |
|---|---|---|
| 0 (At-most-once) | 配信保証なし | センサーの高頻度テレメトリ (欠損許容) |
| 1 (At-least-once) | 少なくとも1回配信 | アラート・コマンド・状態変更通知 |
QoS 1 では PUBACK を受け取るまでデバイス側でメッセージを保持し再送する。IoT Core 側は重複排除しないため、冪等処理が前提となる。
MQTT 5 対応
IoT Core は MQTT 5 プロトコルをサポートする。MQTT 5 の主要機能として以下が利用できる。
- User Properties: メッセージヘッダー相当のキーバリューペア (デバイスメタデータを payload 外に持てる)
- Reason Codes: CONNACK / PUBACK 等に詳細エラーコードが付与される
- Session Expiry Interval: Persistent Session の有効期限を秒単位で指定可能
- Shared Subscriptions: 同一 Topic へ複数コンシューマーで負荷分散受信
Topic 設計
MQTT Topic は / で区切る階層構造。ワイルドカード + (1階層) と # (以降全階層) をサブスクライブ側で使用できる。
# 推奨 Topic 階層設計
{env}/{region}/{building}/{device-type}/{device-id}/{data-type}
# 例
prod/ap-northeast-1/plant-A/temperature-sensor/sensor-0042/telemetry
prod/ap-northeast-1/plant-A/temperature-sensor/sensor-0042/alert
prod/ap-northeast-1/plant-A/+/+/telemetry# building内全デバイスのtelemetry
prod/# # prod環境の全メッセージ (管理用途限定)
フラットな Topic (sensor/data) は、デバイス数増加後に Rules Engine での振り分けが困難になる。最低4階層の設計を推奨する。
Persistent Session
MQTT の cleanSession=false (MQTT 3.1.1) または sessionExpiryInterval > 0 (MQTT 5) を設定すると、IoT Core はデバイスのオフライン中に届いた QoS 1 メッセージを最大 1 時間 (デフォルト) 保持する。再接続時にキューが配信される。帯域の限られた現場デバイスにとって重要な機能だ。
Retained Message
Topic に対して最後に送信された Retained Message を新規サブスクライバーへ即座に配信する機能。デバイスの現在ステートを新規接続クライアントへプッシュするユースケースに適している。ただし IoT Core の Retained Message は Thing ごとに 1 件のみ保持され、削除には空ペイロードの Retained publish が必要。
Device Shadow
Device Shadow は、クラウド側にデバイスの「仮想状態」を JSON ドキュメントとして保持する仕組みだ。デバイスがオフラインであっても、アプリケーションは Shadow 経由でデバイスの状態を読み書きできる。
Shadow ドキュメント構造
{
"state": {
"desired": {
"led": "on",
"threshold": 75
},
"reported": {
"led": "on",
"threshold": 70
},
"delta": {
"threshold": 75
}
},
"metadata": { ... },
"version": 42,
"timestamp": 1716285600
}
desired: アプリケーション側が「こうあってほしい」と設定する状態reported: デバイスが「現在こうなっている」と報告する状態delta:desiredとreportedの差分。デバイスは delta を受信して自身を更新する
Classic Shadow vs Named Shadow
| 種別 | 識別子 | 用途 |
|---|---|---|
| Classic Shadow | Thing に1個、デフォルト | シンプルな状態管理 |
| Named Shadow | Thing に複数、名前付き | 機能別 (設定/ステータス/アラート) に分離 |
Named Shadow により、ファームウェア設定・センサーデータ・アラート状態を別ドキュメントで管理でき、ポリシーでのアクセス制御も細粒度化できる。
Shadow MQTT Topic
# Classic Shadow
$aws/things/{thing-name}/shadow/update # アプリ→デバイス (desired更新)
$aws/things/{thing-name}/shadow/update/delta # デバイスが購読 (差分通知)
$aws/things/{thing-name}/shadow/update/accepted # 更新成功通知
$aws/things/{thing-name}/shadow/get # 現在状態取得
# Named Shadow
$aws/things/{thing-name}/shadow/name/{shadow-name}/update
$aws/things/{thing-name}/shadow/name/{shadow-name}/update/delta
Rules Engine
Rules Engine は IoT Core 上のイベント駆動ルーティングエンジンだ。MQTT メッセージに対して SQL ライクなクエリを評価し、条件を満たしたメッセージを AWS サービスへ自動ルーティングする。
SQL 構文
-- 基本構文
SELECT <attributes> FROM '<topic_filter>' WHERE <condition>
-- 全フィールドを Lambda に転送
SELECT * FROM 'prod/+/+/+/+/telemetry'
-- 特定フィールドのみ抽出 + 計算
SELECT temperature, humidity, timestamp() as ts
FROM 'prod/ap-northeast-1/plant-A/#'
WHERE temperature > 80
-- JSON ネスト参照
SELECT payload.device_id, payload.metrics.cpu_usage as cpu
FROM 'device/metrics'
WHERE payload.metrics.cpu_usage > 90
-- 関数利用
SELECT topic(4) as device_id, get_thing_shadow(topic(4), '') as shadow_doc
FROM 'prod/+/+/+/+/telemetry'
Action タイプ (主要)
| Action | 用途 |
|---|---|
| Lambda | カスタム処理 / 変換 / 複合ルーティング |
| DynamoDB | デバイスデータ永続化 |
| DynamoDBv2 | 動的列マッピング (複数列対応) |
| Kinesis Data Streams | 大量データのストリーミング処理 |
| S3 | 生データアーカイブ |
| SNS | アラート通知 |
| IoT SiteWise | 産業データ直接インジェスト |
| OpenSearch | フルテキスト検索・ダッシュボード |
| IoT Events | 状態マシンベースのイベント検知 |
Terraform での Rules Engine 設定
resource "aws_iot_topic_rule" "high_temperature_alert" {
name = "high_temperature_alert"
enabled = true
sql= "SELECT *, topic(4) as device_id FROM 'prod/+/+/+/+/telemetry' WHERE temperature > 80"
sql_version = "2016-03-23"
lambda {
function_arn = aws_lambda_function.alert_handler.arn
}
s3 {
bucket_name = aws_s3_bucket.iot_archive.bucket
key= "alerts/$${timestamp()}/$${topic(4)}.json"
role_arn = aws_iam_role.iot_s3_role.arn
}
error_action {
sns {
message_format = "RAW"
role_arn = aws_iam_role.iot_sns_role.arn
target_arn = aws_sns_topic.iot_errors.arn
}
}
}
Thing Registry
Thing Registry はデバイスのメタデータ台帳だ。Thing / Thing Type / Thing Group / Dynamic Thing Group / Billing Group の5つの概念を組み合わせてデバイス群を管理する。
Thing Type
同種デバイスの属性スキーマを定義する。例えば TemperatureSensor という Thing Type に location, manufacturer, firmware_version の属性を定義しておくと、同型デバイスの属性が統一される。
resource "aws_iot_thing_type" "temperature_sensor" {
name = "TemperatureSensor"
properties {
description = "産業用温度センサー"
searchable_attributes = ["location", "manufacturer", "firmware_version"]
}
}
resource "aws_iot_thing" "sensor_0042" {
name= "sensor-0042"
thing_type_name = aws_iot_thing_type.temperature_sensor.name
attributes = {
location= "plant-A-line-3"
manufacturer = "OmronSensor"
firmware_version = "2.4.1"
}
}
Thing Group と Dynamic Thing Group
Thing Group は静的グループ (手動追加)、Dynamic Thing Group は Thing の属性に基づくクエリで自動的にメンバーが変動するグループだ。
# 静的 Thing Group
resource "aws_iot_thing_group" "plant_a_sensors" {
name = "PlantA-Sensors"
properties {
description = "工場Aの全センサー"
}
}
# Dynamic Thing Group (属性クエリ)
resource "aws_iot_thing_group" "old_firmware_sensors" {
name = "OldFirmware-Sensors"
properties {
description = "ファームウェア更新対象デバイス"
}
# Dynamic Groupは AWS Console / CLI で queryString を指定
# thingName:* AND attributes.firmware_version:1.*
}
Dynamic Thing Group は IoT Job のターゲットとして活用すると強力だ。「firmware 1.x の全デバイス」を動的グループとし、そこへ Job を発行することで更新対象の追加・削除を自動化できる。
Certificate 管理
IoT Core への接続は X.509 証明書による mTLS が必須だ。証明書管理の設計が本番運用の安定性を左右する。
証明書の種類
| 方式 | 特徴 | 向いているシーン |
|---|---|---|
| AWS IoT 発行 CA | IoT Core が CA を管理 | 少数デバイス / 開発環境 |
| カスタム CA 登録 | 自社 CA / ACM Private CA を登録 | 大規模本番 / PKI 統合 |
| Just-in-Time Registration (JITR) | 初回接続時に自動証明書登録 | 大量デバイスの工場出荷時自動登録 |
| Fleet Provisioning | テンプレートベースの自動プロビジョニング | 数千台以上の一括登録 |
Fleet Provisioning フロー
Fleet Provisioning は、デバイス製造時にブートストラップ証明書のみ埋め込み、初回クラウド接続時に本番証明書を動的発行する仕組みだ。
1. 工場出荷 → ブートストラップ証明書 + claim ポリシーを書き込み
2. 現場設置 → IoT Core に接続
3. CreateKeysAndCertificate API → 本番証明書を動的生成
4. RegisterThing API → Thing が作成されポリシーが紐付く
5. ブートストラップ証明書を無効化 → 本番証明書のみ有効
resource "aws_iot_provisioning_template" "device_template" {
name= "FleetProvisioningTemplate"
provisioning_role_arn = aws_iam_role.iot_provisioning_role.arn
enabled= true
template_body = jsonencode({
Parameters = {
SerialNumber = { Type = "String" }
}
Resources = {
certificate = {
Type = "AWS::IoT::Certificate"
Properties = { CertificateId = { Ref = "AWS::IoT::Certificate::Id" } }
}
policy = {
Type = "AWS::IoT::Policy"
Properties = { PolicyName = aws_iot_policy.device_policy.name }
}
thing = {
Type = "AWS::IoT::Thing"
Properties = {
ThingName = { Fn::Join = ["", ["sensor-", { Ref = "SerialNumber" }]] }
ThingTypeName = aws_iot_thing_type.temperature_sensor.name
}
}
}
})
}
AWS IoT が発行する証明書のデフォルト有効期限は 5年だが、カスタム CA や ACM Private CA で発行する場合は自社の PKI ポリシーに依存する。よくある失敗パターン3つ:
(1) 期限監視の欠如: CloudWatch で
aws.iot メトリクスの ConnectError を監視しているだけでは証明書期限切れを事前検知できない。ACM Private CA の期限通知 (EventBridge + SNS) と組み合わせよ。(2) PCA 自動ローテーション未設定: ACM Private CA の証明書自動更新は設定必須。手動ローテーションは大量 Thing 環境では運用不可能。Fleet Provisioning テンプレートと組み合わせたローテーションフローを事前設計せよ。
(3) 再発行コストの過小評価: 1万台のデバイスが同時に証明書期限切れで接続不能になると、Fleet Provisioning の再実行フローが必要になる。事前に証明書有効期限の分散 (デバイス毎にオフセット) を設計せよ。
IoT Job
IoT Job はデバイスへのリモート操作 (ファームウェア更新 / 設定配布 / コマンド実行) を管理する仕組みだ。
Job タイプ
| タイプ | 特徴 |
|---|---|
| Snapshot Job | 対象デバイスリストが固定 (Job作成時に確定) |
| Continuous Job | Dynamic Thing Group をターゲットにすると、グループへの追加デバイスにも自動適用 |
Job Rollout 設定
大規模デプロイでは段階的ロールアウトが必須だ。
resource "aws_iot_thing_group_membership" "firmware_update_job" {
# IoT Job はaws_iot_* リソースで定義。Job Document は S3 に配置
}
# Job の主要パラメータ (AWS CLI / SDK で設定)
# jobExecutionsRolloutConfig:
#maximumPerMinute: 10 # 毎分最大10台に配布
#exponentialRate:
# baseRatePerMinute: 5
# incrementFactor: 2
# rateIncreaseCriteria:
# numberOfSucceededThings: 50 # 50台成功後に加速
#
# abortConfig:
#criteriaList:
# - action: CANCEL
# failureType: FAILED
# minNumberOfExecutedThings: 10
# thresholdPercentage: 20.0# 20%失敗で全停止
#
# timeoutConfig:
#inProgressTimeoutInMinutes: 30
Job Document
Job Document は S3 に配置した JSON ファイルで、デバイスが実行すべき操作を記述する。
{
"operation": "firmware-update",
"firmware": {
"version": "2.5.0",
"url": "https://firmware-bucket.s3.amazonaws.com/sensor-fw-2.5.0.bin",
"checksum": "sha256:abc123...",
"size_bytes": 1048576
},
"steps": [
"download",
"verify-checksum",
"apply",
"reboot"
],
"rollback_on_failure": true
}
デバイス側の AWS IoT Device SDK は Job の通知を受け取り、Document を取得・実行し、JobExecution の Status (IN_PROGRESS / SUCCEEDED / FAILED) を報告する。
Thing Registry: Thing Type でスキーマ統一 / Thing Group 階層を事前設計 (最大5階層) / Dynamic Thing Group で Job ターゲット自動化
Certificate 管理: ACM Private CA 統合 + 自動ローテーション設定 / 証明書有効期限の分散 / Fleet Provisioning テンプレート整備
IoT ポリシー最小権限:
iot:Publish は自 Thing の Topic のみ / iot:Subscribe は必要 Topic のみ / iot:Connect は ClientID = ThingName を強制 (iot:Connection.Thing.IsAttached 条件キー活用)Rules Engine: error_action を必ず設定 (ルール評価失敗の DLQ) / SQL バージョン
2016-03-23 を明示指定Job Rollout: maximumPerMinute + abortConfig を必ず設定 / Continuous Job で動的グループを活用 / timeoutConfig でゾンビ Job を防止
MQTT 設計: Topic 階層は最低4階層 / QoS 1 を基本 (センサー高頻度テレメトリのみ QoS 0) / Persistent Session でオフライン耐性を確保
§3 では Greengrass を使ったエッジランタイムの設計・運用を解説する。クラウド接続が不安定な現場でも推論・集約・フィルタリングをエッジで完結させる構成を実装形式で見ていく。
§3 Greengrass 本番運用 — Edge runtime × Component × Lambda × ML Inference × Stream Manager ★山場1
3-1. Greengrass v1 と v2 の違い — 本記事は v2 (2020年 GA) を前提とする
AWS IoT Greengrass は 2020年に v2 (GA) が公開され、アーキテクチャが根本から刷新された。
| 項目 | v1 | v2 (本記事対象) |
|---|---|---|
| ランタイム | Java ベース Greengrass Core | Nucleus (OSS 公開 / Python 拡張可) |
| コンポーネント管理 | Lambda Group + Subscription | Component 単位 (独立ライフサイクル) |
| デプロイ単位 | Group Deployment | Deployment (コンポーネント集合) |
| OSS 状況 | クローズド | Nucleus は GitHub 公開 (aws-greengrass-nucleus) |
| マルチランタイム | Lambda のみ | Lambda / Container / Generic / Plugin / Nucleus 5種 |
| プロビジョニング | 手動 / CloudFormation 限定 | Fleet Provisioning / Manual / Automatic |
v1 は 2023年6月に新機能停止 (メンテナンスモード)。本番環境では v2 への移行を優先する。
3-2. Greengrass Core (GGC) の構成と IoT Core 接続
GGC のインストールは JAR ファイル 1 本で完結する。
# GGC インストール (Linux)
curl -s https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-nucleus-latest.zip \
-o greengrass-nucleus.zip
unzip greengrass-nucleus.zip -d GreengrassInstaller
sudo java -Droot="/greengrass/v2" -Dlog.store=FILE \
-jar ./GreengrassInstaller/lib/Greengrass.jar \
--aws-region ap-northeast-1 \
--thing-name MyGreengrassThing \
--thing-group-name MyGreengrassGroup \
--tes-role-alias GreengrassV2TokenExchangeRoleAlias \
--component-default-user ggc_user:ggc_group \
--provision true \
--setup-system-service true
IoT Core との接続フロー:
- GGC 起動時に IoT Core エンドポイントへ MQTT 接続
$aws/things/{thingName}/shadow/トピックで Device Shadow を同期$aws/greengrass/v2/deployment/経由で Deployment ドキュメントを受信- コンポーネントのダウンロード・インストール・起動を自動実行
Terraform: Thing + Certificate + Policy の完全例:
resource "aws_iot_thing" "greengrass_core" {
name = "MyGreengrassThing"
}
resource "aws_iot_certificate" "greengrass_cert" {
active = true
}
resource "aws_iot_policy" "greengrass_policy" {
name = "GreengrassCorePolicy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = [
"iot:Connect", "iot:Publish",
"iot:Subscribe", "iot:Receive",
"greengrass:*"
]
Resource = "*"
}]
})
}
resource "aws_iot_thing_principal_attachment" "core_attach" {
thing = aws_iot_thing.greengrass_core.name
principal = aws_iot_certificate.greengrass_cert.arn
}
resource "aws_iot_policy_attachment" "policy_attach" {
policy = aws_iot_policy.greengrass_policy.name
target = aws_iot_certificate.greengrass_cert.arn
}
3-3. Component 設計 — レシピ × アーティファクト × Lifecycle
Greengrass v2 の最小単位は Component (コンポーネント)。各コンポーネントは独立したライフサイクルを持ち、依存関係を宣言して複数コンポーネントを組み合わせてシステムを構成する。
Component の種類:
| 種類 | 説明 | 用途 |
|---|---|---|
| Generic | 任意の実行ファイル | シェルスクリプト / バイナリ |
| Lambda | Lambda Function コンポーネント | 既存 Lambda の Edge 移植 |
| Container | Docker コンテナ | マイクロサービス化 |
| Plugin | Greengrass Nucleus 拡張 | Stream Manager / Token Exchange |
| Nucleus | Greengrass Core 本体 | 自動インストール |
recipe.yaml の完全構造:
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.SensorProcessor
ComponentVersion: '1.0.0'
ComponentDescription: センサーデータ処理コンポーネント
ComponentPublisher: MyCompany
ComponentDependencies:
aws.greengrass.StreamManager:
VersionRequirement: '>=2.0.0'
DependencyType: HARD
ComponentConfiguration:
DefaultConfiguration:
SensorTopicPrefix: '/sensors/'
BatchSize: '50'
StreamName: 'SensorDataStream'
Manifests:
- Platform:
os: linux
Artifacts:
- URI: 's3://my-greengrass-artifacts/SensorProcessor-1.0.0.zip'
Unarchive: ZIP
Lifecycle:
Install:
Script: |
pip3 install -r {artifacts:decompressedPath}/SensorProcessor/requirements.txt
Run:
Script: |
python3 {artifacts:decompressedPath}/SensorProcessor/main.py \
--topic-prefix "{configuration:/SensorTopicPrefix}" \
--batch-size "{configuration:/BatchSize}"
Shutdown:
Script: |
python3 {artifacts:decompressedPath}/SensorProcessor/shutdown.py
Lifecycle の 3ステージ:
- Install: パッケージインストール / 設定ファイル展開。再デプロイ時も実行。冪等性を確保する
- Run: メインプロセス起動。プロセス終了で Shutdown へ移行。常駐型は無限ループまたはデーモン起動
- Shutdown: グレースフルシャットダウン。最大 15秒のデフォルトタイムアウト。データのフラッシュ処理をここに記述
3-4. Lambda Component — Edge での Lambda Function 実行
Greengrass v2 は既存の Lambda Function をそのまま Edge へデプロイできる LambdaFunction コンポーネント を提供する。クラウドの Lambda と同じコードをローカルで実行でき、段階的な Edge 移行が可能。
Terraform: Lambda Component 登録例:
resource "aws_greengrassv2_component_version" "lambda_processor" {
inline_recipe = jsonencode({
RecipeFormatVersion = "2020-01-25"
ComponentName = "com.example.LambdaProcessor"
ComponentVersion = "1.0.0"
ComponentType = "aws.greengrass.lambda"
ComponentDependencies = {
"aws.greengrass.LambdaLauncher" = {
VersionRequirement = ">=2.0.0"
DependencyType = "HARD"
}
}
Manifests = [{
Platform = { os = "linux" }
Lifecycle = { Run = { Isolate = true } }
}]
})
}
Lambda Component の制約:
– Edge 環境でサポートするランタイム: Python 3.8 / Java 11 / Node.js 12
– タイムアウトは最大 900秒 (クラウド Lambda と同じ)
– IoT Core トピックへの Publish は AWSIoTDataPlane IPC 経由で実行
3-5. ML Inference — DLR / TFLite / ONNX Component × ローカル推論パイプライン
Greengrass v2 は ML コンポーネント として、エッジデバイスでの機械学習推論を標準でサポートする。
| ランタイム | コンポーネント名 | 用途 |
|---|---|---|
| DLR (Deep Learning Runtime) | aws.greengrass.DLRObjectDetection | SageMaker Neo コンパイル済みモデル |
| TensorFlow Lite | aws.greengrass.TensorFlowLiteObjectDetection | モバイル向け軽量モデル |
| ONNX Runtime | カスタム Generic Component | 汎用モデル形式 |
ML 推論パイプライン構成:
[センサー/カメラ]
→ [前処理 Component]
→ [MLInference Component] ← ModelStore (S3 → デバイス / OTA 更新)
→ [Stream Manager]
→ [IoT Core / S3 / Kinesis]
モデルアーティファクトの recipe.yaml 統合例:
Manifests:
- Artifacts:
- URI: 's3://my-ml-models/object_detection_model_v2.tar.gz'
Unarchive: TAR
Permission:
Read: ALL
Lifecycle:
Run:
Script: |
python3 inference.py \
--model-dir {artifacts:decompressedPath}/model \
--confidence-threshold 0.7
推論レイテンシの設計指針:
– CPU のみ (Raspberry Pi 4 等): MobileNet SSD (DLR 最適化済み) で ~100ms / フレーム
– GPU 搭載 (Jetson Nano 等): ResNet-50 で ~30ms / フレーム
– モデル更新: OTA Deployment によるローリング更新。コンポーネントバージョン固定で安定性を確保

3-6. Stream Manager — IoT SiteWise / S3 / Kinesis へのストリームルーティング
Stream Manager は Greengrass v2 の標準 Plugin コンポーネントで、エッジで生成されたデータを Cloud へ安定転送する。ネットワーク断絶時はローカルバッファに蓄積し、復旧後に自動再送する。
Stream Manager がサポートする転送先:
| エクスポート先 | ユースケース |
|---|---|
| IoT SiteWise | 産業設備データの Asset Property 紐付け |
| Amazon S3 | 生データ永続化 / データレイク構築 |
| Amazon Kinesis Data Streams | リアルタイムストリーム処理 |
| IoT Analytics | IoT 専用パイプライン (分析 / クリーニング) |
Python SDK でのストリーム書き込み:
from stream_manager import (
StreamManagerClient,
ExportDefinition,
KinesisConfig,
MessageStreamDefinition,
StrategyOnFull,
)
client = StreamManagerClient()
client.create_message_stream(
MessageStreamDefinition(
name="SensorDataStream",
strategy_on_full=StrategyOnFull.OverwriteOldestData,
export_definition=ExportDefinition(
kinesis=[KinesisConfig(
identifier="KinesisExport",
kinesis_stream_name="iot-sensor-stream",
batch_size=500,
)]
),
)
)
# センサーデータをストリームへ書き込み
client.append_message("SensorDataStream", sensor_data.encode())
Stream Manager 設計のポイント:
– strategy_on_full: OverwriteOldestData は最新データ優先。古いデータを捨てても最新を送りたい場合に使用
– strategy_on_full: RejectNewData はデータの完全性が必要な場合 (ファイナンシャルデータ等)
– batch_size は転送先の制限 (Kinesis: 最大 500 レコード) に合わせて設定
3-7. Deployment 設定 — フリート展開 × バージョン固定 × ロールバック
Greengrass v2 の Deployment は Thing Group 単位でフリート展開を行う。コンポーネントのバージョンを明示的に固定することで、意図しない自動更新を防ぐ。
Terraform: Deployment 完全例:
resource "aws_greengrassv2_deployment" "fleet_deployment" {
name = "SensorFleetDeployment-v1.0"
target_arn = aws_iot_thing_group.sensor_group.arn
components = {
"aws.greengrass.Nucleus" = {
component_version = "2.12.0" # バージョン固定 — LATEST 禁止
}
"aws.greengrass.StreamManager" = {
component_version = "2.1.0"
}
"com.example.SensorProcessor" = {
component_version = "1.0.0"
configuration_update = {
merge = jsonencode({
SensorTopicPrefix = "/sensors/line-a/"
BatchSize= "100"
})
}
}
}
deployment_policies = {
failure_handling_policy = "ROLLBACK"
component_update_policy = {
timeout_in_seconds = 60
action = "NOTIFY_COMPONENTS"
}
}
}
段階ロールアウト設計:
– カナリア (全台の 5%) → ステージング (20%) → 本番全台 (100%) の 3段階
– 各段階でコンポーネント稼働状態・ログ・デバイスメトリクスを確認してから次段階へ進む
– failure_handling_policy: ROLLBACK で失敗時に前バージョンへ自動復帰
鉄則1: Component バージョンは必ず固定するLATEST 指定は本番禁止。新バージョン公開時の意図しない自動更新がデバイス群に伝播する。必ずセマンティックバージョン (例: 2.12.0) を Terraform で管理し、テスト環境で検証後に本番へ昇格させる。
鉄則2: Stream Manager でエッジの耐障害性を確保する
ネットワーク断絶が頻繁に発生するエッジ環境では、データを直接 Publish するのではなく Stream Manager 経由でバッファリングする。最大保存容量・エクスポート先・StrategyOnFull を必ず設定し、断絶時のデータ消失を防ぐ。
鉄則3: OTA 更新は段階ロールアウトで実施する
全デバイスへの一括デプロイは禁止。Thing Group を「カナリア (5%)」「ステージング (20%)」「本番全台 (100%)」に分割し、各段階でデバイスの健全性を確認してから次段階へ進む。
Greengrass を推奨する場面
- エッジでの ML 推論が必要 (カメラ映像解析 / 振動センサー異常検知)
- ネットワーク帯域が限られており、生データを全量クラウド送信できない
- ネットワーク断絶時もローカル処理を継続させる必要がある
- 既存の Lambda 関数をそのままエッジ環境へ移植したい
- 10台以上のデバイスをフリートとして統一管理・更新したい
Greengrass が不要 / 非推奨な場面
- センサーが単純な MQTT Publish のみ (IoT Core 直接接続で十分)
- デバイスが常時ネットワーク接続でき、帯域制約がない
- 処理がステートレスで Edge 側でのバッファリングが不要
- リソース制約が極めて厳しい MCU 系デバイス (FreeRTOS 向け)
モデル選定: エッジの CPU / メモリに合わせてモデルを選ぶ。GPU 搭載 (Jetson Nano) なら ResNet-50 / YOLOv5。CPU のみ (Raspberry Pi 4) なら MobileNet SSD / TFLite 最適化モデル。
推論レイテンシ目標: リアルタイム判定 (製造ライン異常検知) は 100ms 以下、バッチ推論は 500ms 以下を目安に設計する。
モデル更新 OTA: S3 にモデルアーティファクトを配置し、Greengrass Deployment でコンポーネントバージョンを更新することで OTA 配信する。旧モデルは S3 バージョニングで保持し、ロールバックに備える。
DLR (Deep Learning Runtime): SageMaker Neo でコンパイルすると CPU のみ環境でも最大 4x の性能向上を期待できる。
§3 では Greengrass v2 の Core セットアップから Component 設計、Lambda Component、ML Inference パイプライン、Stream Manager、フリートデプロイまでを解説した。次の §4 では、産業設備データの取り込みと可視化を担う IoT SiteWise の Asset Modeling と OPC-UA Gateway 構成を詳述する。
§4 SiteWise 本番運用 — Asset Modeling × Gateway × OPC-UA × Industrial data × Portal
AWS IoT SiteWise は製造ラインや設備の産業データを収集・構造化し、稼働状況をリアルタイム可視化するマネージドサービスだ。IT 側で API 設計や CloudWatch メトリクスに慣れた SRE が初めて OT (Operational Technology) 領域に踏み込むとき、最初の壁となるのが OPC-UA の概念体系である。
4-1. OPC-UA 最低知識補足 — Tag / Server / Client を理解する
OPC-UA とは — OPC Unified Architecture (IEC 62541) は製造現場の異機種設備が共通言語でデータを交換するための国際標準プロトコルだ。Ethernet 以前から存在した独自プロトコル (PROFIBUS / Modbus) に代わり、TCP/IP 上でセキュアな通信を実現する。SiteWise Gateway は OPC-UA Client として実装されており、現場に OPC-UA Server が稼働していれば特別なドライバーなしにデータを取得できる。
Tag とは — 設備上の計測ポイントに付けられた論理名で「ライン1_温度センサー_現在値」「ポンプA_吐出圧力」のように一意に識別する。OPC-UA 仕様では Node と呼ぶが、SiteWise の設定画面では Source の Tag として扱う。Tag パスは Namespace Index と Node ID を組み合わせた文字列 (ns=2;s=FactoryLine1.Temp) で表現する。現場エンジニアから Tag リストを受領することがゼロデイ作業の第一歩になる。
Server / Client 分離 — OPC-UA Server は設備側 (PLC/SCADA) で動作し Tag の現在値・履歴・イベントを公開する。OPC-UA Client はデータを読み取る側で、SiteWise Gateway に内蔵された OPC-UA Connector がクライアントとして動作する。Server と Client の間には「ポーリング間隔 (スキャンレート)」と「変化量閾値 (deadband)」の 2 パラメーターで転送量を制御する。この Server → Client → Gateway → SiteWise Cloud の流れを把握すると以後の設定が腑に落ちやすい。
4-2. SiteWise 概要 — 産業 IoT データの構造化
IoT Core + Lambda だけでは設備データの「意味」はアプリ層で暗黙に持つしかない。SiteWise は Asset Model というスキーマ定義によって設備の階層構造・計測値・計算式・アラームを Cloud 上でモデル化し、「どの設備の何の値か」を明示的に管理できる。
主な用途は 3 つだ。
| 用途 | 概要 | SiteWise 機能 |
|---|---|---|
| 稼働監視 | 生産ラインの OEE・歩留まりをリアルタイム可視化 | Metric + SiteWise Monitor |
| 設備予知保全 | 振動・温度トレンドの閾値超過アラーム | Metric + Alarm + IoT Events |
| データ統合 | IoT Core / Greengrass → SiteWise → Analytics / S3 | IoT Core Rule → SiteWise |
4-3. Asset Modeling — Asset Model / Property 4 種 / Hierarchy
Asset Model は「設備の型定義」で、Property と Hierarchy を持つ。
Property 4 種類
| Property | 説明 | 典型例 |
|---|---|---|
| Measurement | センサーから受信する生データ (時系列) | 温度: 73.2°C |
| Attribute | 変更頻度の低い静的情報 | 設備シリアル番号 |
| Transform | 他 Property を式で変換した計算値 | temp_c * 9 / 5 + 32 で °F 変換 |
| Metric | 時間窓で集計する計算値 | avg(temp_c) を 1h tumbling window で平均 |
Measurement は OPC-UA / MQTT から実測値を受け取る。Transform は Python ライクな式をコンソール上で設定できる。Metric は tumbling window (固定時間窓) で集計し、OEE ダッシュボードや予知保全アラームに使う。Metric の計算はクラウド側で実行されるが、SiteWise Edge を有効にした場合はエッジでも同一ロジックが動作する。
Hierarchy — Asset の親子関係
Asset Model には子 Asset Model を参照する Hierarchy を定義できる。Factory Model → Line Model → Machine Model の 3 層構造を表現できる。
Factory (Asset)
└── ProductionLine_A (Asset)
├── CNC_Machine_01 (Asset)
└── CNC_Machine_02 (Asset)
Hierarchy を定義すると、親 Asset の Metric から nested_expression で子 Asset の Measurement を参照できる。後から階層設計を変更すると Metric 依存関係が崩壊してリソース再作成が必要になるため、設計フェーズで確定させるのが原則だ。
Asset インスタンス化とデータバインド
Asset は Asset Model のインスタンスだ。ProductionLine_A という Asset を作成し、OPC-UA Gateway からのデータストリームを LineTemperature Property にバインドする。バインドは Gateway のデータストリーム alias と Asset Property の論理 ID を関連付けることで設定する。
# 子 Asset を親 Asset に関連付ける
aws iotsitewise associate-assets \
--asset-id "${PARENT_ASSET_ID}" \
--hierarchy-id "${HIERARCHY_ID}" \
--child-asset-id "${CHILD_ASSET_ID}"
# Portal の Project に Asset を登録する
aws iotsitewise batch-associate-project-assets \
--project-id "${PROJECT_ID}" \
--asset-ids "${ASSET_ID}"
4-4. OPC-UA Gateway 構成 — Greengrass Connector × OPC-UA Connector
SiteWise Gateway は Greengrass v2 の Component として動作し、工場内ネットワークに設置した Greengrass デバイス上で OPC-UA Client として機能する。
Factory Network (L2/L3) AWS Cloud
┌──────────────────────────┐ ┌────────────────────────────────────┐
│ PLC / SCADA │ │ IoT SiteWise Service │
│ (OPC-UA Server │ ││
│Port 4840) │ │ Asset Model / Asset│
└──────────┬───────────────┘ │ Metric 計算 (1h avg 等) │
│ OPC-UA (TCP)│ SiteWise Monitor Portal│
▼ └────────────────────────────────────┘
┌──────────────────────────────────┐▲
│ Greengrass Device││ HTTPS (Port 443)
│ ├── IoT SiteWise Gateway │────────────────────────┘
│ │Component (OPC-UA Connector)│ Data Stream
│ └── IoT Core Connection│ (alias → Property バインド)
└──────────────────────────────────┘
Gateway 構成の 3 ステップ:
Step 1 — Greengrass デバイスを Gateway として登録
SiteWise コンソール → Gateways → Create gateway → Greengrass Core デバイス ID を設定する。IoT SiteWise Gateway Component が Greengrass Deployment に自動追加される。Greengrass デバイスには iotsitewise:BatchPutAssetPropertyValue 等の権限を持つ IAM ロールが必要だ。
Step 2 — OPC-UA Source を追加
Gateway コンソールで OPC-UA Source を追加し、OPC-UA Server のエンドポイント (opc.tcp://192.168.10.5:4840) と認証情報を設定する。本番では匿名認証を避け、Basic256Sha256 セキュリティポリシーと X.509 証明書認証を選択する。
Step 3 — データストリームと Tag マッピングを設定
OPC-UA Node のパスを SiteWise Property に紐付ける。マッピング JSON を用意して CLI / SDK で一括インポートが可能だ。
{
"sources": [
{
"name": "FactoryLine1-PLC",
"endpoint": {
"endpointUri": "opc.tcp://192.168.10.5:4840",
"securityPolicy": "Basic256Sha256",
"messageSecurityMode": "SIGN_AND_ENCRYPT"
},
"measurementDataStreamPrefix": "/Factory1",
"propertyGroups": [
{
"name": "TemperatureGroup",
"nodeFilterRules": [
{
"action": "INCLUDE",
"definition": {
"type": "OpcUaRootPath",
"rootPath": "/FactoryLine1/Temperature"
}
}
],
"deadband": {
"type": "PERCENT",
"value": 0.5
},
"scanMode": {
"mode": "POLL",
"rate": 1000
}
}
]
}
]
}
deadband を 0.5% に設定することで微小変化による不要なデータ転送を抑制できる。scanMode.rate は PLC へのポーリング間隔 (ミリ秒) で、高頻度すぎると PLC 側に負荷をかけるため現場エンジニアと協議して決める。
4-5. SiteWise Edge — エッジ処理とオフライン耐性
SiteWise Edge を有効化すると Greengrass デバイス上でローカル処理が可能になる。工場のネットワーク断線時でも Measurement の蓄積と Metric 計算をエッジで継続し、接続回復後にクラウドへ差分同期する。
SiteWise Edge (Greengrass 上)
├── Local Asset Model : クラウドから同期済みのモデル定義
├── Local Measurement ingestion : OPC-UA → Edge buffer (SQLite)
├── Local Metric 計算 : 1h 平均等を Edge でリアルタイム計算
└── Cloud Sync: 接続回復時に未送信データを自動アップロード
Edge 処理が有効なとき、SiteWise Monitor のダッシュボードはクラウドデータと Edge データの双方を表示できる。断線時もローカル監視を継続したい現場環境では Edge 有効化は必須の設定だ。
4-6. Portal — SiteWise Monitor × ダッシュボード × アラーム設定
SiteWise Monitor は非エンジニア向け Web UI で、ライン管理者や品質担当者が追加開発なしに設備データを可視化できる。
Portal 設定の流れ
| ステップ | 操作 | ポイント |
|---|---|---|
| 1 | Create Portal → IAM Identity Center 設定 | SSO 連携必須 (IAM ユーザーで代替可) |
| 2 | Portal 内に Project を作成、Asset を関連付け | Project が表示範囲の境界単位 |
| 3 | Dashboard に Widget (折れ線/棒/KPI) を追加し Metric を設定 | ドラッグ&ドロップで設定 |
| 4 | Alarm を定義し閾値超過通知を設定 | IoT Events Detector Model と連携 |
Alarm の仕組み
SiteWise Alarm は IoT Events に連携して状態管理を行う。アラーム発報後は SNS 経由でオペレーターへメール/SMS 通知が可能だ。
Measurement (温度センサー値)
└── Alarm Definition
├── NORMAL: temp < 80°C
├── LATCHED : temp >= 80°C (ラッチ後は手動リセット必要)
└── ACTIVE: temp >= 100°C → IoT Events → SNS → オペレーター通知
SiteWise Monitor 上でアラーム状態を一覧表示し、確認・リセット操作も行える。
4-7. Terraform 構成例
# Asset Model: 製造ラインの型定義
resource "aws_iotsitewise_asset_model" "production_line" {
name = "ProductionLineModel"
asset_model_properties {
name= "LineTemperature"
data_type = "DOUBLE"
unit= "Celsius"
type {
measurement {}
}
}
asset_model_properties {
name= "TempFahrenheit"
data_type = "DOUBLE"
unit= "Fahrenheit"
type {
transform {
expression = "temp_c * 9 / 5 + 32"
variables {
name = "temp_c"
value {
property_logical_id = "LineTemperature"
}
}
}
}
}
asset_model_properties {
name= "AvgTemperature1h"
data_type = "DOUBLE"
unit= "Celsius"
type {
metric {
expression = "avg(temp)"
variables {
name = "temp"
value {
property_logical_id = "LineTemperature"
}
}
window {
tumbling {
interval = "1h"
}
}
}
}
}
asset_model_hierarchies {
name = "MachineHierarchy"
child_asset_model_id = aws_iotsitewise_asset_model.machine.id
}
}
# Asset: 製造ラインのインスタンス
resource "aws_iotsitewise_asset" "line_a" {
asset_model_id = aws_iotsitewise_asset_model.production_line.id
asset_name = "ProductionLine_A"
}
# Gateway: Greengrass デバイスと紐付け
resource "aws_iotsitewise_gateway" "factory_gw" {
gateway_name = "factory-gw-01"
gateway_platform {
greengrass_v2 {
core_device_thing_name = aws_iot_thing.greengrass_core.name
}
}
}
# Portal: SiteWise Monitor ポータル
resource "aws_iotsitewise_portal" "factory_portal" {
portal_name = "FactoryMonitorPortal"
portal_contact_email = "ops-team@example.com"
role_arn = aws_iam_role.sitewise_portal_role.arn
}

Asset 階層設計を先に固める: Factory → Line → Machine の 3 層構造は設計フェーズで確定させる。後から変更すると Metric 依存関係が崩壊し、Asset と関連リソースの再作成が必要になる。
Metric 計算窓を業務要件に合わせる: tumbling window の interval は 1m / 5m / 15m / 1h から選択する。短すぎると Metric Property の蓄積コスト (per data point 課金) が急増するため、監視精度と費用のバランスを事前に見積もる。
Gateway 冗長化: 工場内ネットワーク障害を想定し Greengrass デバイスを 2 台構成 (Active-Standby) にする。SiteWise Edge の Local buffering を有効化して断線耐性を確保し、重要データの欠損を防ぐ。
deadband を適切に設定する: OPC-UA Source の deadband を 0.5〜2% に設定してノイズ性の微小変化による不要なデータ転送を抑制する。センサー精度と必要なデータ鮮度を現場エンジニアと合意してから値を決定する。
Portal 権限を 3 層分離する: Portal Administrator (SiteWise コンソール操作可) / Project Editor (ダッシュボード編集) / Project Viewer (閲覧専用) を IAM Identity Center グループで分離し、製造現場の情報セキュリティポリシーに準拠する。
§4 では産業 IoT の核心となる Asset Modeling と OPC-UA Gateway 構成、SiteWise Monitor による可視化を解説した。次の §5 では IoT デバイスセキュリティの要である Device Defender を取り上げる。Audit による設定不備の検出から ML Detect による行動異常の自動検知、Mitigation による自動対処まで、4 機能の連携がゼロトラスト IoT 環境の基盤を形成する。
§5 Device Defender 本番運用 — Audit × Detect × ML Detect × Mitigation × 異常検知 ★山場2
AWS IoT Device Defender はデバイスのセキュリティ体制を継続監視・検知・自動対処するマネージドサービスだ。接続する IoT デバイスが数千〜数十万台規模になると、個々のデバイスの不審な動作や設定ミスを人手で追うのは不可能になる。Device Defender の 4 機能 (Audit / Detect / ML Detect / Mitigation) が組み合わさることで、セキュリティ運用を自動化できる。
5-1. Device Defender 4 機能の全体像
| 機能 | 目的 | 検出対象 | アクション |
|---|---|---|---|
| Audit | IoT 設定の不備を定期検査 | Certificate 期限切れ / Policy 過剰権限 | Audit レポート + Mitigation |
| Detect | デバイス行動の異常をルールで検知 | 接続頻度異常 / メッセージ量急増 / 未知 IP | CloudWatch Alarm + Mitigation |
| ML Detect | 機械学習でベースライン逸脱を検知 | 行動パターンの統計的異常 | CloudWatch Alarm + Mitigation |
| Mitigation | 異常検知後の自動対処 | Quarantine / 証明書無効化 / Job 発行 | — (アクション本体) |
5-2. Audit — 設定不備の定期検査
Audit は IoT リソースの設定状態を定期的にスキャンし、セキュリティ上の問題点を検出する。検査項目は AWS 管理型とカスタムの 2 種類だ。
AWS 管理型チェック (主要 8 項目)
| チェック項目 | 検出内容 |
|---|---|
| CA_CERTIFICATE_EXPIRING_CHECK | CA 証明書の有効期限切れ間近を警告 |
| DEVICE_CERTIFICATE_EXPIRING_CHECK | デバイス証明書の期限切れを検出 |
| DEVICE_CERTIFICATE_SHARED_CHECK | 複数デバイスで同一証明書を共有する不適切な運用を検出 |
| IOT_POLICY_OVERLY_PERMISSIVE_CHECK | iot:* など過剰なポリシー権限を検出 |
| IOT_ROLE_ALIAS_OVERLY_PERMISSIVE_CHECK | Role Alias の過剰権限を検出 |
| LOGGING_DISABLED_CHECK | IoT Core のログが無効な状態を検出 |
| CONFLICTING_CLIENT_IDS_CHECK | 同一 Client ID が複数箇所から接続し競合していることを検出 |
| UNAUTHENTICATED_COGNITO_ROLE_OVERLY_PERMISSIVE_CHECK | 未認証 Cognito ロールの過剰権限を検出 |
本番環境では DEVICE_CERTIFICATE_EXPIRING_CHECK と IOT_POLICY_OVERLY_PERMISSIVE_CHECK は必ず有効化する。証明書の期限切れは突然の Thing 認証失敗につながり、過剰権限ポリシーは侵害時の影響範囲を広げる。
スケジュール Audit の Terraform 設定
resource "aws_iot_account_audit_configuration" "main" {
enabled = true
audit_check_configurations {
ca_certificate_expiring_check {
enabled = true
}
device_certificate_expiring_check {
enabled = true
}
iot_policy_overly_permissive_check {
enabled = true
}
device_certificate_shared_check {
enabled = true
}
logging_disabled_check {
enabled = true
}
}
audit_notification_target_configurations {
sns {
enabled = true
target_arn = aws_sns_topic.iot_audit_alert.arn
role_arn= aws_iam_role.iot_audit_role.arn
}
}
}
# 毎日 02:00 JST (17:00 UTC) にスケジュール実行
resource "aws_iot_scheduled_audit" "daily" {
name= "daily-security-audit"
frequency = "DAILY"
target_check_names = [
"DEVICE_CERTIFICATE_EXPIRING_CHECK",
"IOT_POLICY_OVERLY_PERMISSIVE_CHECK",
"DEVICE_CERTIFICATE_SHARED_CHECK",
"LOGGING_DISABLED_CHECK"
]
}
Audit 結果は SNS 経由で Slack / PagerDuty に転送し、運用チームが即時対応できる体制を整える。
5-3. Detect — ルールベース異常検知
Detect は Security Profile にルールを定義し、デバイスの行動がルールを逸脱した場合にアラームを発報する。ルールは Metric (行動の数値指標) に対して閾値を設定する形式だ。
主な Detect Metric
| Metric | 説明 | 単位 |
|---|---|---|
aws:num-authorization-failures | 認証失敗回数 | count |
aws:num-connection-attempts | 接続試行回数 | count |
aws:num-disconnects | 切断回数 | count |
aws:num-messages-sent | 送信メッセージ数 | count |
aws:num-messages-received | 受信メッセージ数 | count |
aws:source-ip-address | 接続元 IP アドレスの種類数 | set count |
aws:listening-tcp-ports | Listen 中の TCP ポート一覧 | set |
aws:bytes-out | 送信バイト数 | bytes |
Security Profile の Terraform 設定例
resource "aws_iot_security_profile" "abnormal_behavior" {
name = "prod-abnormal-behavior-profile"
behaviors {
name= "high-auth-failures"
metric = "aws:num-authorization-failures"
criteria {
comparison_operator = "greater-than"
value {
count = 10
}
duration_seconds = 300
}
suppress_alerts = false
}
behaviors {
name= "message-spike"
metric = "aws:num-messages-sent"
criteria {
comparison_operator = "greater-than"
value {
count = 1000
}
duration_seconds = 60
}
suppress_alerts = false
}
alert_targets {
alert_target_type = "SNS"
alert_target_arn = aws_sns_topic.iot_detect_alert.arn
role_arn = aws_iam_role.iot_detect_role.arn
}
}
アラーム発報時は CloudWatch Alarm → SNS → Lambda のチェーンで自動対処フローを組むことが多い。
5-4. ML Detect — 機械学習による行動異常の自動検知
ML Detect はデバイスの過去の行動データ (Metric の時系列) から正常ベースラインを機械学習で自動構築し、ベースラインから逸脱したデバイスを検知する。ルールベースの Detect と異なり、閾値を事前に決めなくてよい点が最大の利点だ。
ML Detect の仕組み
過去 14 日間 (推奨) のデバイス行動データ
└── ML モデル学習 (1 日 1 回更新)
└── Baseline (正常範囲の統計分布)
└── リアルタイム Metric と比較
├── 正常範囲内 → NORMAL
└── 逸脱 → ANOMALY (アラーム発報)
ML モデルの学習には最低 14 日間の連続データが必要だ (AWS 推奨は 14〜30 日)。学習データが不足している段階では検知が行われないため、本番投入の 2 週間前からデータ収集を開始しておく。
Sensitivity (感度) 設定
Sensitivity は LOW / MEDIUM / HIGH の 3 段階で、高いほど微小な逸脱でもアラームが発報される。
| Sensitivity | 特徴 | 推奨用途 |
|---|---|---|
| LOW | 大幅な逸脱のみ検知 / False Positive 最小 | 初期運用 / デバイス台数が多い環境 |
| MEDIUM | バランス型 (デフォルト推奨) | 通常の本番環境 |
| HIGH | 微小逸脱も検知 / False Positive 増加 | 医療機器など高セキュリティ要件 |
False Positive (誤検知) 対策
ML Detect の運用初期は誤検知が多い。以下の対策を組み合わせる。
- Sensitivity を LOW から始める — 明らかな異常から順に対応し、運用に慣れてから MEDIUM/HIGH に上げる。
- デバイスタイプ別に Security Profile を分ける — 動作特性が異なるデバイス (センサー / アクチュエーター / ゲートウェイ) を同一プロファイルに入れると正常ベースラインが歪む。
- 定期メンテナンス期間を抑制する — OTA 更新やメンテナンス期間中は一時的に
suppress_alerts = trueを設定し、メンテ起因のアラームを除外する。 - Metric を絞り込む — 最初は
aws:num-messages-sentとaws:num-authorization-failuresの 2 つだけで始め、運用データを見てから Metric を追加する。
5-5. Mitigation — 自動対処アクション
Mitigation Action は Audit / Detect / ML Detect のアラーム発報後に自動実行する対処を定義する。アクションは事前に定義しておき、Alarm にバインドする形式だ。
Mitigation Action 主要 6 種類
| Action | 処理 | 典型的な使い方 |
|---|---|---|
| ADD_THINGS_TO_THING_GROUP | 対象 Thing を指定 Thing Group に追加 | 隔離 Group や調査 Group への自動振り分け |
| REPLACE_DEFAULT_POLICY_VERSION | デフォルトポリシーを最小権限版に差し替え | 過剰権限ポリシーを自動的に制限版で上書き |
| UPDATE_DEVICE_CERTIFICATE | デバイス証明書のステータスを変更 | 侵害されたデバイス証明書を DEACTIVATE に変更 |
| UPDATE_CA_CERTIFICATE | CA 証明書のステータスを変更 | 侵害された CA 証明書を INACTIVE に変更 |
| PUBLISH_FINDING_TO_SNS | アラーム内容を SNS に送信 | Slack / PagerDuty への通知チェーンに使う |
| ENABLE_IOT_LOGGING | IoT ログを有効化 | 侵害後の詳細調査ログを取得する |
Terraform: 隔離アクションと証明書無効化アクション
# 隔離 Thing Group (通信制限ポリシーを適用済み)
resource "aws_iot_thing_group" "quarantine" {
name = "QuarantineGroup"
}
# 隔離アクションの定義
resource "aws_iot_mitigation_action" "quarantine" {
name = "quarantine-compromised-device"
role_arn = aws_iam_role.iot_mitigation_role.arn
action_params {
add_things_to_thing_group_params {
thing_group_names = [aws_iot_thing_group.quarantine.name]
override_dynamic_groups = false
}
}
}
# 証明書無効化アクションの定義
resource "aws_iot_mitigation_action" "revoke_cert" {
name = "revoke-compromised-certificate"
role_arn = aws_iam_role.iot_mitigation_role.arn
action_params {
update_device_certificate_params {
action = "DEACTIVATE"
}
}
}
隔離 Thing Group には iot:Connect のみ許可し iot:Publish / iot:Subscribe を拒否するポリシーを適用する。隔離されたデバイスはメッセージ送受信ができなくなり、侵害拡大を防止できる。
5-6. 実践的な異常検知パターン 3 選
IoT デバイスの侵害や誤動作は特定の行動パターンとして現れることが多い。以下の 3 パターンは Device Defender の Detect / ML Detect でカバーできる代表例だ。
パターン 1 — 帯域幅の異常急増 (Cellular Bandwidth / bytes-out 急増)
侵害されたデバイスがデータを外部へ大量送信する場合、aws:bytes-out が通常の数十倍に急増する。工場センサーなら通常の送信量は数 KB〜数十 KB / 分程度だ。ML Detect でベースラインを学習しておけば、マルウェアによるデータ流出が始まった瞬間に ANOMALY として検知できる。
通常状態 : bytes-out ≈ 20 KB/min (センサー計測値 + ハートビート)
侵害後 : bytes-out ≈ 5 MB/min (内部データ流出)
→ ML Detect ANOMALY → Mitigation: 証明書 DEACTIVATE + SNS 通知
パターン 2 — 予期しない TCP ポートの Listen (Listening TCP Ports 異常)
デバイスが外部からの接続を受け付ける新しいポートを開いた場合、aws:listening-tcp-ports に未知のポートが追加される。これはバックドア設置やマルウェア感染の典型的な兆候だ。Detect のルールベースで許可ポートセット (例: Port 8883 のみ) を定義し、逸脱を即検知する。
{
"behaviors": [{
"name": "only-iot-port",
"metric": "aws:listening-tcp-ports",
"criteria": {
"comparisonOperator": "in-cidr-set",
"value": { "cidrs": [] },
"consecutiveDatapointsToAlarm": 1
}
}]
}
パターン 3 — 接続頻度の異常な増加 (Cellular num-connection-attempts 急増)
短時間に異常な頻度で接続を試みるデバイスは、Broker のクレデンシャルを奪われて botnet に組み込まれた可能性がある。通常デバイスは 1 回 / 時間程度の接続試行しか行わないが、乗っ取られると分間数十回〜数百回に跳ね上がる。Detect ルールで aws:num-connection-attempts > 20 / 5分 をトリガーに隔離アクションを発動する。

学習データの準備: ML モデルの学習には最低 14 日間の連続データが必要。本番投入の 2 週間前から Security Profile を適用してデータ収集を開始する。データ不足期間は検知が行われない (Silent period)。
Sensitivity の選択基準: 初回は LOW から始め、運用 1〜2 ヶ月後に False Positive の発生頻度を確認しながら MEDIUM に上げる。HIGH は高セキュリティ要件環境のみ適用する。
デバイスタイプ別プロファイル分離: 動作特性が異なるデバイスカテゴリ (センサー / ゲートウェイ / アクチュエーター) を別々の Security Profile に分類することで、混在による誤った Baseline 形成を防ぐ。
Metric 選定は段階的に: 最初は 2〜3 Metric に絞る。多すぎる Metric は False Positive 増加と調査コスト増大を招く。運用データを見ながら段階的に追加する。
ML Detect の学習期間を待たずに本番適用: 学習データが不足した状態でデバイスを本番登録すると、モデルが形成される 14 日間は検知が行われない「空白期間」が生まれる。本番移行の前にテスト環境で 14 日間以上のデータを蓄積しておくこと。
Audit のスケジュール未設定: コンソールで Audit Configuration を有効化しただけではスケジュールが設定されず、手動実行しないと検査が行われない。aws_iot_scheduled_audit リソースを必ず作成し、DAILY または WEEKLY で自動実行を設定する。
Mitigation Action を定義したが Alarm にバインドしていない: Mitigation Action を作成しただけでは自動実行されない。Detect の Security Profile alert target と Mitigation Action を Alarm 経由で結びつける設定が必要。定期的に Alarm → Action のバインドが生きているか確認する。
隔離 Thing Group のポリシー設定漏れ: ADD_THINGS_TO_THING_GROUP アクションで Thing を隔離 Group に移動させても、隔離 Group に適用する IoT ポリシーが未設定だと通信制限が機能しない。隔離 Group に Deny: iot:Publish / iot:Subscribe ポリシーを事前に設定しておく。
§5 では IoT デバイスのセキュリティ運用を担う Device Defender の 4 機能を解説した。次の §6 では SiteWise と Device Defender を含む 4 本柱の本番運用でよく遭遇する詰まりポイント 7 選を判断ツリーとともに整理する。
§6 詰まりポイント7選 図解 (Mermaid01 判断ツリー)
AWS IoT の本番運用では、4本柱にまたがる特有の詰まりパターンが存在する。コンテナやサーバーレスの経験者が初めて IoT システムを構築する際、「なぜか接続できない」「Job がなぜか別のデバイスに届いた」「SiteWise の Metric が急に計算されなくなった」といった症状で数時間〜数日を費やすことが多い。本節では現場で頻出する7パターンを症状・原因・解決策の三点セットで解説する。
詰まり1: Device Certificate 期限切れ → Thing 認証失敗
症状: ある日突然、特定デバイス群が IoT Core に接続できなくなる。CloudWatch の ConnectError が急増するが、ネットワーク障害や IoT Core 側の障害は確認されない。デバイスのログには CERTIFICATE_EXPIRED が記録されている。
原因: X.509 証明書の有効期限切れ。AWS IoT が発行する証明書のデフォルト有効期限は5年だが、ACM Private CA や自社 CA で発行した証明書は PKI ポリシーによって1〜3年に設定されていることが多い。証明書の期限管理を IoT システム外で実施していた場合、期限切れを事前検知できずに認証失敗が発生する。
解決策:
– ACM Private CA の CertificateExpiration CloudWatch アラームを設定し、期限 90日前・30日前に SNS 通知
– Fleet Provisioning テンプレートを事前整備し、証明書ローテーション手順を文書化
– 証明書の有効期限を Thing の Attribute に記録し、Dynamic Thing Group で期限切れ接近デバイスを自動集約
resource "aws_cloudwatch_metric_alarm" "cert_expiry_alarm" {
alarm_name = "iot-cert-expiry-30days"
comparison_operator = "LessThanThreshold"
evaluation_periods = 1
metric_name= "DaysToExpiry"
namespace = "AWS/ACM"
period = 86400
statistic = "Minimum"
threshold = 30
alarm_actions = [aws_sns_topic.cert_alerts.arn]
}
(1) 証明書有効期限を Thing Attribute に記録 → Dynamic Thing Group で期限切れ接近デバイスを自動集約
(2) ACM Private CA の期限通知 (EventBridge → SNS) を全証明書に設定 (90日前・30日前)
(3) Fleet Provisioning テンプレートで証明書ローテーションを自動化 → 手動1万台更新を防ぐ
(4) 証明書有効期限をデバイスごとにオフセット (例: ±90日) し、一斉期限切れを防ぐ
詰まり2: Thing Group 設計ミス → Job ターゲット誤配布
症状: ファームウェア更新 Job を「工場A のセンサー」に発行したつもりが、工場B のセンサーにも配布されてしまった。または Dynamic Thing Group のクエリが意図せず広すぎ、無関係のデバイスが更新対象になった。
原因: Thing Group 階層設計の誤りと Dynamic Thing Group のクエリ条件が不十分な組み合わせ。Thing Group は親子関係で Job を継承するため、親グループへの Job が子グループ全体に伝播する。Dynamic Thing Group のクエリが広すぎると、想定外のデバイスが対象になる。
解決策:
– Thing Group 階層は env/region/building/device-type の4階層を基本設計とし、Job ターゲットは必ず末端グループを指定
– Job 発行前に list-things-in-thing-group でターゲットデバイス一覧を確認し、レビューをプロセスに組み込む
– Dynamic Thing Group のクエリは attributes.firmware_version:1.* の代わりに attributes.firmware_version:[1.0.0 TO 1.9.9] のように範囲を厳密に指定する
(1) Thing Group 階層は env/region/building/device-type の4階層で設計
(2) Job 発行前に
aws iot list-things-in-thing-group で対象デバイス数を確認(3) Dynamic Thing Group のクエリは範囲を厳密指定 → 意図しない広すぎる条件を避ける
(4) Snapshot Job vs Continuous Job の用途を明確化 (Continuous は Dynamic Group 専用)
詰まり3: IoT Rules SQL WHERE 句の罠 (NULL 値 / 型変換)
症状: WHERE temperature > 80 という Rules Engine の SQL を設定したが、一部のデバイスが 80℃超のデータを送っているのに Lambda が呼ばれない。Rules SQL の評価は通っているのに SiteWise にデータが届かない、といった症状も頻出する。
原因: IoT Rules SQL の型変換と NULL 値処理の仕様。デバイスが temperature を文字列 ("85") として送信していると、数値比較 > 80 が正常に機能しない。フィールドが存在しないメッセージに WHERE 句を適用すると、undefined 値として評価され条件が false になる。SELECT * FROM '#' はトピック全体をサブスクライブするため、意図せず全メッセージを処理対象にしてしまう。
解決策:
-- 悪い例: 型が不定 / フィールドなし時に評価失敗
SELECT * FROM 'prod/+/+/+/+/telemetry'
WHERE temperature > 80
-- 良い例: 型変換 + NULL チェック + トピック絞り込み
SELECT cast(temperature AS Decimal) as temp,
device_id,
timestamp() as ts
FROM 'prod/ap-northeast-1/+/temperature-sensor/+/telemetry'
WHERE isUndefined(temperature) = false
AND cast(temperature AS Decimal) > 80.0
(1) 数値比較前に
cast(field AS Decimal) で型変換を明示(2)
isUndefined(field) = false を WHERE 句の先頭に置き、フィールド欠落メッセージを除外(3)
FROM '#' は開発デバッグ専用 → 本番は必ずトピックフィルターを絞り込む(4) SQL バージョン
2016-03-23 を明示指定し、古い挙動の差異を排除するflowchart TD
A[IoT問題発生] --> B{Certificate期限切れ?}
B -->|Yes| C[PCA自動ローテーション設定\nDynamic Thing Groupで期限管理]
B -->|No| D{Job誤配布?}
D -->|Yes| E[ThingGroup階層設計確認\nJob前にlist-things確認]
D -->|No| F{Rules SQL失敗?}
F -->|Yes| G[WHERE句NULL/型変換確認\ncast+isUndefined追加]
F -->|No| H{Greengrass更新失敗?}
H -->|Yes| I[ComponentバージョンPIN確認\nLATEST禁止→セマンティックVer固定]
H -->|No| J{SiteWise Metric崩壊?}
J -->|Yes| K[Asset hierarchy親子依存確認\n設計変更は新モデル作成で対応]
J -->|No| L{ML Detect誤検知?}
L -->|Yes| M[Sensitivity設定調整\nLow→Medium段階確認]
L -->|No| N[Job Rollout設定確認\nmaximumPerMinute+abortConfig]
詰まり4: Greengrass Component version 固定忘れ → 本番更新でブレーキ解放
症状: Greengrass Deployment で LATEST を指定していたコンポーネントが、AWS による新バージョン公開とともに自動更新された。新バージョンに互換性のない変更が含まれており、全フリートのコンポーネントがクラッシュした。
原因: ComponentVersion: LATEST 指定は Deployment 実行時点の最新バージョンを取得する。AWS がコンポーネントを更新すると次の Deployment 時に意図しないバージョンアップが発生する。aws.greengrass.Nucleus・aws.greengrass.StreamManager 等の AWS 管理コンポーネントはマイナーバージョンでも動作変更が入ることがある。
解決策:
– Terraform / AWS CLI で Deployment を管理する場合、全コンポーネントのバージョンをセマンティックバージョン (例: 2.12.0) で固定する
– 新バージョンへの更新は テスト環境 → カナリアグループ (5%) → 本番全体 (100%) の段階手順を踏む
– failure_handling_policy: ROLLBACK で失敗時の自動復帰を必ず保証する
(1) 全コンポーネントのバージョンを
LATEST 禁止 → セマンティックバージョンで Terraform 管理(2) AWS 管理コンポーネント (Nucleus/StreamManager/TokenExchangeService) は特に注意
(3) バージョンアップは テスト → カナリア (5%) → ステージング (20%) → 本番 (100%) の4段階
(4) Deployment の
failure_handling_policy: ROLLBACK を必ず設定し、失敗時の自動復帰を保証する詰まり5: SiteWise Asset hierarchy 設計誤り → Metric 計算の親子依存崩壊
症状: 工場ライン全体の消費電力を集計する Metric が突然 null を返すようになった。個々のセンサーデータは正常に届いているが、上位 Asset の Metric 計算が停止している。
原因: SiteWise の Metric / Transform は Asset Model 階層の親子依存関係に基づいて計算される。親 Asset Model の Metric が子 Asset の Property を参照している状態で、子 Asset Model を削除・再作成すると階層の依存関係が崩壊する。SiteWise の Asset Model はイミュータブルな設計に近く、一度作成したモデルへの変更は制限される。
解決策:
– Asset Model 設計は本番稼働前に完全にフリーズする。「後で階層を追加すればいい」という考えは危険
– 設計変更が必要な場合は 新 Asset Model を作成 → データ移行 → 旧 Asset を削除 の順で実施。既存 Asset の Model 変更は不可
– Asset hierarchy の設計は 工場 → ライン → 機器 → センサー の4層を標準とし、Metric 集計のデータフローを図にしてレビューする
(1) Asset Model 設計は本番稼働前に完全フリーズ → 後付け変更はコスト大
(2) 親子依存 Metric のデータフローを図示し、計算の依存ツリーを事前レビュー
(3) 設計変更時は 新モデル作成 → データ移行 → 旧 Asset 削除 の順で安全に実施
(4) Sampling interval (最小 1秒) と Metric 集計窓 (最小 1分) は設計時に明示指定
詰まり6: Device Defender ML Detect FP (誤検知) → Sensitivity 設定最適化
症状: Device Defender ML Detect が「異常デバイス」として多数アラートを発出し、Mitigation Action によってデバイスが次々と切断された。しかし実際には正常なデバイスであり、誤検知 (False Positive) だった。
原因: ML Detect の Sensitivity が High に設定されており、通常のトラフィックパターン変動 (日中 vs 夜間) を異常として検知した。ML Detect はデバイスの行動プロファイルを学習するため、学習データが不十分な初期 (最低14日間推奨) や業務繁閑に応じたトラフィック変動を学習前に High 感度で運用すると誤検知が多発する。
解決策:
– 初期導入時は Sensitivity を Low で開始し、14〜30日間の学習期間を確保してからアラートを本番評価に使用する
– Sensitivity は Low → Medium → High と段階的に上げる。一度に High にしない
– ML Detect アラートを Mitigation Action (自動切断) に直結させない。最初は SNS 通知 + 人手確認のみにし、FP 率を計測してから自動化を判断する
(1) 初期導入は Sensitivity=Low + 30日間観察期間 → FP 率確認後 Medium に昇格
(2) 自動 Mitigation (デバイス切断) は FP 率 <1% を確認してから有効化
(3) 業務サイクル (昼夜/繁閑) をカバーする十分なトレーニングデータを確保
(4) ML Detect と Rule-based Detect を並列で運用し、相互補完的に活用する
詰まり7: IoT Job Rollout 設定ミス → 全デバイス同時更新でサービス停止
症状: ファームウェア更新 Job を発行したところ、1000台のデバイスが数分以内に一斉に更新を開始した。帯域逼迫と更新失敗が連鎖し、30% のデバイスが不整合な状態で止まった。
原因: jobExecutionsRolloutConfig の maximumPerMinute を指定しなかった (デフォルトは無制限)。また abortConfig も未設定のため、失敗が連鎖しても Job は継続した。
解決策:
jobExecutionsRolloutConfig:
maximumPerMinute: 10
exponentialRate:
baseRatePerMinute: 5
incrementFactor: 2
rateIncreaseCriteria:
numberOfSucceededThings: 50
abortConfig:
criteriaList:
- action: CANCEL
failureType: FAILED
minNumberOfExecutedThings: 10
thresholdPercentage: 10.0
timeoutConfig:
inProgressTimeoutInMinutes: 30
(1)
maximumPerMinute は必ず指定 (デフォルト=無制限は本番禁止)(2)
abortConfig.thresholdPercentage: 失敗率 10〜20% で Job 自動停止(3)
timeoutConfig: 更新タイムアウトで中途半端なままのゾンビ Job を防止(4) Exponential Rate で成功実績を積みながら段階加速 → 大規模フリートの安全な更新を実現
詰まり1: Certificate 期限切れ → ACM Private CA 期限通知 + Fleet Provisioning 自動ローテーション
詰まり2: Job 誤配布 → ThingGroup 4階層設計 + 発行前デバイス確認
詰まり3: Rules SQL 失敗 → cast + isUndefined + トピックフィルター絞り込み
詰まり4: Component 自動更新 → LATEST 禁止 + セマンティックバージョン固定
詰まり5: SiteWise Metric 崩壊 → Asset Model 設計フリーズ + 変更は新モデル作成
詰まり6: ML Detect 誤検知 → Sensitivity=Low 開始 + 30日学習 + 自動切断の段階的有効化
詰まり7: Job 全台同時更新 → maximumPerMinute + abortConfig + timeoutConfig 必須設定
§7 アンチパターン → 正解パターン変換演習 (5問)
現場で実際に発生したアンチパターンを5問の変換演習として整理した。各問は「悪い実装」と「正しい実装」をコードレベルで対比し、なぜ悪いのか・なぜ良いのかを解説する。
Q1: 個別 Certificate 手動管理 → AWS Private CA 連携 + 自動ローテーション
状況: 100台のデバイスを管理する IoT システムで、各デバイスの証明書をスプレッドシートで有効期限管理していた。デバイスが月に5台ずつ増加するにつれ、手動管理の限界に達しつつある。
悪い実装 (アンチパターン):
# 手動で証明書を発行・デバイスに転送
aws iot create-keys-and-certificate --set-as-active \
--certificate-pem-outfile device-001.crt \
--private-key-outfile device-001.key
# スプレッドシートに有効期限を手動記録
# 有効期限が来たらまた手動で更新
# 1000台になったとき、これは不可能
良い実装 (正解パターン):
resource "aws_acmpca_certificate_authority" "iot_ca" {
type = "SUBORDINATE"
certificate_authority_configuration {
key_algorithm = "RSA_2048"
signing_algorithm = "SHA256WITHRSA"
subject {
common_name = "IoT Device CA"
organization = "MyCompany"
country= "JP"
}
}
}
resource "aws_iot_ca_certificate" "ca_cert" {
active= true
ca_certificate_pem= aws_acmpca_certificate_authority.iot_ca.certificate
certificate_mode = "SNI_ONLY"
allow_auto_registration = true
registration_config {
template_arn = aws_iot_provisioning_template.device_template.arn
role_arn = aws_iam_role.iot_provisioning_role.arn
}
}
解説: Fleet Provisioning + ACM Private CA を組み合わせると、デバイスの初回接続時に本番証明書を自動発行し、PCA の自動更新と連携してローテーションを自動化できる。スプレッドシート管理は台数が100台を超えた時点で破綻する。Terraform でテンプレートを管理することで、新規デバイス追加のオペレーションコストをゼロに近づけられる。
Q2: Pull-based Polling → IoT Rules Engine + Event-driven
状況: デバイスのアラート状態を確認するため、Lambda が1分ごとに全デバイスの Device Shadow をポーリングしていた。デバイス数が1000台を超えたあたりから、Lambda の実行コストと API スロットリングが問題になり始めた。
悪い実装 (アンチパターン):
# Lambda が1分毎に全デバイスの Shadow をポーリング
def lambda_handler(event, context):
iot = boto3.client('iot-data')
devices = get_all_device_ids() # DynamoDB から全台取得
for device_id in devices:
shadow = iot.get_thing_shadow(thingName=device_id)
state = json.loads(shadow['payload'].read())
if state['state']['reported'].get('alert'):
send_alert(device_id)
# 1万台 × 毎分 = 大量 API コール + Lambda コスト増大
良い実装 (正解パターン):
resource "aws_iot_topic_rule" "alert_rule" {
name = "device_alert_trigger"
enabled = true
sql= <<-EOF
SELECT topic(4) as device_id,
state.reported.alert,
timestamp() as ts
FROM '$aws/things/+/shadow/update/accepted'
WHERE state.reported.alert = true
EOF
sql_version = "2016-03-23"
lambda {
function_arn = aws_lambda_function.alert_handler.arn
}
}
解説: Rules Engine + shadow/update/accepted トピックを使うと、デバイスがアラートを報告した瞬間にイベント駆動で Lambda が起動する。ポーリングと比べてコストが 1/100 以下になり、レイテンシも数分 → 数秒に改善する。デバイス台数が増えても Rules Engine はスケールするため、ポーリング Lambda のような「台数依存コスト」が発生しない。
Q3: Edge 処理なし → Greengrass ML Inference (レイテンシ削減 + 帯域最適化)
状況: 製造ラインのカメラ画像をすべてクラウドに転送し、SageMaker エンドポイントで異常検知していた。1ライン5台のカメラで1日あたり数百GB の転送が発生し、帯域コストが月額100万円を超えてしまった。
悪い実装 (アンチパターン):
# 全フレームをクラウドへ転送 → SageMaker で推論
def process_frame(frame_bytes):
s3 = boto3.client('s3')
sm = boto3.client('runtime.sagemaker')
# 1フレーム (1MB) × 30fps × 24時間 = 約 2.5TB/日
s3.put_object(Bucket='frames', Key=f'frame-{ts}.jpg', Body=frame_bytes)
response = sm.invoke_endpoint(
EndpointName='anomaly-detector',
Body=frame_bytes,
ContentType='image/jpeg'
)
# ネットワーク遅延 + API コスト + S3 コストが積み重なる
良い実装 (正解パターン):
Manifests:
- Artifacts:
- URI: 's3://my-ml-models/mobilenet_anomaly_v3.tar.gz'
Unarchive: TAR
Lifecycle:
Run:
Script: |
python3 inference.py \
--model-dir {artifacts:decompressedPath}/model \
--confidence-threshold 0.85 \
--upload-anomalies-only true
# 異常フレームのみクラウド転送 → 帯域 99% 削減
解説: Greengrass ML Inference により、エッジで推論を完結させ「異常のみ」クラウドに転送するアーキテクチャへ転換できる。異常率が 0.1% の場合、転送データ量は 1/1000 になる。推論レイテンシも 200ms (クラウド往復) → 30ms (エッジ GPU) に改善する。帯域コストが劇的に下がるだけでなく、ライン異常への応答速度も向上する。
Q4: 手動異常検知 → Device Defender ML Detect (自動化 + スケーラブル)
状況: CloudWatch で MessagesSent メトリクスの手動閾値アラーム (1000件/分超えでアラート) を設定していたが、攻撃を受けたデバイスは 999件/分で送信し続け、閾値をすり抜けた。またデバイスごとのトラフィック特性が違うため、全デバイス共通の閾値では誤検知と見逃しの両方が多発していた。
悪い実装 (アンチパターン):
resource "aws_cloudwatch_metric_alarm" "messages_alarm" {
alarm_name = "iot-messages-threshold"
metric_name= "PublishIn.Success"
namespace = "AWS/IoT"
threshold = 1000
comparison_operator = "GreaterThanThreshold"
# 固定閾値はデバイスプロファイルの個体差を無視
# 意図的に閾値直下で維持される攻撃を検知できない
}
良い実装 (正解パターン):
resource "aws_iot_security_profile" "ml_detect_profile" {
name = "fleet-ml-detect"
behaviors {
name= "MessagesSent-ml"
metric = "aws:num-messages-sent"
criteria {
comparison_operator = "ML_DETECT_LESS_THAN_OR_EQUAL"
ml_detection_config {
confidence_level = "MEDIUM"
}
}
}
alert_targets {
alert_target_type = "SNS"
alert_target_arn = aws_sns_topic.iot_alerts.arn
role_arn = aws_iam_role.iot_defender_role.arn
}
}
解説: ML Detect はデバイスごとの行動プロファイル (過去14日間のベースライン) と比較して異常を検知するため、固定閾値では検知できない「個体差を活用した低速攻撃」を捕捉できる。デバイス台数が増えても管理コストがスケールしない点も重要で、10万台のフリートでも1つの Security Profile で管理できる。
Q5: フラット構造 Thing 管理 → Thing Group + Billing Group (コスト可視化 + Job 管理)
状況: 1万台の Thing が階層なくフラットに登録されており、「工場A のセンサーだけ更新」「IoT Core の月間コストを工場別に把握」が両方できない状態だった。Job 発行のたびにデバイス ID リストを手動でまとめる運用が限界に達していた。
悪い実装 (アンチパターン):
resource "aws_iot_thing" "sensors" {
for_each = var.device_ids
name = each.value
# グループなし / タグなし
# Job 配布もコスト集計も困難
}
良い実装 (正解パターン):
resource "aws_iot_thing_group" "plant_a_temp_sensors" {
name = "PlantA-TempSensors"
parent_group_name = aws_iot_thing_group.plant_a.name
}
resource "aws_iot_billing_group" "plant_a_billing" {
name = "PlantA-BillingGroup"
properties {
billing_group_description = "工場A IoT コスト配賦グループ"
}
}
resource "aws_iot_thing_group_membership" "thing_to_group" {
for_each= var.plant_a_device_ids
thing_name = each.value
thing_group_name = aws_iot_thing_group.plant_a_temp_sensors.name
}
resource "aws_iot_billing_group_membership" "thing_to_billing" {
for_each = var.plant_a_device_ids
thing_name= each.value
billing_group_name = aws_iot_billing_group.plant_a_billing.name
}
解説: Thing Group の4階層設計により Job を精密なターゲットに絞り込める。Billing Group を工場・部門別に設定することで、IoT Core の接続・メッセージ・Job 実行コストを部門別に Cost Explorer で確認できる。SRE として IoT コストの可視化は必須の設計であり、Billing Group は後から追加するとデータの遡及が困難なため、最初から設計に組み込むことを推奨する。
§8 まとめ + 第19軸目 IoT 起点 + 45記事化告知 + 全軸クロスリンクナビ
4本柱の学習まとめ
本記事では AWS IoT 本番運用の4本柱を一気に解説した。各柱のエッセンスを最後に整理する。
IoT Core は MQTT ブローカー設計の三本柱として、Topic 4階層・QoS 1・Persistent Session が基本だ。Certificate 管理は Fleet Provisioning + ACM Private CA による自動化が必須で、手動管理は100台を超えた時点で破綻する。Rules Engine の SQL は型変換 (cast)・NULL チェック (isUndefined)・トピックフィルター絞り込みを徹底し、SELECT * FROM '#' は本番で使わない。Device Shadow の Named Shadow により、設定/ステータス/アラートを別ドキュメントで分離管理することでアクセス制御が細粒度化できる。
Greengrass は Component バージョンを LATEST 禁止・セマンティックバージョン固定が絶対ルールだ。Stream Manager でエッジの耐断絶性を確保し、ML Inference でクラウド帯域コストを最小化する。Deployment は 5% カナリア → 20% → 100% の3段階ロールアウトで安全に実施し、failure_handling_policy: ROLLBACK で失敗時の自動復帰を保証する。Lambda Component を活用することで、既存の Lambda 関数をエッジへ段階移行できる。
SiteWise は Asset Model の設計を本番稼働前に完全フリーズすることが最重要だ。OPC-UA Gateway の設置位置とデータサンプリング間隔の設計が産業データ品質を左右する。Metric / Transform の親子依存ツリーは事前に図示してレビューし、後から設計変更が困難な点を念頭に置く。Portal の権限設計 (Viewer / Operator / Administrator) は部門別アクセス制御の単位として位置づける。
Device Defender は ML Detect の初期導入に Sensitivity=Low・30日学習期間確保・自動 Mitigation の段階的有効化の3ステップを守る。Audit は週次スケジュールで実行し、Certificate 期限切れ・ポリシー過剰権限・デバイスの不審な接続パターンを定期チェックする。Mitigation Action は「通知 → 隔離 (Quarantine) → 切断」の段階設計とし、誤動作時のリカバリ手順を事前に準備する。
AWS IoT 本番設計 5原則
本記事全体を通じて一貫して強調してきた設計哲学を5原則としてまとめる。
原則1: Certificate から始めよ
IoT システムの根幹はデバイスの認証だ。証明書管理が自動化されていないシステムは、台数増加とともに運用不能になる。Fleet Provisioning + ACM Private CA による自動証明書発行・ローテーションを Day 1 から設計に組み込む。
原則2: Event-driven を徹底せよ
ポーリングは IoT のアンチパターンだ。デバイスが「変化した瞬間」に Rules Engine でイベントを発生させ、Lambda・SiteWise・Kinesis へルーティングする Event-driven アーキテクチャが IoT のコストと応答速度を最適化する。デバイスが 10万台になっても Rules Engine はスケールするが、ポーリング Lambda はスケールしない。
原則3: エッジでフィルタリングせよ
全データをクラウドに送ることをデフォルトにしてはいけない。Greengrass の Stream Manager・ML Inference・Lambda Component を活用し、「異常・変化・集計後データ」のみをクラウドに転送するアーキテクチャを設計する。帯域コストの削減と応答レイテンシの改善は同時に達成できる。
原則4: 設計をフリーズしてから稼働せよ
SiteWise の Asset Model は変更が困難で、Thing Group・Billing Group も後から追加すると既存データへの遡及適用ができない。デバイス階層・データモデル・コスト配賦グループは本番稼働前に完全にフリーズし、「あとで追加すればいい」という考えを持ち込まない。
原則5: 異常検知は段階的に自動化せよ
Device Defender ML Detect の自動 Mitigation Action (デバイス切断) は、FP 率を確認してから有効化する。最初は通知のみ、次に隔離、最後に切断という段階的な自動化が、誤動作によるサービス停止を防ぐ。同様に Job の Rollout 設定も maximumPerMinute を必ず設定し、「段階的に展開する」思想を徹底する。
本番運用チェックリスト — 稼働前の最終確認
本番稼働前に以下のチェックリストを確認することを推奨する。
Certificate / Thing Registry
– [ ] Fleet Provisioning テンプレートを整備し、デバイス自動登録フローを検証済み
– [ ] 証明書有効期限の分散設定 (有効期限オフセット ±90日)
– [ ] ACM Private CA の期限通知 (EventBridge → SNS) を設定済み
– [ ] Thing Group の階層設計 (4階層) を事前レビュー済み
– [ ] Billing Group を工場・部門別に設定済み
MQTT / Rules Engine
– [ ] Topic 設計が最低4階層 (env/region/building/device-type)
– [ ] Rules Engine の SQL に cast + isUndefined を適用済み
– [ ] error_action を全 Rule に設定済み (評価失敗の DLQ)
– [ ] QoS 1 をコマンド・アラート系のトピックに適用済み
Greengrass
– [ ] 全 Component のバージョンをセマンティックバージョンで固定済み
– [ ] Stream Manager の strategy_on_full と batch_size を設定済み
– [ ] Deployment の failure_handling_policy: ROLLBACK を設定済み
– [ ] カナリアグループ (5%) を事前に Thing Group として定義済み
SiteWise
– [ ] Asset Model の階層設計を確定し、変更凍結済み
– [ ] OPC-UA Source の認証をデフォルト匿名認証から X.509 に変更済み
– [ ] Metric / Transform の親子依存ツリーを図示・レビュー済み
– [ ] Portal の権限設計 (Viewer / Operator / Administrator) を完了済み
Device Defender
– [ ] Audit のスケジュール (aws_iot_scheduled_audit WEEKLY) を設定済み
– [ ] ML Detect Security Profile を Sensitivity=Low で作成済み
– [ ] 隔離 Thing Group に Deny: iot:Publish / iot:Subscribe ポリシーを設定済み
– [ ] Mitigation Action のバインド (Alarm → Action) を確認済み
Job / Rollout
– [ ] maximumPerMinute を全 Job に設定済み (デフォルト=無制限は禁止)
– [ ] abortConfig を設定済み (失敗率 10〜20% で自動停止)
– [ ] timeoutConfig を設定済み (ゾンビ Job 防止)
第19軸目 IoT 起点宣言と後続 Vol への道
本記事は AWS 本番運用シリーズの第19軸目「IoT」の起点として設計された。これまでの18軸がコンテナ・サーバーレス・ネットワーク・セキュリティ・AI/ML・DevOps といったクラウドネイティブの世界を扱ってきたのに対し、IoT シリーズは物理世界のデータをクラウドに接続するという新たな次元を開拓する。
製造業のスマートファクトリー、物流の冷凍コンテナ追跡、スマートシティの交通制御——これらのユースケースは全て、本記事で学んだ4本柱の組み合わせで実現できる。IoT Core で数万台のデバイスを束ね、Greengrass でエッジ推論を走らせ、SiteWise で産業データを構造化し、Device Defender で異常デバイスを自動隔離する。この4層が揃ったとき、AWS IoT の真の力が発揮される。
IoT 本番運用で最初に感じる壁は「デバイスが接続できない」という Certificate の問題だ。そこを越えると次は「思ったデータが届かない」という Rules Engine の問題、そして「エッジでどこまで処理するか」という Greengrass の設計問題へと発展する。本記事の §6 詰まり7選が、その壁を越えるためのチェックリストとして機能することを意図している。
AWS本番運用シリーズは第19軸目「IoT」を開拓した。製造業・物流・スマートシティの IoT 本番運用に踏み出す SRE / プラットフォームエンジニアの起点として、本記事が機能することを意図した。
後続ロードマップ (第19軸目 IoT Vol2+):
・IoT Vol2: AWS IoT Events (状態マシン型イベント検知) × IoT TwinMaker (デジタルツイン) × FleetWise (車両・移動体データ収集)
・IoT Vol3: IoT Analytics パイプライン × Kinesis Data Analytics × QuickSight 可視化 × Timestream 時系列 DB
各 Vol は本記事で習得した IoT Core / Greengrass / SiteWise / Device Defender を基盤として発展させる構成だ。
graph LR
IOT[IoT本番運用 Vol1\n第19軸目起点\nCore/Greengrass/SiteWise/Defender] --> CONT[Container Vol1-3\nGreengrass Docker統合]
IOT --> SEC[Security Vol1-3\nDevice Certificate+IAM]
IOT --> AI[AI/ML Vol1-3\nGreengrass ML Inference]
IOT --> NET[Network Vol1-2+Hybrid\nSite-to-Site VPN/DX]
IOT --> OBS[Observability Vol1-2\nCloudWatch IoT統合]
IOT --> SRV[Serverless Vol1-2\nLambda IoT Trigger]
IOT --> STG[Storage Vol1-2\nIoT Data to S3]
IOT --> ANL[Analytics Vol1\nIoT Analytics/Kinesis]
本記事の公開により、AWS本番運用シリーズは 44記事 → 45記事 へと到達した。第19軸目 IoT の開拓で、このシリーズはコンテナ・サーバーレス・セキュリティ・AI/ML に加え、物理世界のデータを扱うエッジ・IoT 領域へと版図を広げた。
全19軸 45記事 全景:
Container Vol1-3 (3記事) / Security Vol1-3 (3記事) / Network Vol1-2+Hybrid (3記事) / IAM Vol1 (1記事) / Observability Vol1-2 (2記事) / Serverless Vol1-2 (2記事) / Storage Vol1-2 (2記事) / Database Vol1-3 (3記事) / Edge-CDN Vol1 (1記事) / Analytics Vol1 (1記事) / Migration Vol1 (1記事) / DevOps CI/CD Vol1-4 (4記事) / AI-ML Vol1-3 (3記事) / Step Functions Vol1-2 (2記事) / 古参リライト batch1-6 (6記事) / IoT Vol1 (本記事 第19軸目新規) 合計 45記事
IoT 本番運用の典型的インシデントと対応パターン
実際の IoT 本番運用では、以下の3つのインシデントパターンが頻出する。対応フローを事前に設計しておくことで、影響を最小化できる。
インシデント1: 大量デバイスの一斉接続断 (ブリザードアタック)
症状: IoT Core の接続数が短時間で急落し、数百〜数千台のデバイスが同時に再接続を試みる。再接続のスパイクが更なる接続エラーを誘発するカスケード障害に発展する。
原因: ネットワーク瞬断・クラウド側メンテナンス・証明書一斉期限切れのいずれか。
対応:
– デバイスの再接続ロジックに Exponential Backoff + Jitter を実装する (AWS IoT Device SDK v2 のデフォルト)
– 再接続試行間隔: min(base * 2^attempt + random(0, jitter), max_backoff) の計算式を使用
– Persistent Session (QoS 1) でオフライン中のメッセージをキューに保持し、再接続後に受信
インシデント2: Greengrass フリートの Deployment 失敗ループ
症状: Deployment が全デバイスに FAILED を返し、ロールバックが発生する。ロールバック後に同じ Deployment を再実行しても同様に失敗する。
原因: Component レシピの記述誤り・S3 アーティファクトへのアクセス権限不足・デバイス側のディスク容量不足のいずれか。
対応:
1. 失敗デバイスのログを journalctl -u greengrass で確認
2. aws greengrassv2 list-installed-components --core-device-thing-name {thingName} で現在インストール済みのバージョンを確認
3. 問題のあるコンポーネントを特定し、レシピを修正してバージョンを上げて再デプロイ
4. デバイス側ストレージが不足している場合は /greengrass/v2/packages/ の古いバージョンを手動クリーンアップ
インシデント3: SiteWise データ欠損と Metric 再計算不可
症状: 特定時間帯の SiteWise Measurement データが欠損し、過去データに基づく Metric 集計値が不正確になった。
原因: Greengrass Gateway の接続断による Edge バッファオーバーフロー、または OPC-UA Server 側のデータ欠損。
対応:
– DescribeAssetProperty API で Property の最終更新時刻を確認し、欠損期間を特定
– BatchGetAssetPropertyValueHistory で正常データの範囲を確認
– BatchPutAssetPropertyValue API で欠損期間のデータを補完投入 (データソースが別途保存されている場合)
– Metric 計算の再トリガーは SiteWise が自動実行するため、データ補完後に次の集計窓まで待つ
全軸クロスリンクナビ
本記事で習得した IoT 4本柱は AWS 本番運用シリーズの既存軸と深く連携している。以下の関連軸を参照することで、IoT システムの設計をより深く理解できる。
| IoT の関心事 | 参照すべき軸 | 具体的なつながり |
|---|---|---|
| Greengrass で Docker コンテナを実行 | Container Vol1-3 | ECS/EKS の知識をエッジへ応用 |
| Device Certificate + IAM 最小権限 | Security Vol1-3 | ACM Private CA × IoT ポリシー設計 |
| Greengrass ML モデルの本番デプロイ | AI-ML Vol1-3 | SageMaker Neo コンパイル → OTA 配信 |
| IoT データ → S3 → 分析パイプライン | Storage Vol1-2 | Rules Engine → S3 → Athena クエリ |
| Lambda IoT Trigger / Step Functions | Serverless Vol1-2 | Event-driven アーキテクチャ全体像 |
| CloudWatch IoT メトリクス / アラーム | Observability Vol1-2 | IoT Core メトリクス可視化 |
Container本番運用 Vol1 — ECS × Fargate × ECR 基礎
AI/ML Vol3 — SageMaker MLOps本番運用
AWS IoT の本番運用は、エッジでの ML 推論 (Greengrass × AI-ML シリーズ)、デバイス証明書管理 (IoT Core × Security シリーズ)、データパイプライン構築 (IoT Rules × Serverless/Analytics シリーズ) が三位一体で絡み合う。本記事を起点として各シリーズを参照することで、IoT システム全体の設計力が急速に高まる。
本番運用への最初の一歩: §2 で学んだ Fleet Provisioning を実装し、まず10台のデバイスを IoT Core に接続する。次に §3 の Greengrass をエッジデバイス1台に展開し、Component ライフサイクルを体感する。§6 の詰まりポイントを手元に置いておき、詰まったときに見返す——このサイクルが IoT 本番運用の実践力を最も効率よく養う道だ。
IoT Vol2 では本記事で扱えなかったトピックを深掘りする予定だ。
・AWS IoT Events: センサーデータの状態マシン型イベント検知。「温度が80℃を3分間連続超過したらアラート」のような複合条件を Detector Model で実装
・AWS IoT TwinMaker: 工場・ビルのデジタルツイン構築。SiteWise × Grafana × 3D モデルを統合した産業向けデジタルツイン基盤
・AWS IoT FleetWise: 車両・移動体のテレマティクスデータ収集。OBD-II / CAN バスデータを Signal Catalog で体系化し、リアルタイム分析パイプラインへ連携
第19軸目 IoT シリーズは本 Vol1 を起点として、製造・建設・モビリティの各ドメインへと展開していく。