State Machines

Moving Beyond Single-State IaC to Multi-State Systems as Data

Introduction

At Guidepad we're developing what we believe is the future of modern software system development and management. To us, this means moving out of files into data as much as possible, and shifting the problem of building a distributed system to one of programming a distributed system. To illustrate the difference between the current standards and where we think things should go, we want to take a little bit of time to discuss the differences between our way of doing things and some of the current standards in systems like Terraform (TF) and OpenTofu (OTF). In the remainder of this blog post we'll refer mostly to TF but the points made equally apply to OTF.

Overview of Terraform IaC Concepts and Guidepad Abstractions

Systems like TF are control planes that allow users to manage the state of a set of resources. In TF, a resource is a configuration primitive that describes some system component. Teams write code (HCL in TF or in a given language via the Cloud Development Kit for Terraform (CDKTF)) that specify their system components' desired state as a set of files (called a module), which is then often kept within a version control system. In TF, an entity called a provider implements the logic of using the resource definitions to manipulate state in some remote system to reify the desired state expressed in those definitions. TF maintains a database of current state for the resources so that providers can calculate the delta between the current and desired state and make a plan to bring the states into alignment. Teams can then parameterize their modules to allow them to be configurable for different use cases and target environments.

The above arrangement of concepts means that:

  • resource specifications in systems like TF are tightly coupled to the provider implementation
  • specification of your entire system is tightly coupled to the control plane (Terraform)
  • the only possible state mutation is to go from the current remote state to the state expressed in the IaC module
  • changes to specifications happen at compile time, not run time

Guidepad removes these constraints by abstracting at a level higher than the control plane and shifting configuration from a compile time concern to a run time concern. To facilitate the shift to run time configuration management, Guidepad stores system definitions as dynamic data rather than static files. As far as Guidepad's abstractions, we can loosely map them to TF concepts:

  • resources in TF would be considered services in Guidepad
    • unlike resources, however, services are control plane agnostic and can be used across environments and control planes
    • TF, like Ansible, kubectl, Web Assembly, Pulumi, etc. are control planes
  • control planes manage the state of services in what Guidepad calls environments
  • environments are logical boxes around resources and can be things like an AWS account (or other cloud provider), a Kubernetes cluster, some server racks, etc.
  • TF modules would be considered state plans in Guidepad
    • Guidepad state plans are directed acyclic graphs of commands that can be used to put a service into a particular state
    • state plans are not tightly coupled to a particular control plane, unless that control plane has its own syntax
    • state plans can be provided code to execute, or they can execute Guidepad operations (think portable functions)
    • multiple control plans can be involved in a single state plan execution

So to summarize, Guidepad services, environments, control planes, state plans, and operations mean that:

  • service definitions are control plane agnostic
  • state plans are parameterized and abstract and can be re-usable across both environments and services
  • Guidepad provides an experience where a user tells Guidepad to put service A into state B and Guidepad determines how to do that
  • teams have standardized flows for managing systems regardless of the underlying control plane
  • new control planes can be rapidly implemented and customized (via Guidepad plugins)
  • system data and schema can be manipulated as part of state transitions

Automating Distributed System Management with State Machines

So all of the above is great, and gives teams using Guidepad unparalleled visibility and flexibility when building and managing modern systems. But what if we want to automate the transition between states in those systems in response to real world conditions? Guidepad's state machine abstraction provides that capability:

State machines allow for specification of the valid states within a distributed system, as well as the allowed transitions between those states for each service in the system. Importantly, each service can use a different control plane, with a different state plan, targeting a different environment in its own transition from state to state. Each transition can also be assigned requirements, which are logical gates on when the transition is allowed to fire. Requirements are another extensible part of the Guidepad framework and new requirements can be added either as data records or via guidepad plugins.

Some common examples of requirements include:

  • boolean and/or
  • cron-style scheduling
  • conditioning on the result of a particular operation
  • the state of services in other state machines
  • internal and external events recorded by Guidepad
  • the contents of log messages

The Guidepad state machine orchestrator monitors all state machines with the "autonomous" flag set to true, and will automatically move services to new states when the requirements for the state transitions are satisfied.

It is important to remember that each transition can utilize a different state plan/control plane combination, meaning that teams have fine-grained control over how services change their state. Does a state change make the most sense using Terraform, written in HCL? Use the Terraform control plane. Is the team responsible for managing this particular state change most comfortable with Python, or Bash, or Rust? Use one of the control planes tailored to executing code instead. Maybe your team has a large set of Pulumi IaC that you're not ready to move away from. With Guidepad you can utilize a Pulumi control plane to use those existing IaC resources and migrate to different control planes as need dictates.

The Terraform Control Plane

A moment should be taken here to highlight the built-in Terraform control plane in Guidepad, since this is a blog post mostly about Terraform-like capabilities. This control plane allows for nodes within the State Plan DAGs to be written directly in HCL, but still utilize all of Guidepad's other system modeling capabilities. With the Terraform control plane, Guidepad automatically manages state artifacts for each service x state x environment combination via other subsystems within Guidepad. This control plane is also an excellent example of how straightforward it is to add new control plane support to the system, as the file implementing the control plane in our code base is less than 100 lines.

If you'd like to learn more about the Guidepad system or request a demo, please reach out at hello@guidepad.io.

Recent Publications

Blog

Guidepad's ML Plugin

The guidepad-ML plugin is an extension of the guidepad platform that helps users with their end-to- end ML lifecycle.

Tommy O'Keefe

Jul 28, 2023 · 10 min read read

Blog

Guidepad's Managed Embeddings Service (Part 1)

This demo showcases the capabilities of our embeddings service. This notebook will interact with a set of APIs we offer, showing that the embeddings service can be utilized by any downstream application with internet access, or any user with their preferred programming language.

Tommy O'Keefe

Aug 8, 2023 · 10 min read read

Blog

Guidepad's Managed Embeddings Service (Part 2)

Let's explore how we can leverage our REST API to save documents, compute document embeddings using a combination of pretrained open-source language models, and generate custom embeddings for your documents.

Tommy O'Keefe

Aug 8, 2023 · 10 min read read