Difference between convergence and idempotence in Chef

dextren picture dextren · Jun 3, 2015 · Viewed 9.4k times · Source

What is the basic difference between convergence and idempotence in Chef?

Answer

jtimberman picture jtimberman · Jun 3, 2015

Convergence and idempotence are not Chef-specific. They're generally attributed to configuration management theory, though have use in other fields, notably mathematics.

Let's start with the more basic, idempotent. We're going to ignore the mathematic use of idempotent, and focus instead on what configuration management people mean when they talk about it. That is: "multiple applications of the same action do not have side effects on the system state." A simple example of an idempotent operation is mkdir -p:

mkdir -p /var/lib/statedir/myapp

No matter how many times we run this command, it will result in that tree being created. Another way of stating this about idempotent operations is, "running the tool over and over doesn't change the system after the first time."

Now to contrast that with convergence. Generically, to converge means to bring [people or] things together. In configuration management, convergence means to bring the system state in line with a defined policy. That is, changes are made on the system only if they need to be made. A simple example of a convergent operation is:

if [ ! -d /var/lib/statedir/myapp ]; then
  mkdir -p /var/lib/statedir/myapp
fi

This is convergent because we're only executing the mkdir command if the desired directory does not exist. We also call this a "test and repair" operation. That is, we test the current state of the specific thing we're managing, and then repair it with a specific command or operation if it is not in that state. That is what Chef does behind the scenes with a resource like this:

directory '/var/lib/statedir/myapp' do
  recursive true
end

The way we (Chef) talk about this is that Chef takes idempotent actions to converge the system to the state declared by the various resources. Every resource in Chef is declarative, and performs a test about the current state of the resource, and then repairs the system to match that.

To get deeper into the weeds about how Chef works, it has a "compile" phase and a "converge" phase in a Chef run. In the "compile" phase, it evaluates the Ruby recipes on the node, and it is looking for resource objects that it adds to a "resource collection." Once it has evaluated all the recipes, it then enters the "converge" phase where it iterates over the resource collection, taking the appropriate action to put the resources into the desired state, whereby users are created, files are written, packages are installed, and so forth.