Skip to content

Startup

Michael Dombrowski edited this page Sep 12, 2023 · 3 revisions

Greengrass startup

The main method of Nucleus handles argument parsing and then automatic provisioning if requested. Very early on in the startup process Greengrass creates the Kernel instance. Kernel is the primary launchpad for all the Greengrass does in its state machine to create and run services. Next during startup, DeviceConfiguration is created which is used as a more ergonomic wrapper to read common configuration values from the global Greengrass configuration. If the device needs to be provisioned, then Greengrass calls out to the provisioning code. If the component default user does not exist, then Greengrass will try to create the user and group. If requested, Greengrass then configures itself as a system service. Finally, Greengrass can startup the Kernel.

Kernel Launch

Kernel launch begins by validating that we have a valid user configured for components to execute with. Next, Kernel checks to see if there is an ongoing deployment which restarted Greengrass and what to do next. If Greengrass is in the BOOTSTRAP phase, then it needs to identify which components need to execute their bootstrap steps and then execute them all sequentially. If any bootstrap step fails, then Greengrass will log the error and quit with an error in order to trigger the rollback.

If Greengrass is in the KERNEL_ACTIVATE or KERNEL_ROLLBACK phase when starting it will read the currently active deployment details from a persistent file and insert it as a deployment into the deployment queue.

If Greengrass is in the default state, then it will read the configuration and simply continue to the KernelLifecycle.launch.

Configuration

Greengrass is entirely controlled by the configuration that it keeps on the device. The source of truth for everything on the device is the config file config.tlog. This is a transaction log of all configuration changes in a newline separated JSON format. Because this file is the source of truth for everything, Greengrass takes great pains to ensure that its contents are correct and never corrupted, and if it is corrupted then to try and fallback as gracefully as possible. This logic is in KernelLifecycle.initConfigAndTlog.

KernelLifecycle initConfigAndTlog

  1. If Greengrass is provided a config file using the --config flag, then all other configuration which may exist will be ignored. This flag must not be used by anyone manually as it is very likely to cause problems. This flag is used by Greengrass when doing a KERNEL_BOOTSTRAP or KERNEL_ROLLBACK.
  2. Assuming that no --config is provided, Greengrass attempts to validate the config.tlog to see if we can trust it
  3. If we believe config.tlog is valid, then we read it into the configuration in memory
  4. If we do not believe that it is valid, then we attempt to read from one or more backup locations
    1. Greengrass reads config.tlog~, bootstrap.tlog, and bootstrap.tlog~ in order until it finds one which is valid
    2. Greengrass then loads the valid configuration (if any) into memory
  5. If no --init-config is provided and there is no config.tlog, Greengrass checks for config.yaml and will load that file if it exists
  6. If --init-config is provided, then that config file is read into the in memory configuration which will merge with the existing configuration based on the timestamp when the --init-config file was last modified
  7. If Greengrass did not read from the config.tlog, then it dumps the configuration that it just built up into `config.tlog
  8. Greengrass then dumps the effective configuration to effectiveConfig.yaml
  9. Last, Greengrass configures a ConfigurationWriter to keep the config.tlog updated with configuration changes as they happen

KernelLifecycle Launch

KernelLifecycle.launch is where the Greengrass state machine starts up services and starts doing real work. The launch starts by starting startables. This is done so that these services are guaranteed to be in a running state before anything else begins to start which may wish to use these services. Next, Greengrass finds any provisioning plugins, then builtin services and non-provisioning plugins, then the builtin services and non-provisioning plugins are loaded into the JVM. If the device is not configured to connect to IoT Core yet, the provisioning plugin (if any) will be executed to get the connection to IoT Core configured. Next, Greengrass locates the main service. The main service is a dummy service which does nothing itself except to have a HARD dependency on all Greengrass components and services. Greengrass then starts up all services.

To startup all services, Greengrass determines the dependency ordering from main since all services were added as dependencies of main. For each dependency, Greengrass checks if it should start and if it should start then Greengrass requests it to startup.

Clone this wiki locally