Exploring Configuration Management Tools
Start course

Learn how to simplify all of your application infrastructure into just a few configuration files then deploy your code on Google Cloud Platform with this course. We will start by learning the core concepts behind Infrastructure as Code, discussing security best practices when working with IaC, and comparing some popular orchestration and configuration management tools.

After that, we’ll implement version control for our IaC configurations, and learn how we can automate deployment updates using Cloud Build Triggers. Next, we’ll learn how to integrate Google Secret Manager to protect any sensitive data in our source code. Then to tie it all together, we’ll walk through Google Identity and Access Management and learn how to monitor our users and resources on GCP.

After learning the basics, we’ll build our own immutable server images with Google Cloud Build using both Docker and Packer. We’ll then explore a practical usage scenario and build a WordPress deployment with Google Deployment Manager. We’ll also deploy a similar WordPress configuration using Terraform to compare the two methods.

I will be working in Visual Studio Code during the demos for this course, but you are also free to use any other IDE you are comfortable with instead. A demo repository is provided along with this course, and while we will be working with some Python and PHP in our examples, you should still be able to follow along with the demos without any background in either of these languages.

Learning Objectives

  • Build server images from a configuration file using Docker and Packer.
  • Learn to use Google Cloud Build with third-party build steps.
  • Deploy application infrastructure from code using Google Deployment Manager and Terraform.
  • Understand templating systems for Infrastructure as Code.
  • Implement version control for Infrastructure as Code.
  • Learn to protect secret data in IaC configurations using Google IAM role management and Google Secret Manager.

Intended Audience

This course is intended for programmers interested in expanding their knowledge about modern cloud-based DevOps workflows. Learning to manage Infrastructure as Code is beneficial to solo developers who need to focus as much of their time as possible on their application code and not on managing infrastructure. Development teams will also benefit from this course, because implementing IaC provides consistent performance across deployments in multiple environments, which greatly simplifies project collaboration. This course will also help prepare the viewer for the Google Professional Cloud DevOps Engineer certification.


  • You should already have a Google Cloud Platform account.
  • You should have Google Cloud SDK already installed and initialized.
  • You should already have Git installed, and be familiar with its use.
  • Demos will be shown in Visual Studio Code, but you're free to use any IDE they are familiar with.
  • Demos will utilize some Python and PHP, but you're not required to be fluent in either of these languages to follow along with the examples.


Additional Documentation


"Exploring Configuration Management Tools." In this course, we'll be working with Google Deployment Manager and Terraform, which are orchestration management tools. There are however a number of server configuration management tools that have been around for years that can also help us to deploy infrastructure as code.

In this lecture, we're going to take a look at a few of these configuration management tools and compare them to orchestration management to understand why we actually won't be using them in the rest of this course. You will often hear imperative versus declarative programming mentioned when discussing these configuration management tools. Imperative code gives a program specific statements with instructions to follow, telling it exactly how to perform every step the job requires.

Procedural and object-oriented programming languages both follow this imperative programming paradigm. Declarative code tells a program what to do without explicitly specifying how to do it. Where an imperative program would lay out every single ingredient and specific step in sequential order to make a sandwich, a declarative program would just say, "Make me a sandwich with extra pickles," and leave exactly how the sandwich gets made up to the program to figure out.

Typically, a domain-specific language is used to give our declarative statement the information it needs to fill in the blanks with the right steps to perform the job for us. Structured query language or SQL is an example of a domain-specific language. Functional programming languages also follow this declarative programming paradigm. The benefit of imperative programming is that we always know exactly what actions our application is performing because we told it exactly how to behave. The downside is we have to code all that functionality ourselves.

The benefit of declarative programming is that a lot of the minute details of our configuration are abstracted for us. So we can focus more on the end product and less on how we get there. This adds a lot of magic to our application. However, where we may no longer fully comprehend all the actions our program is executing to reach our desired end state for us, that can introduce difficulties in debugging our application.

In general, adding layers of abstraction makes things easier for us when they work properly but tends to make things more difficult for us when they don't. Most modern programming languages support multiple programming paradigms, as do all of the configuration management tools we are discussing in this lecture. It's up to the developer to choose which is appropriate to implement when writing their own code.

Whether we're talking about application code or infrastructure as code. A modern cloud-based DevOps approach fits most naturally with declarative functional programming because it's inherently stateless and immutable. This helps us to avoid other common pitfalls when working with immutable containers in a cloud-based configuration. But it's not necessarily quick and intuitive to get started with.

Procedural code is generally more comfortable for the operations team already familiar with traditional server scripting. While object-oriented declarative programming is the bread and butter of most any development team. Depending on your team composition and your production environment, a configuration management tool like Puppet, Chef or Ansible could benefit your workflow.

Terraform and Google Deployment Manager are orchestration tools that are capable of provisioning new infrastructure resources. Puppet, Chef, and Ansible were designed as configuration management tools meant to oversee the state of already deployed resources. This means that when working with these configuration management tools, we are by default employing mutable rather than immutable infrastructure.

These tools are by design connecting to existing deployments and making changes to them to match a desired configuration state rather than making a new deployment based on an updated configuration. We can combine Puppet, Chef or Ansible with Packer and Terraform though to gain both the benefits of immutable orchestration and any specific server configuration management features we may need.

Puppet generally takes a declarative approach to server configuration. We define the final state we require for our new server and Puppet uses configuration information it already knows to reach that state without us explicitly telling it every step to take along the way when updating the server. Scripting in Puppet heavily relies on Ruby. And Puppet uses is its own domain-specific language, which can present a fairly steep learning curve to Puppet mastery.

Puppet uses a master-agent server architecture where client machines running our application pull information from a master server that tells them what their current configuration state should be. The Puppet domain-specific language is capable of some complex configurations, but the code can get very bulky and can suffer from scalability issues. Puppet has the benefit of being well-established and it has many robust features and a strong support community due to its longevity.

Chef is similar to Puppet in many ways but leans even more heavily into a developer-centric administrative approach, which will thrill your programmers but make your sysadmins cry. It also relies heavily on Ruby scripting using a Ruby-based domain-specific language when building cookbooks, which is what Chef calls its configuration files.

Cookbooks can also be written imperatively but are then called declaratively from the Chef workstation. So a single Chef configuration can end up using both paradigms. Chef also uses a master-agent model but with an additional workstation component that controls configuration changes from the master to the agents. The complexity can make Chef the most difficult and time consuming configuration management tool to master but also the most flexible. Chef has also been around for a while and is known for being very stable across a wide number of environments and having strong documentation.

Ansible is newer to the scene than Puppet and Chef, which shows in its more modern and streamlined workflow. Ansible is also a mix of imperative and declarative paradigms. Configuration files in Ansible called playbooks are executed in the order they appear, making Ansible procedural. But the playbooks themselves are typically called in a declarative manner. Sysadmins will find themselves at home with Ansible where scripting is written in Python and configuration files are stored in YAML.

Ansible differs from Puppet and Chef in the server architecture. Using an agentless model instead, connecting to clients and sending commands over standard SSH connections. This means Ansible is generally faster, lighter weight and more scalable than either Puppet or Chef.

Chef and Puppet are both popular in enterprise environments and suitable for some very complex configurations. Both include in-depth reporting options and intuitive user interfaces and integrations with a number of both bare metal and cloud server providers. Yet both suffer from some similar performance and scalability issues due to their master-agent server models and heavyweight DSL code, Ansible with its agentless approach is a more natural fit in cloud environments.

Google Cloud Platform already tends to favor Python scripting and YAML config files across their cloud products, which makes Ansible further feel at home there. Python is also far more in demand than Ruby these days. So while Ansible lacks some of the robust features and reporting, or even a good GUI when compared to Puppet or Chef, you're probably going to find fewer developers with Ruby experience than developers who aren't already familiar with Python.

Using a modern DevOps approach like we've taken in this course though, we very well might not even require any of these configuration management tools for our project at all. We will already be building immutable servers using Docker images and defining the rest of our infrastructure requirements using Google Deployment Manager and Terraform in this course.

There's no reason to introduce extra complexity into our project, if we don't have a specific need to include one of these additional configuration management tools. The most common reason to implement one of these tools would be to support a hybrid deployment that utilizes both cloud-based and bare metal infrastructure resources across multiple environments.

About the Author

Arthur spent seven years managing the IT infrastructure for a large entertainment complex in Arizona where he oversaw all network and server equipment and updated many on-premise systems to cloud-based solutions with Google Cloud Platform. Arthur is also a PHP and Python developer who specializes in database and API integrations. He has written several WordPress plugins, created an SDK for the Infusionsoft API, and built a custom digital signage management system powered by Raspberry Pis. Most recently, Arthur has been building Discord bots and attempting to teach a Python AI program how to compose music.