Greengrass Component
greengrass#component 생성기는 기존 Python 또는 TypeScript 프로젝트에 AWS IoT Greengrass v2 컴포넌트를 추가합니다. 레시피, 진입점, Python 컴포넌트용 단위 테스트, 그리고 코어 디바이스용 컴포넌트를 패키징하는 Nx 타겟을 생성합니다. 기본 infra를 사용하면 컴포넌트 버전을 게시하고, 아티팩트 리포지토리를 소유하며, 배포를 설명하는 재사용 가능한 CDK 구성 요소 또는 Terraform 모듈도 제공합니다. 이러한 빌딩 블록을 자체 인프라 코드에서 구성할 수 있으며, 생성기는 디바이스, 플릿 또는 배포를 직접 생성하지 않습니다.
호스트 프로젝트가 이미 존재해야 합니다. 먼저 py#project 또는 ts#project로 프로젝트를 생성하세요.
사용법
섹션 제목: “사용법”컴포넌트 생성
섹션 제목: “컴포넌트 생성”이 제너레이터 실행@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로 표기합니다.
하드웨어 및 운영 체제
섹션 제목: “하드웨어 및 운영 체제”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 | 아키텍처별 매니페스트가 있는 하나의 컴포넌트 버전 |
| 32비트 Linux / ARMv7을 실행하는 Raspberry Pi | 없음 | 이 생성기에서 지원되지 않음, 클래식 Greengrass nucleus는 ARMv7을 지원함 |
| Raspberry Pi Pico, ESP32 또는 다른 마이크로컨트롤러 | 없음 | 코어 디바이스의 IoT 클라이언트 또는 주변 장치로 사용 |
Raspberry Pi에서는 uname -m과 getconf LONG_BIT를 모두 확인하세요. 이 경로에는 aarch64와 64가 필요합니다. 32비트 사용자 공간을 실행하는 64비트 프로세서는 ARM64 배포 타겟이 아닙니다. 디바이스에는 생성된 레시피에 명시된 Python 인터프리터 또는 TypeScript용 Node.js와 Greengrass nucleus 전제 조건이 필요합니다. Python 종속성 벤더링은 manylinux_2_28을 타겟으로 하므로 glibc 2.28 이상을 사용하세요. GPIO 라이브러리와 사용자 정의 네이티브 종속성은 선택한 플랫폼에 호환되는 바이너리를 제공해야 합니다. 생성기는 이러한 주변 장치를 프로비저닝하지 않습니다.
생성된 Python 레시피는 호스트 프로젝트의 requires-python 최소값(예: python3.14)에 인터프리터를 고정합니다. 컴포넌트를 실행하는 각 코어 디바이스에 해당 인터프리터를 설치하세요. TypeScript 컴포넌트는 코어 디바이스에 Node.js가 필요합니다.
linux-amd64-arm64의 경우, 레시피에는 아키텍처당 하나의 매니페스트가 포함됩니다. 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컴포넌트 언어. 호스트에 지원되는 언어 마커가 정확히 하나만 있을 때만 생략합니다.
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제너레이터 실행 후 의존성 설치를 선호할지 여부.
생성기 출력
섹션 제목: “생성기 출력”디렉터리greengrass
디렉터리pulse
- recipe.yaml 컴포넌트 레시피
- main.py 컴포넌트 진입점
디렉터리tests
디렉터리greengrass
- test_pulse.py 경로로 main.py를 로드하는 단위 테스트
pulse-vendor 타겟은 uv pip install --only-binary :all:을 사용하여 선택한 디바이스 플랫폼용 프로젝트 종속성을 벤더링합니다. platform: linux-amd64-arm64의 경우, 아키텍처당 한 번씩 벤더링하고 레시피는 아키텍처당 하나의 매니페스트를 포함합니다.
디렉터리greengrass
디렉터리pulse
- recipe.yaml 컴포넌트 레시피
디렉터리src
디렉터리greengrass
디렉터리pulse
- 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 타겟의 종속성이므로, 일반 빌드는 아티팩트를 생성합니다.
인프라
섹션 제목: “인프라”이 생성기는 선택한 iac를 기반으로 코드형 인프라를 제공하므로, 관련 CDK constructs 또는 Terraform 모듈을 포함하는 packages/common에 프로젝트를 생성합니다.
공통 코드형 인프라 프로젝트는 다음과 같이 구성됩니다:
디렉터리packages/common/constructs
디렉터리src
디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 Constructs
- …
디렉터리core/
app의 constructs에서 재사용되는 일반 constructs- …
- index.ts
app에서 constructs를 내보내는 진입점
- project.json 프로젝트 빌드 타겟 및 구성
디렉터리packages/common/terraform
디렉터리src
디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 Terraform 모듈
- …
디렉터리core/
app의 모듈에서 재사용되는 일반 모듈- …
- project.json 프로젝트 빌드 타겟 및 구성
기본 infra: component-version은 누락된 경우 아래의 Greengrass 코어 파일과 컴포넌트당 하나의 앱 래퍼를 추가합니다. 기존 코어 파일은 보존되므로 로컬 편집 내용이 이후 실행에서도 유지됩니다. 디바이스, 사물 그룹 또는 배포를 생성하지 않습니다.
디렉터리packages/common/constructs/src
디렉터리core/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
디렉터리app/greengrass
- pulse.ts
Pulse, 이 컴포넌트의 빌드 출력에 고정된GreengrassComponentVersion
- pulse.ts
공유 구성 요소 프로젝트의 build 및 assemble 타겟은 호스트 프로젝트에 종속되므로, 인프라 빌드 또는 배포는 항상 최신 아티팩트를 읽습니다.
디렉터리packages/common/terraform/src
디렉터리core/greengrass
- artifact-bucket 선택적 토큰 교환 역할 권한 부여가 있는 보존된, 버전 관리된, TLS 전용 리포지토리
- component-version
awscc_greengrassv2_component_version을 통해 아티팩트를 업로드하고 버전을 게시 - deployment 선택적
aws_iot_thing_group이 있는awscc_greengrassv2_deployment
디렉터리app/greengrass-component
- pulse 이 컴포넌트의 빌드 경로와
bucket_name입력으로component-version을 래핑하는 모듈
- pulse 이 컴포넌트의 빌드 경로와
Greengrass 리소스는 hashicorp/aws 프로바이더에 존재하지 않습니다. 모듈은 hashicorp/awscc를 사용합니다. iac: terraform이 선택되면, Greengrass 생성기는 누락된 경우 Terraform 애플리케이션 루트에 awscc 필수 프로바이더와 provider "awscc" { region = var.aws_region }를 추가합니다. 기존 프로바이더 구성은 보존됩니다.
아키텍처
섹션 제목: “아키텍처”컴포넌트 버전은 빌드된 아티팩트를 명시적으로 소유한 리포지토리에 게시합니다. 스택 또는 루트 모듈은 코어 디바이스의 토큰 교환 역할에 읽기 액세스 권한을 부여하고 하나 이상의 배포에 버전을 추가합니다. 기본 읽기 권한은 워크스페이스의 컴포넌트 네임스페이스로 범위가 지정됩니다. 역할의 디바이스가 해당 컴포넌트의 하위 집합만 필요한 경우 범위를 더 좁히세요.
infra: none은 레시피, 진입점, Python 테스트, 타겟 및 공유 스크립트만 생성합니다. 인프라 프로젝트나 공유 구성 요소는 생성되거나 변경되지 않습니다. 나중에 infra: component-version으로 다시 실행하여 인프라를 추가할 수 있습니다. 이미 인프라를 소유한 컴포넌트를 none으로 다시 전환할 수는 없습니다.
로컬에서 빌드 및 실행
섹션 제목: “로컬에서 빌드 및 실행”개발 머신에서 아티팩트를 빌드합니다:
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 컴포넌트는 매니페스트당 하나의 아카이브를 빌드하며, 두 아키텍처를 모두 타겟으로 하는 경우 <component>-<architecture>.zip으로 명명됩니다. TypeScript 컴포넌트는 모든 매니페스트가 공유하는 하나의 아카이브를 빌드합니다. ipc: true의 경우 각 아키텍처용 aws-crt 애드온을 포함하고 각 매니페스트의 Setenv가 자체 애드온을 선택합니다. 레시피의 아티팩트 URI에 있는 BUCKET_NAME, COMPONENT_NAME 및 COMPONENT_VERSION 플레이스홀더는 게시 시간에 대체되며, 아카이브 기본 이름은 Run 단계가 압축을 푸는 이름으로 유지되어야 합니다.
다음 두 타겟은 일반 워크스테이션이 아닌 클래식 Greengrass nucleus와 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은 로컬 배포를 제출한 다음 컴포넌트의 수명 주기 상태를 폴링하고 세 번의 확인에서 RUNNING 또는 FINISHED 상태를 유지하지 않으면 0이 아닌 값으로 종료합니다. 로컬 배포는 디바이스에서 해당 버전을 고정하고 다른 버전의 이후 클라우드 배포와 충돌합니다. 로컬 및 클라우드 배포를 참조하세요.
배포 구성은 인프라 프로젝트에 있습니다. 일반적인 흐름은 하나의 리포지토리, 하나의 읽기 권한 부여, 컴포넌트당 하나의 앱 래퍼, 그리고 타겟당 하나의 배포입니다. 기존 사물 그룹 또는 사물에 대해 하나의 배포를 사용하고 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를 명명하는 메시지와 함께 실패합니다.
하나의 플릿에 두 개의 컴포넌트
섹션 제목: “하나의 플릿에 두 개의 컴포넌트”동일하거나 다른 프로젝트에 두 번째 컴포넌트를 생성한 다음 둘 다 하나의 배포에 추가합니다. 재정의는 해당 컴포넌트 항목의 명명된 최상위 필드를 대체합니다. 버전은 항상 구성 요소에서 가져옵니다.
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을 사용하세요.
두 개의 플릿에 하나의 컴포넌트
섹션 제목: “두 개의 플릿에 하나의 컴포넌트”동일한 구성 요소를 두 개의 배포에 등록합니다. 각 배포는 자체 구성을 포함합니다:
new GreengrassDeployment(this, 'WestFleet', { thingGroupName: 'west-fleet',}).addComponent(pulse);
new GreengrassDeployment(this, 'EastFleet', { thingGroupName: 'east-fleet',}).addComponent(pulse, { configurationUpdate: { merge: { sampleIntervalSeconds: 60 } },});동일한 구성 요소를 하나의 배포에 두 번 추가하는 것은 두 번째 호출이 재정의를 제공하지 않는 한 작동하지 않으며, 재정의는 항목을 업데이트합니다. 동일한 컴포넌트 이름으로 다른 구성 요소를 하나의 배포에 추가하면 구성 시간에 실패합니다.
공개 컴포넌트 및 원시 항목
섹션 제목: “공개 컴포넌트 및 원시 항목”이 워크스페이스에서 빌드하지 않은 컴포넌트는 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 문자열로 직렬화합니다.
기존 리포지토리 가져오기
섹션 제목: “기존 리포지토리 가져오기”하나의 스택이 리포지토리를 소유합니다. 다른 모든 스택은 이름으로 가져오고 소유 스택에 자체 권한 부여를 추가하거나, 토큰 교환 역할 자체에 동등한 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 애플리케이션을 사용하세요. 여기서 대신 생성하는 경우, 계속하기 전에 Greengrass 컴포넌트 생성기를 다시 실행하여 awscc 프로바이더 구성을 추가할 수 있도록 하세요.
이 제너레이터 실행@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을 사용하거나, 하나의 사물에는 thing_name을 사용하세요. 리터럴 target_arn은 계획 시간에 현재 파티션, 계정 및 리전에 대해 확인됩니다.
Terraform은 컴포넌트 레시피에서 명시적 시맨틱 버전을 사용합니다. 게시된 버전은 불변이므로 변경된 각 컴포넌트에 대해 새 버전을 선택하세요. Terraform은 플러그인의 NEXT_* 센티널을 해결하거나 Greengrass API를 호출하여 버전을 선택하지 않습니다. awscc 프로바이더는 Terraform용으로 구성된 자격 증명과 리전을 사용합니다.
plan 타겟은 assemble을 실행하고 계획된 아티팩트 다이제스트를 기록합니다. plan과 apply 사이에 레시피와 빌드 출력을 변경하지 마세요. 둘 중 하나가 변경되면 plan을 다시 실행하고 새 계획을 적용하여 게시된 바이트가 계획된 버전 및 객체 키와 일치하도록 하세요.
단계적 롤아웃 및 보존된 버전
섹션 제목: “단계적 롤아웃 및 보존된 버전”레시피 버전을 올리면 Terraform의 관리되는 컴포넌트 버전이 교체되고 Greengrass 레지스트리에서 나가는 버전이 삭제됩니다. 변경된 아티팩트 콘텐츠도 S3 키를 교체하고 나가는 객체를 삭제합니다. 변경되지 않은 아티팩트 바이트가 있는 버전 또는 레시피 변경은 동일한 키를 재사용할 수 있습니다. 삭제된 버전을 여전히 참조하는 배포는 실패하며, 여기에는 이전 버전에 남아 있는 두 번째 사물 그룹이 포함됩니다. create_before_destroy는 리소스 생성 순서를 지정합니다. 이전 버전을 보존하거나 모든 디바이스가 롤아웃을 완료할 때까지 기다리지 않습니다.
단계적 롤아웃 전에 컴포넌트 버전 및 S3 객체 리소스를 포함한 전체 게시 모듈을 보존하세요. 버전만 보존하면 해당 아티팩트가 삭제될 수 있습니다. prevent_destroy는 대체가 아닙니다: 나가는 버전을 유지하는 대신 버전 교체를 거부합니다.
먼저 기존 module "pulse" 블록을 제거하고 해당 출력에 대한 모든 배포 참조를 현재 게시된 이름과 버전으로 바꿉니다. 공유 artifacts 모듈, 배포 주소, 기타 컴포넌트 및 플릿 구성을 유지하세요. 예를 들어, 게시자가 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 키를 공유할 수 있으므로, 이후 게시자는 이전 버전이 여전히 참조하는 객체를 관리할 수 있습니다. 보존된 버전과 해당 아티팩트 키의 인벤토리를 유지하세요. 보존된 버전, 배포 또는 롤백이 필요하지 않을 때만 키를 삭제하세요. 리소스를 잊으면 사용 가능한 상태로 유지되지만 정리가 사용자에게 전송됩니다.
하나의 플릿에 두 개의 컴포넌트
섹션 제목: “하나의 플릿에 두 개의 컴포넌트”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 구성 요소와 다릅니다.
두 개의 플릿에 하나의 컴포넌트
섹션 제목: “두 개의 플릿에 하나의 컴포넌트”두 개의 배포 모듈이 동일한 컴포넌트 출력을 참조합니다:
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 }) } } }}공개 컴포넌트 및 리터럴 버전
섹션 제목: “공개 컴포넌트 및 리터럴 버전”게시된 공개 컴포넌트는 리터럴 항목이며 종속성이 필요하지 않습니다. 동일한 적용에서 생성된 리소스에 대한 리터럴 버전(예: 수동으로 작성된 awscc_greengrassv2_component_version)은 모듈 수준 depends_on의 한 가지 경우입니다. 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]}기존 리포지토리 가져오기
섹션 제목: “기존 리포지토리 가져오기”artifact-bucket 모듈에서 existing_bucket_name을 설정하세요. 그러면 모듈은 버킷의 설정이나 정책을 관리하지 않으므로, 버킷을 소유한 구성에서 아티팩트 접두사에 대한 토큰 교환 역할 s3:GetObject를 부여하세요:
module "artifacts" { source = "../../common/terraform/src/core/greengrass/artifact-bucket" existing_bucket_name = "central-greengrass-artifacts"}디바이스에서 확인
섹션 제목: “디바이스에서 확인”완료된 스택 업데이트 또는 적용은 배포 리소스가 존재함을 증명합니다. 배포와 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
섹션 제목: “레시피 및 IPC”기본 ipc: false를 사용하면 main.py는 30초마다 한 줄을 로깅하고 레시피에는 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초마다 한 줄을 로깅하고 레시피에는 IPC 액세스 제어가 없습니다. ipc: true를 사용하면 AWS IoT Device SDK의 Greengrass IPC 클라이언트를 통해 컴포넌트 자체의 로컬 토픽에 하트비트를 게시하고, pulse-vendor는 선택한 아키텍처용 aws-crt 네이티브 애드온을 스테이징합니다. AWS IoT Core에 게시하는 것은 동일한 클라이언트의 publishToIoTCore 작업, 레시피의 aws.greengrass.ipc.mqttproxy 권한 부여, 그리고 디바이스의 IoT 정책의 iot:Publish를 사용합니다.
레시피의 액세스 제어는 디바이스의 nucleus에 의해 시행됩니다. SDK만으로는 아무것도 승인하지 않으므로 컴포넌트가 성장함에 따라 operations와 resources를 확장하세요.
생성된 레시피는 클래식 aws.greengrass.Nucleus를 타겟으로 합니다. Nucleus Lite는 IPC 작업의 하위 집합을 구현하고, 플러그인 컴포넌트를 실행하지 않으며, v2.15에서만 컨테이너 지원을 얻었습니다. 플릿이 실행하는 nucleus에 대해 레시피를 확인하세요. 생성기는 nucleus 기능을 감지하지 않습니다.
Ubuntu 25.10 이상에서는 IPC 환경이 손실되기 때문에 sudo-rs가 Greengrass Nucleus 2.18.3으로 IPC 컴포넌트가 시작되는 것을 방지할 수 있습니다. 생성기는 호스트의 sudo 보안 구성을 변경하지 않습니다. IPC가 필요한 경우 클래식 sudo 동작을 제공하는 디바이스 설정을 사용하세요.
자동 버전 관리
섹션 제목: “자동 버전 관리”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 배포 중에 실행됩니다. 동일한 컴포넌트에 대해 동시 게시를 실행하지 마세요: 배포가 동일한 다음 버전을 선택하여 하나의 게시가 실패할 수 있습니다.
아티팩트 스토리지 및 보존
섹션 제목: “아티팩트 스토리지 및 보존”계정 및 리전당 하나의 아티팩트 리포지토리를 사용하며, 하나의 스택 또는 루트 모듈이 소유합니다. 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 해시를 해시하며, 하나 또는 여러 아티팩트에 대해 동일한 공식을 사용합니다. 키 접두사만 단축됩니다. 아티팩트 다이제스트와 자동 버전 ID는 전체 해시를 유지합니다. CDK의 버킷 배포 태그는 접두사를 102자로 제한하여 컴포넌트 이름에 68자를 남깁니다. 생성기는 CDK 인프라가 선택될 때 해당 제한을 확인하고, 합성은 레시피 편집을 확인합니다. Terraform의 객체 업로드에는 이 CDK 제한이 없습니다.
배포 또는 롤백이 컴포넌트 버전을 필요로 할 수 있는 동안 게시된 아티팩트를 사용 가능하게 유지하세요. CDK는 기본적으로 교체된 컴포넌트 버전과 해당 업로드를 보존합니다. Terraform은 교체된 버전과 나가는 객체 키를 삭제합니다. 여러 그룹에서 사용하는 버전을 올리기 전에 단계적 롤아웃 및 보존된 버전을 참조하세요. 레지스트리 버전을 제거해도 디바이스에서 이미 실행 중인 컴포넌트는 제거되지 않습니다. Terraform의 리포지토리는 prevent_destroy를 설정합니다. 아티팩트가 더 이상 필요하지 않은 후 의도적인 해체를 위해서만 해당 리터럴 수명 주기 설정을 제거하세요.
기본 토큰 교환 역할 권한 부여는 워크스페이스의 컴포넌트 네임스페이스에서 s3:GetObject를 허용합니다. 더 좁은 권한 부여를 위해 CDK에서 keyPrefix를 설정하거나 Terraform에서 token_exchange_key_prefix를 설정하세요. 가져온 버킷은 자체 정책을 유지하므로 버킷 또는 역할이 소유된 곳에서 권한 부여를 관리하세요.
배포 수정
섹션 제목: “배포 수정”컴포넌트 버전 또는 배포 구성을 변경하면 배포 리소스가 교체됩니다. CloudFormation은 하나의 스택 작업에서 최대 10개의 배포 리소스를 추가하거나 삭제할 수 있습니다. 대규모 롤아웃을 배치로 분할하세요. 교체에는 일반 deploy 타겟을 사용하세요. deploy-sandbox는 CloudFormation 익스프레스 모드를 사용하며, 교체 업데이트에는 --rollback이 필요합니다.
배포 리소스를 삭제하면 클라우드 관리 상태가 제거되지만 디바이스에서 컴포넌트가 제거되지는 않습니다. 먼저 컴포넌트를 생략하는 수정을 배포하고, list-installed-components에서 사라질 때까지 기다린 다음 IaC 리소스를 제거하세요.
로컬 및 클라우드 배포
섹션 제목: “로컬 및 클라우드 배포”<component>-deploy-local의 로컬 배포는 해당 디바이스에서 컴포넌트 버전을 고정합니다. 다른 버전을 요청하는 클라우드 배포는 고정을 충족할 수 없습니다. 클라우드에서 해당 디바이스를 업데이트하기 전에 로컬 배포를 제거하세요:
sudo /greengrass/v2/bin/greengrass-cli deployment create --remove com.example.Pulse개발 디바이스에는 로컬 배포를 사용하고 플릿 타겟에는 클라우드 배포를 사용하세요.
문제 해결 및 서비스 제한
섹션 제목: “문제 해결 및 서비스 제한”클라우드 배포 후 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는 리전당 하나의 컴포넌트를 5,000개 버전으로 제한하고 CreateComponentVersion을 리전당 초당 하나의 요청으로 제한합니다. 레시피는 16KB로 제한되고, 배포 문서는 사물 그룹의 경우 31KB, 단일 사물의 경우 7KB로 제한됩니다. 새 버전을 하트비트로 사용하지 말고 대규모 배포를 더 작은 배치로 분할하세요.