Your Resource for All Things Apps, Ops, and Infrastructure

The Philosophy of Automation: Desired State vs. Imperative Orchestration

Introduction

The demands of modern business dictate that automation and increased efficiency are must-haves to stay competitive, relevant, and scaling. Sometimes you have developers who want ephemeral environments that destroy themselves after two days, or your security team wants to enforce CIS compliance over time. In other cases, you just want to make patching cycles easier and faster. But where do you start? What platforms do you use? Do you need an orchestration platform? A desired-state configuration platform?

These are all questions that businesses need to answer to scale their environments successfully. Below, we’ll explore the predominant approaches to automation, what some major platforms can offer, and a few of the most common use cases for each approach.

Decision Paralysis – An Abundance of Choices

With all the fantastic automation platforms available today, we now have a problem of choice – there are simply too many!

For example, let’s imagine that you want to ensure that an application server has a consistent rule for port 443/tcp added to iptables. You take a look at some of the major automation platforms and find that you can do this through Puppet. Great! But then you look at some more documentation and sure enough, Chef can do it too. Upon further inspection, you find that not only can Puppet and Chef meet your needs, but both Ansible and SaltStack can as well.

With four different platforms that all fall under the umbrella descriptor of ‘configuration management,’ you become overwhelmed – when every platform you consider has this capability, how are you supposed to choose one?

Most developers are all too familiar with this conundrum. Automation platforms are especially prone to this, because while every platform is centered around the concept of configuration management, each uses a slightly different method. Here, we’ll break down some of the different approaches to ease the stress of this decision.

Desired-State Configuration (Declarative Automation)

The first style of automation we’ll explore is Desired-State Configuration (DSC), or declarative. With DSC, we begin by defining an end-state, and our automation platform does the work of reconciling what we want, where we are, and what we need to do to get there. These platforms are almost always agent-based, with a process running on each node that enforces this desired state.

Think of DSC like hiring someone to paint your house red. You don’t tell the painter: “I want you to take your paint roller, dip it in the paint, and then roll it across each wall of the house.” Instead, you tell the painter: “I want all of the outside walls painted red.” The painter then reconciles what color your house is now (moth grey), what color you want it to be (red), and how to get there (open a paint can, pour it in a tray, dip the roller in the paint tray, roll across the wall, etc.).

Automation platforms that use DSC work the exact same way. Platforms like Puppet, Chef, SaltStack, Powershell DSC, and CFEngine are all based on this methodology. They are designed to reconcile those three things – desired state, current state, and process. Let’s take a look at some DSC pseudocode:

file “C:\Users\Brandon\Desktop\docs\hello.txt” 
{
  ensure {
    file.exists = true
    file.content = “Hello!”
    }
}

folder “C:\Users\Brandon\Desktop\docs” 
{
  ensure {
    folder.exists = true
    }
}

This code does two things: it ensures that (1) the directory listed actually exists and (2) that it contains a text file with the contents: “Hello!” Our DSC platform doesn’t need to be told the order of operations here – it will build out a dependency map for these code blocks and recognize that the first section cannot happen if the second section is false. Then, it will ensure that we’ve reached the desired state by creating the ‘docs’ folder and ‘hello.txt’ (if they don’t already exist), and finally, changing the content of ‘hello.txt’ to say “Hello!” The contents must exactly match our string in file.content above – otherwise, it gets changed to what we’ve declared. The agent that performs the actual work here will always run on a schedule – every 30 minutes is a common default, but it’s always configurable. Because the agent is located on the node itself, your desired state is still enforced even if the controlling server goes down.

This, in a nutshell, is how DSC works – no matter what platform you are using. We’ll cover some specific use cases and examples for this style of automation later in the article.

Orchestration (Imperative Automation)

While Puppet, Chef, SaltStack, Powershell DSC, and CFEngine are declarative platforms, there are others, such as Ansible, that are Orchestration (or imperative) platforms. Orchestrators are almost always imperative because they themselves run tasks against nodes. As a result, imperative tools are often much easier to get started with – after all, you are essentially just giving them a list of commands to execute.

Here’s an example of some Ansible code that creates a user account on a Linux machine and then changes ownership of a file to that user:

name: ‘Create user bhartman’
  ansible.builtin.user:
    name: bhartman
    comment: Brandon Hartman
    uid: 1040
    group: wheel

name: ‘Ensure bhartman exclusively owns /var/tmp/app.bin’
  ansible.builtin.file:
    path: /var/tmp/app.bin
    owner: bhartman
    group: bhartman
    mode: 0700

Ansible will do several things when you run this task:

  1. Gather Facts
    • Ansible collects information on the current node into a catalog
  2. Evaluate Current State
    • Ansible looks to see if user ‘bhartman’ already exists
  3. Make a Decision
    • If the user already exists, the task can be skipped; if not, we’ll create the user (or update it with proper configuration) and report back that we’ve ‘changed’ something
  4. Evaluate Current State
    • Ansible looks at the status of /var/tmp/app.bin
  5. Make a Decision
    • If the file has the wrong owner, group, or permissions, Ansible will adjust accordingly and report back

At first glance, this seems very similar to our DSC examples above. We are still evaluating against current state, deciding what to do, and then executing on it, but the method here is different. Ansible will follow these tasks in the order we present them with no consideration to dependencies. If we were to flip these two blocks, the task would fail (unless the ‘bhartman’ user already existed). Imperative platforms also (almost always) do not have an agent – these commands are run from a controller node over SSH or WinRM. There is no agent process on the endpoint that does any of the work.

It is crucial to understand that because they are agentless, imperative tools only enforce their configurations when they are run. If you only run this playbook once, you will only ever enforce it once. You can automate the playbook to run on a schedule, but this does not scale well once you have thousands of servers and hundreds of playbooks in the environment. That may seem like a downside, but it is by design. This is the most important distinction between declarative and imperative platforms. In the next section, we will discuss why this distinction matters.

Why It Matters

When evaluating any automation platform, it is important to consider your use cases. DSC and imperative orchestration tools both have their place in an environment, and knowing which platform is best for which use case is vital for effectively scaling your environment, toolsets, and skillsets.

Generally, a good test for DSC versus orchestration platforms is this: If the use case involves ongoing enforcement, security enforcement, or ‘stable’ settings, use DSC. If the operation is a one-off, infrequent, or special situation that demands things happen in a particular order, use imperative platforms.

In the table below, we’ve laid out some situational examples and indicated which platform is most suitable for each use case:

Key Takeaways

  • Each automation platform has their own area that they specialize in – not every tool is right for every job.
  • DSC platforms are agent-based and designed for ongoing compliance as well as enforcing security posture. The platform itself determines how to reach the end state.
    • Configurations are enforced on an interval that you specify
  • Orchestration tooling is agentless and designed for one-offs, dependency-based workflows, and infrequent operations. The platform does exactly what you tell it to do, in the order you specify.
    • Configurations are only enforced when you run your job
  • Some use cases might call for both DSC and imperative tooling. They are very rarely competitors within a use case and serve very different needs.

At AHEAD, we provide our customers with ongoing education, demos, services, and expertise on automation platforms. If you have questions, need help with your automation initiatives, or just want to discuss which platforms are available, contact us today!

Conduct a Health Check on your ransomware resiliency and work fearlessly toward the future.

Subscribe to the AHEAD i/o Newsletter