Greengrass Component
greengrass#componentジェネレーターは、既存のPythonまたはTypeScriptプロジェクトにAWS IoT Greengrass v2コンポーネントを追加します。レシピ、エントリーポイント、Pythonコンポーネント用のユニットテスト、およびコアデバイス用にコンポーネントをパッケージ化するNxターゲットを作成します。デフォルトのinfraでは、コンポーネントバージョンを公開し、アーティファクトリポジトリを所有し、デプロイメントを記述する再利用可能なCDKコンストラクトまたはTerraformモジュールも提供します。これらのビルディングブロックを独自のインフラストラクチャコードで構成します。ジェネレーターは、デバイス、フリート、またはデプロイメントを単独で作成することはありません。
ホストプロジェクトは既に存在している必要があります。まずpy#projectまたはts#projectで作成してください。
コンポーネントの生成
Section titled “コンポーネントの生成”このジェネレーターを実行@aws/nx-plugin:greengrass#component
pnpm nx g @aws/nx-plugin:greengrass#component --project=telemetry --name=pulse --language=python yarn nx g @aws/nx-plugin:greengrass#component --project=telemetry --name=pulse --language=python npx nx g @aws/nx-plugin:greengrass#component --project=telemetry --name=pulse --language=python bunx nx g @aws/nx-plugin:greengrass#component --project=telemetry --name=pulse --language=python- インストール Nx Console VSCode Plugin まだインストールしていない場合
- VSCodeでNxコンソールを開く
- クリック
Generate (UI)"Common Nx Commands"セクションで - 検索
@aws/nx-plugin - greengrass#component - 必須パラメータを入力
- project: telemetry
- name: pulse
- language: python
- クリック
Generate
コマンドを組み立てる12
必須
必須
スクリプトやドキュメントではlanguageを明示的に渡してください。省略された場合、ジェネレーターは選択されたプロジェクト内のtsconfig.jsonからtypescriptを、またはpyproject.tomlからpythonを推測します。両方のファイルを持つプロジェクトは--languageを渡す必要があります。どちらのファイルも持たないプロジェクトはサポートされていません。
ipcは両方の言語でデフォルトでfalseです。Greengrass IPCアクセスを追加するには--ipc=trueを、無効のままにするには--ipc=falseを渡してください。
レシピのComponentPublisherはワークスペースのnpmスコープをデフォルトとします。別の値を設定するには--publisherを渡してください。aws-nx-plugin.config.mtsにはGreengrassパブリッシャー設定はありません。
iac: terraformの場合、このジェネレーターを実行する前にterraform#projectでTerraformアプリケーションを作成してください。Greengrassジェネレーターは、そのアプリケーションにawsccプロバイダー設定を追加します。後でTerraformアプリケーションを作成する場合は、プロバイダーを追加できるようにgreengrass#componentを再実行してください。
--projectは非修飾プロジェクト名を受け入れます。生成されたプロジェクトは名前空間修飾されているため、nx runには完全な名前が必要です。Pythonプロジェクトの場合は<scope>.telemetry、TypeScriptプロジェクトの場合は@<scope>/telemetryです。以下の例では、その名前を<project>と記述し、npmスコープがmy-scopeのワークスペースで--name=infraで生成されたインフラストラクチャプロジェクトを@my-scope/infraと記述します。
ハードウェアとオペレーティングシステム
Section titled “ハードウェアとオペレーティングシステム”platformは、ボード名ではなく、コアデバイスのオペレーティングシステムとCPUアーキテクチャを選択します。現在のターゲットは、glibcを使用した64ビットLinuxです。
| デバイス | ジェネレーターターゲット | ステータス |
|---|---|---|
| Linux PC、産業用ゲートウェイ、またはEC2 x86_64インスタンス | linux-amd64 | サポート済み。EC2コアで検証済み |
| 64ビットCPUと64ビットLinuxを搭載したRaspberry Pi、または別のLinux ARM64ゲートウェイ | linux-arm64 | パッケージングはサポート済み。Raspberry Piハードウェアは未検証 |
| 上記の両方を含むフリート | linux-amd64-arm64 | アーキテクチャ固有のマニフェストを持つ1つのコンポーネントバージョン |
| 32ビットLinux / ARMv7を実行しているRaspberry Pi | なし | このジェネレーターではサポートされていませんが、クラシックGreengrassヌクレウスはARMv7をサポートしています |
| Raspberry Pi Pico、ESP32、または別のマイクロコントローラー | なし | コアデバイスのIoTクライアントまたは周辺機器として使用 |
Raspberry Piでは、uname -mとgetconf LONG_BITの両方を確認してください。このパスにはaarch64と64が必要です。32ビットユーザースペースを実行している64ビットプロセッサは、ARM64デプロイメントターゲットではありません。デバイスには、生成されたレシピで指定されたPythonインタープリター、またはTypeScript用のNode.js、およびGreengrassヌクレウスの前提条件も必要です。Python依存関係のベンダリングはmanylinux_2_28をターゲットとしているため、glibc 2.28以降を使用してください。GPIOライブラリとカスタムネイティブ依存関係は、選択されたプラットフォーム用の互換性のあるバイナリを提供する必要があります。ジェネレーターはこれらの周辺機器をプロビジョニングしません。
生成されたPythonレシピは、インタープリターをホストプロジェクトのrequires-pythonフロア(例:python3.14)に固定します。コンポーネントを実行する各コアデバイスにそのインタープリターをインストールしてください。TypeScriptコンポーネントには、コアデバイスにNode.jsが必要です。
linux-amd64-arm64の場合、レシピにはアーキテクチャごとに1つのマニフェストが含まれます。Greengrassは、Platformがコアデバイスと一致する最初のマニフェストを選択するため、各マニフェストのアーティファクトと環境設定をそのアーキテクチャとペアにしてください。
ESP32ファームウェアは、これらのPythonおよびTypeScriptコンポーネントとは別に実行されます。AWS IoT CoreにMQTTメッセージを送信するか、クライアントデバイスサポートを使用してローカルGreengrassコアに接続できます。ローカルルートには、ブローカー、クライアント認証、MQTTブリッジ設定が必要です。このジェネレーターは、これらやファームウェアをスキャフォールドしません。ARMv7、Windows、musl Linux、およびその他のCPUアーキテクチャには、追加のパッケージングとランタイム作業が必要です。レシピのアーキテクチャラベルを変更するだけでは不十分です。
project必須string既存の Python または TypeScript ホストプロジェクト
name必須stringコンポーネント名
platformenumデフォルト:linux-arm64コアデバイスのプラットフォーム。
linux-amd64linux-arm64linux-amd64-arm64infraenumデフォルト:component-versioncomponent-version は再利用可能な Greengrass コンポーネントインフラストラクチャを提供します。none はローカル開発のみをサポートします。
component-versionnoneiacenumデフォルト:inheritIaC プロバイダー。インフラストラクチャが要求された場合にのみ解決されます。
inheritcdkterraformlanguageenumコンポーネントの言語。ホストがサポートする言語マーカーを正確に1つだけ持つ場合のみ省略可能。
typescriptpythoncomponentNamestringレシピの ComponentName。デフォルトでは、ワークスペースの npm スコープとコンポーネント名から派生した逆ドメイン名。
componentVersionstringデフォルト:1.0.0レシピの ComponentVersion。CDK はデプロイ時に NEXT_* を解決します。Terraform は明示的なセマンティックバージョンが必要です。infra=none の場合、NEXT_* はそのまま書き込まれます。
publisherstringレシピの ComponentPublisher。デフォルトではワークスペースの npm スコープ。
ipcbooleanデフォルト:falseGreengrass IPC クライアントを接続するかどうか。両言語ともデフォルトは false。
gdkConfigbooleanデフォルト:falseGDK CLI を手動で使用するための gdk-config.json を生成します。GDK は NEXT_PATCH をサポートしますが、NEXT_MINOR や NEXT_MAJOR はサポートしません。
preferInstallDependenciesbooleanデフォルト:trueジェネレーター実行後に依存関係のインストールを優先するかどうか。
ジェネレーター出力
Section titled “ジェネレーター出力”Directorygreengrass
Directorypulse
- recipe.yaml コンポーネントレシピ
- main.py コンポーネントエントリーポイント
Directorytests
Directorygreengrass
- test_pulse.py パスでmain.pyをロードするユニットテスト
pulse-vendorターゲットは、uv pip install --only-binary :all:を使用して、選択されたデバイスプラットフォーム用にプロジェクトの依存関係をベンダリングします。platform: linux-amd64-arm64の場合、アーキテクチャごとに1回ベンダリングし、レシピはアーキテクチャごとに1つのマニフェストを保持します。
Directorygreengrass
Directorypulse
- recipe.yaml コンポーネントレシピ
Directorysrc
Directorygreengrass
Directorypulse
- main.ts コンポーネントエントリーポイント
プロジェクトのbundleターゲットは、パッケージング前にエントリーポイントをバンドルします。ipc: trueの場合、pulse-vendorターゲットは選択されたアーキテクチャ用のaws-crtネイティブアドオンもステージングします。
レシピ、エントリーポイント、およびPythonの場合はテストは、最初の実行から自分のものです。再実行しても書き換えられることはありません。ターゲット、メタデータ、依存関係宣言はフレームワーク管理であり、実行ごとに収束します。packages/common/scripts/src/greengrass/の下の共有パッケージングスクリプトは一度作成されます。そのディレクトリを削除してジェネレーターを再実行すると、更新されます。
ターゲットはケバブケースのコンポーネント名を使用します。
| ターゲット | 目的 |
|---|---|
<component>-vendor | Python依存関係、またはIPCが有効な場合はTypeScript CRTアドオンをベンダリング |
<component>-artifact | dist/<project-root>/greengrass/<component>/greengrass-build/の下に解決されたレシピとデプロイ可能なアーカイブを書き込み |
<component>-deploy-local | コアデバイス上でgreengrass-cliを通じてローカルデプロイメントを作成し、安定したコンポーネント状態を待機 |
<component>-logs | コアデバイス上のコンポーネントログをテール |
<component>-artifactはホストプロジェクトのbuildおよびassembleターゲットの依存関係であるため、通常のビルドでアーティファクトが生成されます。
インフラストラクチャ
Section titled “インフラストラクチャ”このジェネレーターは、選択した iac に基づいてインフラストラクチャをコードとして提供するため、関連する CDK コンストラクトまたは Terraform モジュールを含む packages/common にプロジェクトを作成します。
共通のインフラストラクチャコードプロジェクトは、次のように構成されています:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ プロジェクト/ジェネレーター固有のインフラストラクチャ用のコンストラクト
- …
Directorycore/
app内のコンストラクトによって再利用される汎用コンストラクト- …
- index.ts
appからコンストラクトをエクスポートするエントリーポイント
- project.json プロジェクトのビルドターゲットと設定
Directorypackages/common/terraform
Directorysrc
Directoryapp/ プロジェクト/ジェネレーター固有のインフラストラクチャ用の Terraform モジュール
- …
Directorycore/
app内のモジュールによって再利用される汎用モジュール- …
- project.json プロジェクトのビルドターゲットと設定
デフォルトのinfra: component-versionは、欠落している場合に以下のGreengrassコアファイルと、コンポーネントごとに1つのアプリラッパーを追加します。既存のコアファイルは保持されるため、ローカル編集は後の実行でも残ります。デバイス、シンググループ、またはデプロイメントは作成しません。
Directorypackages/common/constructs/src
Directorycore/greengrass
- artifact-bucket.ts
GreengrassArtifactBucket:grantReadToを持つ保持された、バージョン管理された、TLSのみのリポジトリ - component-version.ts
GreengrassComponentVersion: アーティファクトをアップロードしてバージョンを公開 - deployment.ts
GreengrassDeployment: デプロイメント、オプションのシンググループ、およびaddComponent - next-version.ts
NEXT_PATCH、NEXT_MINOR、NEXT_MAJORのデプロイ時リゾルバー - recipe.ts シンス時のレシピ読み取りとアーティファクトURI置換
- artifact-bucket.ts
Directoryapp/greengrass
- pulse.ts
Pulse、このコンポーネントのビルド出力に固定されたGreengrassComponentVersion
- pulse.ts
共有コンストラクトプロジェクトのbuildおよびassembleターゲットはホストプロジェクトに依存しているため、インフラストラクチャのビルドまたはデプロイは常に新しいアーティファクトを読み取ります。
Directorypackages/common/terraform/src
Directorycore/greengrass
- artifact-bucket オプションのトークン交換ロール付与を持つ保持された、バージョン管理された、TLSのみのリポジトリ
- component-version
awscc_greengrassv2_component_versionを通じてアーティファクトをアップロードしてバージョンを公開 - deployment オプションの
aws_iot_thing_groupを持つawscc_greengrassv2_deployment
Directoryapp/greengrass-component
- pulse このコンポーネントのビルドパスと
bucket_name入力でcomponent-versionをラップするモジュール
- pulse このコンポーネントのビルドパスと
Greengrassリソースはhashicorp/awsプロバイダーには存在しません。モジュールはhashicorp/awsccを使用します。iac: terraformが選択されている場合、Greengrassジェネレーターは、欠落している場合にTerraformアプリケーションルートにawscc必須プロバイダーとprovider "awscc" { region = var.aws_region }を追加します。既存のプロバイダー設定は保持されます。
アーキテクチャ
Section titled “アーキテクチャ”コンポーネントバージョンは、ビルドされたアーティファクトを明示的に所有されたリポジトリに公開します。スタックまたはルートモジュールは、コアデバイスのトークン交換ロールに読み取りアクセスを付与し、1つ以上のデプロイメントにバージョンを追加します。デフォルトの読み取り付与は、ワークスペースのコンポーネント名前空間にスコープされています。ロールのデバイスがそれらのコンポーネントのサブセットのみを必要とする場合は、さらに絞り込んでください。
infra: noneは、レシピ、エントリーポイント、Pythonテスト、ターゲット、および共有スクリプトのみを作成します。インフラストラクチャプロジェクトや共有コンストラクトは作成または変更されません。後でinfra: component-versionで再実行してインフラストラクチャを追加できます。既にインフラストラクチャを所有しているコンポーネントをnoneに戻すことはできません。
ローカルでのビルドと実行
Section titled “ローカルでのビルドと実行”開発マシンでアーティファクトをビルドします。
pnpm nx run <project>:pulse-artifactyarn nx run <project>:pulse-artifactnpx nx run <project>:pulse-artifactbunx nx run <project>:pulse-artifactdist/<project-root>/greengrass/pulse/greengrass-build/の下の出力には、解決されたレシピを含むrecipes/と、アーカイブを含むartifacts/<ComponentName>/<ComponentVersion>/があります。Pythonコンポーネントは、マニフェストごとに1つのアーカイブをビルドし、両方のアーキテクチャをターゲットとする場合は<component>-<architecture>.zipという名前になります。TypeScriptコンポーネントは、すべてのマニフェストが共有する1つのアーカイブをビルドします。ipc: trueの場合、各アーキテクチャ用のaws-crtアドオンを保持し、各マニフェストのSetenvが独自のものを選択します。レシピのアーティファクトURIのBUCKET_NAME、COMPONENT_NAME、COMPONENT_VERSIONプレースホルダーは公開時に置換され、アーカイブのベース名はRunステップが解凍するものと同じである必要があります。
次の2つのターゲットは、通常のワークステーションではなく、クラシックGreengrassヌクレウスとgreengrass-cliがインストールされたマシンで実行されます。
pnpm nx run <project>:pulse-deploy-localpnpm nx run <project>:pulse-logsyarn nx run <project>:pulse-deploy-localyarn nx run <project>:pulse-logsnpx nx run <project>:pulse-deploy-localnpx nx run <project>:pulse-logsbunx nx run <project>:pulse-deploy-localbunx nx run <project>:pulse-logsGREENGRASS_ROOTはデフォルトで/greengrass/v2です。pulse-deploy-localはローカルデプロイメントを送信し、コンポーネントのライフサイクル状態をポーリングし、3回のチェックでRUNNINGまたはFINISHEDのままでない限り、ゼロ以外で終了します。ローカルデプロイメントは、デバイス上でそのバージョンを固定し、異なるバージョンの後のクラウドデプロイメントと競合します。ローカルおよびクラウドデプロイメントを参照してください。
デプロイメント構成は、インフラストラクチャプロジェクトに存在します。通常のフローは、1つのリポジトリ、1つの読み取り付与、コンポーネントごとに1つのアプリラッパー、ターゲットごとに1つのデプロイメントです。既存のシンググループまたはシングに1つのデプロイメントを使用し、そのtargetArnを設定します。別のターゲット用に別のデプロイメントを作成します。
ワークスペースにCDKアプリケーションがない場合は作成します。
このジェネレーターを実行@aws/nx-plugin:ts#infra
pnpm nx g @aws/nx-plugin:ts#infra --name=infra yarn nx g @aws/nx-plugin:ts#infra --name=infra npx nx g @aws/nx-plugin:ts#infra --name=infra bunx nx g @aws/nx-plugin:ts#infra --name=infra- インストール Nx Console VSCode Plugin まだインストールしていない場合
- VSCodeでNxコンソールを開く
- クリック
Generate (UI)"Common Nx Commands"セクションで - 検索
@aws/nx-plugin - ts#infra - 必須パラメータを入力
- name: infra
- クリック
Generate
コマンドを組み立てる5
必須
トークン交換ロールとターゲットシンググループは、アカウントに既に存在します。ロールはコアデバイスが引き受けるものであり、グループはそれらが登録されている場所です。スタックは、CloudFormationパラメーターを通じて両方をインポートします。
import { GreengrassArtifactBucket, GreengrassDeployment, Pulse,} from '@my-scope/common-constructs';import { CfnParameter, Stack, type StackProps } from 'aws-cdk-lib';import { Role } from 'aws-cdk-lib/aws-iam';import type { Construct } from 'constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props);
const tokenExchangeRoleArn = new CfnParameter( this, 'TokenExchangeRoleArn', { type: 'String' }, ); const thingGroupArn = new CfnParameter(this, 'ThingGroupArn', { type: 'String', });
// One explicitly owned repository, and the grant the devices need. const artifacts = new GreengrassArtifactBucket(this, 'Artifacts'); const tokenExchangeRole = Role.fromRoleArn( this, 'TokenExchangeRole', tokenExchangeRoleArn.valueAsString, ); artifacts.grantReadTo(tokenExchangeRole);
// The generated wrapper takes the repository construct itself. const pulse = new Pulse(this, 'Pulse', { bucket: artifacts });
// addComponent records the resolved version and orders the deployment // resource after the component version resource. const fleet = new GreengrassDeployment(this, 'Fleet', { targetArn: thingGroupArn.valueAsString, }); fleet.addComponent(pulse); }}プロジェクト参照を同期し、アカウントとリージョンを一度ブートストラップしてから、デプロイします。deployターゲットは、^assembleの後にインフラストラクチャプロジェクトでcdk deploy --require-approval=neverを実行し、最初にコンポーネントアーティファクトを再ビルドします。生成されたmain.tsは、すべてのスタックをプロジェクトにちなんで名付けられたステージに配置します。@my-scope/infraの場合はmy-scope-infra-sandboxなので、cdk deployにはそのステージのセレクターが必要です。packages/infra/src/main.tsからステージ名を取得し、パラメーター値とともに--の後に/**を付けて渡します。
AWS_PROFILE=<profile> AWS_REGION=<region> pnpm nx syncpnpm nx run @my-scope/infra:bootstrappnpm nx run @my-scope/infra:deploy -- 'my-scope-infra-sandbox/**' --parameters TokenExchangeRoleArn=<role-arn> --parameters ThingGroupArn=<thing-group-arn>AWS_PROFILE=<profile> AWS_REGION=<region> yarn nx syncyarn nx run @my-scope/infra:bootstrapyarn nx run @my-scope/infra:deploy -- 'my-scope-infra-sandbox/**' --parameters TokenExchangeRoleArn=<role-arn> --parameters ThingGroupArn=<thing-group-arn>AWS_PROFILE=<profile> AWS_REGION=<region> npx nx syncnpx nx run @my-scope/infra:bootstrapnpx nx run @my-scope/infra:deploy -- 'my-scope-infra-sandbox/**' --parameters TokenExchangeRoleArn=<role-arn> --parameters ThingGroupArn=<thing-group-arn>AWS_PROFILE=<profile> AWS_REGION=<region> bunx nx syncbunx nx run @my-scope/infra:bootstrapbunx nx run @my-scope/infra:deploy -- 'my-scope-infra-sandbox/**' --parameters TokenExchangeRoleArn=<role-arn> --parameters ThingGroupArn=<thing-group-arn>deployは完全な安定化を待ち、置換更新を受け入れます。deploy-sandboxはエクスプレスモードを使用し、--rollbackを渡さない限り置換更新を拒否します。定期的な改訂にはdeployを使用するか、deploy-sandboxを使用する場合は--rollbackを渡してください。
fleet.addComponent(pulse)は必須であり、装飾的なものではありません。固定のComponentVersionでは、デプロイメントのコンポーネントマップはリテラル文字列を保持するため、CloudFormationはデプロイメントとコンポーネントバージョンの間に依存関係を認識せず、それらを並行して作成します。その後、IoTジョブはバージョンが存在する前にデバイスに到達し、FAILED_NO_STATE_CHANGEで失敗します。NEXT_PATCHでは、マップはコンポーネントバージョンリソースのComponentVersion属性を保持し、生のNEXT_*文字列がデプロイメントに到達すると、addComponentを指定したメッセージでシンスが失敗します。
1つのフリートに2つのコンポーネント
Section titled “1つのフリートに2つのコンポーネント”同じまたは別のプロジェクトに2番目のコンポーネントを生成し、両方を1つのデプロイメントに追加します。オーバーライドは、そのコンポーネントのエントリの名前付きトップレベルフィールドを置き換えます。バージョンは常にコンストラクトから取得されます。
const pulse = new Pulse(this, 'Pulse', { bucket: artifacts });const uploader = new Uploader(this, 'Uploader', { bucket: artifacts });
const cameras = new GreengrassDeployment(this, 'Cameras', { thingGroupName: 'cameras',});cameras.addComponent(pulse);cameras.addComponent(uploader, { configurationUpdate: { merge: { uploadIntervalSeconds: 60 } },});thingGroupNameは新しいAWS::IoT::ThingGroupを作成します。デバイスを登録しません。デバイスは、プロビジョニングプロセスを通じてグループに参加します。既に存在するグループまたはシングには、targetArnまたはthingNameを使用してください。
2つのフリートに1つのコンポーネント
Section titled “2つのフリートに1つのコンポーネント”同じコンストラクトを2つのデプロイメントに登録します。各デプロイメントは独自の設定を保持します。
new GreengrassDeployment(this, 'WestFleet', { thingGroupName: 'west-fleet',}).addComponent(pulse);
new GreengrassDeployment(this, 'EastFleet', { thingGroupName: 'east-fleet',}).addComponent(pulse, { configurationUpdate: { merge: { sampleIntervalSeconds: 60 } },});同じコンストラクトを1つのデプロイメントに2回追加することは、2回目の呼び出しがオーバーライドを提供しない限り、何もしません。オーバーライドはエントリを更新します。同じコンポーネント名で異なるコンストラクトを1つのデプロイメントに追加すると、構築時に失敗します。
パブリックコンポーネントと生のエントリ
Section titled “パブリックコンポーネントと生のエントリ”このワークスペースでビルドしなかったコンポーネントは、componentsマップに入ります。公開されたパブリックコンポーネントは、既に存在するため依存関係を必要としません。同じスタックで作成されたバージョンの生のエントリ(例:手書きのCfnComponentVersion)には、addComponentから取得する順序エッジが必要です。
import { CfnComponentVersion } from 'aws-cdk-lib/aws-greengrassv2';
const fleet = new GreengrassDeployment(this, 'Fleet', { targetArn: thingGroupArn.valueAsString, components: { // Published by AWS; pick a version from // `aws greengrassv2 list-component-versions`. 'aws.greengrass.LogManager': { componentVersion: '2.3.8', configurationUpdate: { merge: { logsUploaderConfiguration: { systemLogsConfiguration: { uploadToCloudWatch: 'true' }, }, }, }, }, // Created in this stack, so the deployment must wait for it. 'com.example.Handwritten': { componentVersion: '1.2.0' }, },});fleet.addComponent(pulse);
const handwritten = new CfnComponentVersion(this, 'Handwritten', { inlineRecipe: handwrittenRecipe,});fleet.deployment.node.addDependency(handwritten);configurationUpdate.mergeはここではプレーンオブジェクトです。コンストラクトは、CloudFormationが期待するJSON文字列にシリアル化します。
既存のリポジトリのインポート
Section titled “既存のリポジトリのインポート”1つのスタックがリポジトリを所有します。他のすべてのスタックは名前でインポートし、所有スタックに独自の付与を追加するか、トークン交換ロール自体に同等のs3:GetObjectポリシーをアタッチします。
const artifacts = new GreengrassArtifactBucket(this, 'Artifacts', { existingBucketName: 'central-greengrass-artifacts',});const pulse = new Pulse(this, 'Pulse', { bucket: artifacts });インポートされたバケットは、独自の暗号化、バージョン管理、アクセス設定を保持します。リゾルバーは、NEXT_*バージョンのコンテンツIDにバケット名を含めるため、コンポーネントを別のリポジトリに移動すると、変更されていないバイトに対して新しいバージョンが割り当てられます。
greengrass#componentを実行する前に作成したTerraformアプリケーションを使用します。代わりにここで作成する場合は、awsccプロバイダー設定を追加できるように、続行する前にGreengrassコンポーネントジェネレーターを再実行してください。
このジェネレーターを実行@aws/nx-plugin:terraform#project
pnpm nx g @aws/nx-plugin:terraform#project --name=infra --type=application yarn nx g @aws/nx-plugin:terraform#project --name=infra --type=application npx nx g @aws/nx-plugin:terraform#project --name=infra --type=application bunx nx g @aws/nx-plugin:terraform#project --name=infra --type=application- インストール Nx Console VSCode Plugin まだインストールしていない場合
- VSCodeでNxコンソールを開く
- クリック
Generate (UI)"Common Nx Commands"セクションで - 検索
@aws/nx-plugin - terraform#project - 必須パラメータを入力
- name: infra
- type: application
- クリック
Generate
コマンドを組み立てる5
必須
トークン交換ロールを入力として宣言し、提供されたplanターゲットが-var-file=env/dev.tfvarsで読み取る環境ファイルにその値を設定します。ロールはコアデバイスが引き受けるものであり、この設定が実行される前に存在します。
variable "token_exchange_role_arn" { description = "ARN of the IAM role the core devices assume" type = string}
variable "thing_group_arn" { description = "ARN of the existing thing group to deploy to" type = string}environment = "dev"token_exchange_role_arn = "arn:aws:iam::123456789012:role/GreengrassCoreTokenExchangeRole"thing_group_arn = "arn:aws:iot:us-east-1:123456789012:thinggroup/pumps"コアデプロイメントモジュールのcomponentsマップで、コンポーネントモジュールの出力を直接参照します。component_version出力は、コンポーネントバージョンリソースへのdepends_onを保持するため、デプロイメントは、その番号がプラン時に既知であっても、バージョンが存在するまで待機します。このフローには、モジュールレベルのdepends_onは必要ありません。
module "artifacts" { source = "../../common/terraform/src/core/greengrass/artifact-bucket" token_exchange_role_arn = var.token_exchange_role_arn}
module "pulse" { source = "../../common/terraform/src/app/greengrass-component/pulse" bucket_name = module.artifacts.bucket_name}
module "fleet" { source = "../../common/terraform/src/core/greengrass/deployment" target_arn = var.thing_group_arn components = { (module.pulse.component_name) = { component_version = module.pulse.component_version } }}リモート状態を一度ブートストラップしてから、プランと適用を行います。planはinit、validate、assembleに依存し、最初にコンポーネントアーティファクトを再ビルドし、applyはplanが書き込んだプランファイルを適用します。
AWS_PROFILE=<profile> AWS_REGION=<region> pnpm nx run @my-scope/infra:bootstrappnpm nx run @my-scope/infra:planpnpm nx run @my-scope/infra:applyAWS_PROFILE=<profile> AWS_REGION=<region> yarn nx run @my-scope/infra:bootstrapyarn nx run @my-scope/infra:planyarn nx run @my-scope/infra:applyAWS_PROFILE=<profile> AWS_REGION=<region> npx nx run @my-scope/infra:bootstrapnpx nx run @my-scope/infra:plannpx nx run @my-scope/infra:applyAWS_PROFILE=<profile> AWS_REGION=<region> bunx nx run @my-scope/infra:bootstrapbunx nx run @my-scope/infra:planbunx nx run @my-scope/infra:applything_group_nameは新しいaws_iot_thing_groupを作成します。デバイスを登録しません。既に存在するグループまたはシングにはtarget_arnを、1つのシングにはthing_nameを使用してください。リテラルのtarget_arnは、プラン時に現在のパーティション、アカウント、リージョンに対してチェックされます。
Terraformは、コンポーネントレシピで明示的なセマンティックバージョンを使用します。公開されたバージョンは不変であるため、変更されたコンポーネントごとに新しいバージョンを選択してください。Terraformは、プラグインのNEXT_*センチネルを解決したり、Greengrass APIを呼び出してバージョンを選択したりしません。そのawsccプロバイダーは、Terraform用に設定された認証情報とリージョンを使用します。
planターゲットはassembleを実行し、計画されたアーティファクトダイジェストを記録します。planとapplyの間でレシピとビルド出力を変更しないでください。いずれかが変更された場合は、planを再実行し、公開されたバイトが計画されたバージョンとオブジェクトキーと一致するように新しいプランを適用してください。
段階的ロールアウトと保持されたバージョン
Section titled “段階的ロールアウトと保持されたバージョン”レシピバージョンをバンプすると、Terraformの管理されたコンポーネントバージョンが置き換えられ、Greengrassレジストリから置き換え前のバージョンが削除されます。変更されたアーティファクトコンテンツも、そのS3キーを置き換え、置き換え前のオブジェクトを削除します。変更されていないアーティファクトバイトを持つバージョンまたはレシピの変更は、同じキーを再利用できます。削除されたバージョンをまだ参照しているデプロイメントは、以前のバージョンに残された2番目のシンググループを含めて失敗します。create_before_destroyはリソースの作成を順序付けます。古いバージョンを保持したり、すべてのデバイスがロールアウトを完了するのを待ったりしません。
段階的ロールアウトの前に、コンポーネントバージョンとS3オブジェクトリソースを含む公開モジュール全体を保持します。バージョンのみを保持すると、そのアーティファクトは削除の対象になります。prevent_destroyは代替ではありません。置き換え前のバージョンを保持する代わりに、バージョンの置換を拒否します。
まず、既存のmodule "pulse"ブロックを削除し、その出力へのすべてのデプロイメント参照を現在公開されている名前とバージョンに置き換えます。共有artifactsモジュール、デプロイメントアドレス、その他のコンポーネント、フリート設定を保持します。たとえば、これらの2つの既存のグループは、パブリッシャーがTerraform管理を離れる間、1.0.0のままです。
removed { from = module.pulse lifecycle { destroy = false }}
module "fleet" { source = "../../common/terraform/src/core/greengrass/deployment" target_arn = var.thing_group_arn components = { "com.my-scope.Pulse" = { component_version = "1.0.0" } }}
module "stable_fleet" { source = "../../common/terraform/src/core/greengrass/deployment" target_arn = "arn:aws:iot:us-east-1:123456789012:thinggroup/stable" components = { "com.my-scope.Pulse" = { component_version = "1.0.0" } }}実際のコンポーネント名、バージョン、既存のグループARNを使用してください。この保持ステップを個別にプランして適用します。プランは、パブリッシャーのバージョンとオブジェクトリソースを破壊したり、フリートを改訂したりせずに忘れる必要があります。
AWS_PROFILE=<profile> AWS_REGION=<region> pnpm nx run @my-scope/infra:planpnpm nx run @my-scope/infra:applyAWS_PROFILE=<profile> AWS_REGION=<region> yarn nx run @my-scope/infra:planyarn nx run @my-scope/infra:applyAWS_PROFILE=<profile> AWS_REGION=<region> npx nx run @my-scope/infra:plannpx nx run @my-scope/infra:applyAWS_PROFILE=<profile> AWS_REGION=<region> bunx nx run @my-scope/infra:planbunx nx run @my-scope/infra:applyその適用後にのみ、ユーザー所有のレシピのComponentVersionを1.0.1などの新しい明示的なバージョンに変更します。新しいモジュールアドレスの下にパブリッシャーを追加し、パイロットフリートを進めます。上記の安定したフリートのリテラル1.0.0エントリを保持します。
module "pulse_v2" { source = "../../common/terraform/src/app/greengrass-component/pulse" bucket_name = module.artifacts.bucket_name}
module "fleet" { source = "../../common/terraform/src/core/greengrass/deployment" target_arn = var.thing_group_arn components = { (module.pulse_v2.component_name) = { component_version = module.pulse_v2.component_version } }}再度プランしてアーティファクトを再ビルドし、新しいバージョンを公開してから適用します。パイロットデバイスを確認した後、stable_fleetを同じパブリッシャー出力に更新し、そのプロモーションをプラン/適用します。生成されたラッパーは現在のビルド出力を読み取ります。別のインスタンスを追加しても、古いビルドは保持されません。
グループまたはロールバックがそのバージョンを必要とする可能性がある間にpulse_v2を置き換えたり削除したりする前に、個別の保持ステップを繰り返します。変更されていないバイトは、保持されたバージョン間でS3キーを共有できるため、後のパブリッシャーは、古いバージョンがまだ参照しているオブジェクトを管理できます。保持されたバージョンとそのアーティファクトキーのインベントリを保持します。保持されたバージョン、デプロイメント、またはロールバックが必要としない場合にのみ、キーを削除してください。リソースを忘れると、それらは利用可能なままですが、クリーンアップはあなたに転送されます。
1つのフリートに2つのコンポーネント
Section titled “1つのフリートに2つのコンポーネント”module "uploader" { source = "../../common/terraform/src/app/greengrass-component/uploader" bucket_name = module.artifacts.bucket_name}
module "cameras" { source = "../../common/terraform/src/core/greengrass/deployment" thing_group_name = "cameras" components = { (module.pulse.component_name) = { component_version = module.pulse.component_version } (module.uploader.component_name) = { component_version = module.uploader.component_version configuration_update = { merge = jsonencode({ uploadIntervalSeconds = 60 }) } } }}configuration_update.mergeは既にJSON文字列である必要があるため、jsonencodeでラップします。これは、オブジェクトを受け取るCDKコンストラクトとは異なります。
2つのフリートに1つのコンポーネント
Section titled “2つのフリートに1つのコンポーネント”2つのデプロイメントモジュールが同じコンポーネント出力を参照します。
module "west_fleet" { source = "../../common/terraform/src/core/greengrass/deployment" thing_group_name = "west-fleet" components = { (module.pulse.component_name) = { component_version = module.pulse.component_version } }}
module "east_fleet" { source = "../../common/terraform/src/core/greengrass/deployment" thing_group_name = "east-fleet" components = { (module.pulse.component_name) = { component_version = module.pulse.component_version configuration_update = { merge = jsonencode({ sampleIntervalSeconds = 60 }) } } }}パブリックコンポーネントとリテラルバージョン
Section titled “パブリックコンポーネントとリテラルバージョン”公開されたパブリックコンポーネントはリテラルエントリであり、依存関係を必要としません。同じ適用で作成されたリソースのリテラルバージョン(例:手書きのawscc_greengrassv2_component_version)は、モジュールレベルのdepends_onの1つのケースです。depends_onを使用すると、Terraformは依存関係が存在するまでデプロイメントモジュールのIDデータソースを読み取ることができないため、そのターゲットチェックはプランから適用に延期されます。デプロイメントが作成される前に失敗します。
module "fleet" { source = "../../common/terraform/src/core/greengrass/deployment" target_arn = var.thing_group_arn components = { "aws.greengrass.LogManager" = { component_version = "2.3.8" configuration_update = { merge = jsonencode({ logsUploaderConfiguration = { systemLogsConfiguration = { uploadToCloudWatch = "true" } } }) } } "com.example.Handwritten" = { component_version = "1.2.0" } (module.pulse.component_name) = { component_version = module.pulse.component_version } }
# Only for the literal version created by awscc_greengrassv2_component_version.handwritten. depends_on = [awscc_greengrassv2_component_version.handwritten]}既存のリポジトリのインポート
Section titled “既存のリポジトリのインポート”artifact-bucketモジュールにexisting_bucket_nameを設定します。その後、モジュールはバケットの設定もポリシーも管理しないため、バケットを所有する設定でアーティファクトプレフィックスに対してトークン交換ロールにs3:GetObjectを付与します。
module "artifacts" { source = "../../common/terraform/src/core/greengrass/artifact-bucket" existing_bucket_name = "central-greengrass-artifacts"}デバイスでの確認
Section titled “デバイスでの確認”完了したスタック更新または適用は、デプロイメントリソースが存在することを証明します。デプロイメントとそのIoTジョブの両方がSUCCEEDEDを報告する一方で、デバイス上のコンポーネントがBROKENである可能性があります。すべてのデプロイメント後にデバイスとコンポーネントの状態を確認してください。
aws --profile <profile> --region <region> greengrassv2 get-core-device \ --core-device-thing-name <thing-name> --query statusaws --profile <profile> --region <region> greengrassv2 list-installed-components \ --core-device-thing-name <thing-name>デバイスが壊れた状態を報告する場合は、<component>-logsを使用してプロセスログを検査してください。
レシピとIPC
Section titled “レシピとIPC”デフォルトのipc: falseでは、main.pyは30秒ごとに1行をログに記録し、レシピにはIPCアクセス制御がありません。ipc: trueでは、GreengrassCoreIPCClientV2を通じて30秒ごとにコンポーネント自身のローカルトピックにハートビートを公開します。
client.publish_to_topic( topic=TOPIC, publish_message=PublishMessage(json_message=JsonMessage(message={"sequence": sequence})),)レシピは、aws.greengrass.ipc.pubsubの下で<ComponentName>/heartbeatに対してaws.greengrass#PublishToTopicを付与します。ローカルpub/subは、AWS IoT Coreではなく、同じコアデバイス上の他のコンポーネントに到達します。AWS IoT Coreに公開するには、publish_to_iot_coreを呼び出し、レシピのaws.greengrass.ipc.mqttproxyの下でaws.greengrass#PublishToIoTCoreを付与し、デバイスのIoTポリシーで正確なトピックに対してiot:Publishを付与します。
デフォルトのipc: falseでは、main.tsは30秒ごとに1行をログに記録し、レシピにはIPCアクセス制御がありません。ipc: trueでは、AWS IoT Device SDKのGreengrass IPCクライアントを通じてコンポーネント自身のローカルトピックにハートビートを公開し、pulse-vendorは選択されたアーキテクチャ用のaws-crtネイティブアドオンをステージングします。AWS IoT Coreへの公開には、同じクライアントのpublishToIoTCore操作、レシピのaws.greengrass.ipc.mqttproxy認証、およびデバイスのIoTポリシーのiot:Publishを使用します。
レシピのアクセス制御は、デバイス上のヌクレウスによって強制されます。SDK単独に依存しても何も承認されないため、コンポーネントが成長するにつれてoperationsとresourcesを拡大してください。
生成されたレシピは、クラシックaws.greengrass.Nucleusをターゲットとしています。Nucleus Liteは、IPC操作のサブセットを実装し、プラグインコンポーネントを実行せず、v2.15でのみコンテナサポートを獲得しました。フリートが実行するヌクレウスに対してレシピを確認してください。ジェネレーターはヌクレウスの機能を検出しません。
Ubuntu 25.10以降では、sudo-rsがIPC環境が失われるため、Greengrass Nucleus 2.18.3でIPCコンポーネントの起動を妨げる可能性があります。ジェネレーターは、ホストのsudoセキュリティ設定を変更しません。IPCが必要な場合は、クラシックsudo動作を提供するデバイスセットアップを使用してください。
自動バージョニング
Section titled “自動バージョニング”CDKデプロイメントの場合、recipe.yamlのComponentVersionをNEXT_PATCH、NEXT_MINOR、またはNEXT_MAJORに設定して、プラグインのリゾルバーにアカウントとリージョンで既に公開されている最高の厳密なセマンティックバージョンからバージョンを割り当てるように依頼します。
| センチネル | 最高公開1.4.2が次になる | まだ何も公開されていない |
|---|---|---|
NEXT_PATCH | 1.4.3 | 1.0.0 |
NEXT_MINOR | 1.5.0 | 1.0.0 |
NEXT_MAJOR | 2.0.0 | 1.0.0 |
最初のバージョンは1.0.0です。リゾルバーは、コンテンツタグが一致し、バージョンがデプロイ可能な場合、最高公開バージョンを再利用します。それ以外の場合は、センチネルによって選択された次のバージョンを公開します。タグは、バージョン行のないレシピ、アーティファクトバイト、およびアーティファクトバケット名をカバーします。したがって、変更されていないコンテンツはバージョンを再利用し、コンテンツまたはバケットを変更すると新しいバージョンが公開されます。ジェネレーターはrecipe.yamlを書き換えることはありません。
NEXT_*はNxプラグインの規約であり、Greengrassバージョンではありません。CDKはデプロイメント中にセンチネルを解決し、<project>:pulse-deploy-localはデバイスで利用可能なバージョンに対して解決します。GDKはgdk-config.jsonの設定としてNEXT_PATCHを使用し、レシピフィールドとしては使用せず、NEXT_MINORまたはNEXT_MAJORをサポートしていません。プラグインはGDKを呼び出しません。
Terraformには明示的なセマンティックバージョンが必要です。Greengrassバージョンは不変であるため、変更されたアーティファクトごとに新しいComponentVersionが必要です。TerraformはNEXT_*を解決しません。
CDKリゾルバーは、生成されたLambda実行ロールの下でCloudFormationデプロイメント中に実行され、スタックのコンポーネント名にスコープされます。同じコンポーネントに対して同時公開を実行しないでください。デプロイメントが同じ次のバージョンを選択し、1つの公開が失敗する可能性があります。
アーティファクトストレージと保持
Section titled “アーティファクトストレージと保持”アカウントとリージョンごとに1つのアーティファクトリポジトリを使用し、1つのスタックまたはルートモジュールが所有します。CDKのexistingBucketNameまたはTerraformのexisting_bucket_nameを使用して、他の場所でインポートします。生成されたバケットは、バージョン管理され、SSE-S3で暗号化され、プライベートであり、TLSを必要とします。GreengrassアーティファクトはCDKアセットではありません。cdk gcは、コンポーネントバージョンがまだ必要とするアセットを削除できます。
両方のIaCパスは同じS3オブジェクトキーレイアウトを使用します。<ComponentName>/<first 32 hex characters of sha256>/<file>。ダイジェストは、ソートされたアーティファクト名とその完全なSHA-256ハッシュをハッシュし、1つまたは複数のアーティファクトに同じ式を使用します。キープレフィックスのみが短縮されます。アーティファクトダイジェストと自動バージョンIDは完全なハッシュを保持します。CDKのバケットデプロイメントタグは、プレフィックスを102文字に制限し、コンポーネント名に68文字を残します。ジェネレーターは、CDKインフラストラクチャが選択されたときにその制限をチェックし、シンセシスはレシピへの編集をチェックします。Terraformのオブジェクトアップロードには、このCDK制限はありません。
デプロイメントまたはロールバックがコンポーネントバージョンを必要とする可能性がある間、公開されたアーティファクトを利用可能に保ちます。CDKは、デフォルトで置き換えられたコンポーネントバージョンとそのアップロードを保持します。Terraformは、置き換えられたバージョンと置き換え前のオブジェクトキーを削除します。複数のグループで使用されるバージョンをバンプする前に、段階的ロールアウトと保持されたバージョンを参照してください。レジストリバージョンを削除しても、デバイスで既に実行されているコンポーネントはアンインストールされません。Terraformのリポジトリはprevent_destroyを設定します。そのアーティファクトが不要になった後の意図的な解体のためにのみ、そのリテラルライフサイクル設定を削除してください。
デフォルトのトークン交換ロール付与は、ワークスペースのコンポーネント名前空間でs3:GetObjectを許可します。より狭い付与の場合は、CDKでkeyPrefixを、Terraformでtoken_exchange_key_prefixを設定します。インポートされたバケットは独自のポリシーを保持するため、バケットまたはロールが所有されている場所で付与を管理します。
デプロイメントリビジョン
Section titled “デプロイメントリビジョン”コンポーネントバージョンまたはデプロイメント設定を変更すると、デプロイメントリソースが置き換えられます。CloudFormationは、1つのスタック操作で最大10個のデプロイメントリソースを追加または削除できます。大規模なロールアウトをバッチに分割します。置換には通常のdeployターゲットを使用してください。deploy-sandboxはCloudFormationエクスプレスモードを使用し、置換更新には--rollbackが必要です。
デプロイメントリソースを削除すると、クラウド管理状態が削除されますが、デバイスからコンポーネントはアンインストールされません。まず、コンポーネントを省略したリビジョンをデプロイし、list-installed-componentsから消えるのを待ってから、そのIaCリソースを削除してください。
ローカルおよびクラウドデプロイメント
Section titled “ローカルおよびクラウドデプロイメント”<component>-deploy-localからのローカルデプロイメントは、そのデバイス上でコンポーネントバージョンを固定します。異なるバージョンを要求するクラウドデプロイメントは、ピンを満たすことができません。クラウドからそのデバイスを更新する前に、ローカルデプロイメントを削除してください。
sudo /greengrass/v2/bin/greengrass-cli deployment create --remove com.example.Pulse開発デバイスにはローカルデプロイメントを、フリートターゲットにはクラウドデプロイメントを使用してください。
トラブルシューティングとサービス制限
Section titled “トラブルシューティングとサービス制限”クラウドデプロイメント後、Greengrassデプロイメントステータスとコンポーネントのデバイス状態の両方を確認してください。
aws --profile <profile> --region <region> greengrassv2 get-core-device \ --core-device-thing-name <thing-name> --query statusaws --profile <profile> --region <region> greengrassv2 list-installed-components \ --core-device-thing-name <thing-name>ジョブがSUCCEEDEDを報告する一方で、コンポーネントがBROKENである可能性があります。<component>-logsを使用してプロセスログを検査してください。Ubuntu 25.10以降のIPCコンポーネントも、Nucleus 2.18.3でsudo-rsの下で失敗する可能性があります。ジェネレーターは、ホストのセキュリティ設定をそのままにします。
Greengrassは、リージョンごとに1つのコンポーネントを5,000バージョンに制限し、CreateComponentVersionをリージョンごとに1秒あたり1リクエストに制限します。レシピは16 KBに制限され、デプロイメントドキュメントはシンググループの場合は31 KB、単一のシングの場合は7 KBに制限されます。ハートビートとして新しいバージョンを使用することを避け、大規模なデプロイメントを小さなバッチに分割してください。