Files
finistdev-configuration-as-…/index.html

436 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configuration as Code — Puppet vs Ansible vs Terraform</title>
<!-- Reveal.js CDN -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reset.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/theme/moon.css">
<!-- Highlight.js for code blocks -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/monokai.css">
<style>
:root {
--puppet-color: #FFAE1A;
--ansible-color: #EE0000;
--terraform-color: #7B42BC;
}
.reveal .slides section {
text-align: left;
}
.reveal h1, .reveal h2 {
text-align: center;
}
.reveal h1 { font-size: 1.8em; }
.reveal h2 { font-size: 1.3em; }
.reveal p, .reveal li { font-size: 0.78em; }
.reveal code { font-size: 0.7em; }
.reveal pre { width: 100%; }
.title-slide { text-align: center !important; }
.title-slide h1 { font-size: 2em; margin-bottom: 0.2em; }
.title-slide .subtitle { font-size: 1em; color: #aaa; }
.title-slide .meta { font-size: 0.7em; color: #888; margin-top: 1em; }
.tag {
display: inline-block;
padding: 2px 10px;
border-radius: 4px;
font-size: 0.55em;
font-weight: bold;
vertical-align: middle;
margin-left: 8px;
}
.tag-puppet { background: var(--puppet-color); color: #000; }
.tag-ansible { background: var(--ansible-color); color: #fff; }
.tag-tf { background: var(--terraform-color);color: #fff; }
.card-row {
display: flex;
gap: 1em;
margin-top: 0.5em;
}
.card {
flex: 1;
border-radius: 8px;
padding: 0.7em 1em;
font-size: 0.7em;
}
.card-puppet { border: 2px solid var(--puppet-color); background: rgba(255,174,26,0.08); }
.card-ansible { border: 2px solid var(--ansible-color); background: rgba(238,0,0,0.08); }
.card-tf { border: 2px solid var(--terraform-color);background: rgba(123,66,188,0.08); }
.card h3 { margin: 0 0 0.4em; font-size: 1.1em; }
.card ul { margin: 0; padding-left: 1.2em; }
.comparison-table {
width: 100%;
border-collapse: collapse;
font-size: 0.62em;
margin-top: 0.5em;
}
.comparison-table th, .comparison-table td {
border: 1px solid rgba(255,255,255,0.2);
padding: 0.4em 0.6em;
text-align: center;
}
.comparison-table th { background: rgba(255,255,255,0.1); }
.comparison-table td:first-child { text-align: left; font-weight: bold; }
.puppet-col { color: var(--puppet-color); }
.ansible-col { color: var(--ansible-color); }
.tf-col { color: var(--terraform-color); }
.highlight-box {
border-left: 4px solid #4CAF50;
background: rgba(76,175,80,0.1);
padding: 0.5em 1em;
margin: 0.5em 0;
border-radius: 0 6px 6px 0;
font-size: 0.75em;
}
.agenda-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5em;
margin-top: 0.5em;
}
.agenda-item {
background: rgba(255,255,255,0.07);
border-radius: 6px;
padding: 0.5em 0.8em;
font-size: 0.75em;
}
.agenda-item .num { font-size: 1.3em; font-weight: bold; color: #888; }
.emoji { font-style: normal; }
</style>
</head>
<body>
<div class="reveal">
<div class="slides">
<!-- ─── SLIDE 1 : Title ─────────────────────────────────────────── -->
<section class="title-slide">
<h1>⚙️ Configuration as Code</h1>
<p class="subtitle">Puppet · Ansible · Terraform<br>— What's the difference and when to use what? —</p>
<p class="meta">Finistère Dev Meetup · 2026</p>
</section>
<!-- ─── SLIDE 2 : Agenda ────────────────────────────────────────── -->
<section>
<h2>📋 Agenda</h2>
<div class="agenda-grid">
<div class="agenda-item"><span class="num">01</span><br>What is Configuration as Code?</div>
<div class="agenda-item"><span class="num">02</span><br>The IaC landscape</div>
<div class="agenda-item"><span class="num">03</span><br><span class="puppet-col">Puppet</span> — Declare your state</div>
<div class="agenda-item"><span class="num">04</span><br><span class="ansible-col">Ansible</span> — Automate everything</div>
<div class="agenda-item"><span class="num">05</span><br><span class="tf-col">Terraform</span> — Provision infrastructure</div>
<div class="agenda-item"><span class="num">06</span><br>Comparison & when to use what</div>
</div>
</section>
<!-- ─── SLIDE 3 : What is CaC ──────────────────────────────────── -->
<section>
<h2>🤔 What is Configuration as Code?</h2>
<div class="highlight-box">
Managing infrastructure and system configuration <strong>through machine-readable files</strong> stored in version control — just like application code.
</div>
<ul>
<li class="fragment"><strong>Reproducible</strong> — same result every time</li>
<li class="fragment"><strong>Versionable</strong> — Git history, pull requests, rollbacks</li>
<li class="fragment"><strong>Auditable</strong> — who changed what, and when</li>
<li class="fragment"><strong>Scalable</strong> — apply to 1 or 10 000 servers identically</li>
<li class="fragment"><strong>Collaborative</strong> — code review, CI/CD pipelines</li>
</ul>
</section>
<!-- ─── SLIDE 4 : IaC landscape ───────────────────────────────── -->
<section>
<h2>🌍 The IaC Landscape</h2>
<p>Three main problem spaces:</p>
<div class="card-row">
<div class="card card-puppet">
<h3>🐾 Configuration<br>Management</h3>
<ul>
<li>Install / configure software</li>
<li>Enforce desired state on servers</li>
<li><strong>Puppet, Chef, Salt</strong></li>
</ul>
</div>
<div class="card card-ansible">
<h3>⚡ Orchestration &amp;<br>Automation</h3>
<ul>
<li>Run tasks across many hosts</li>
<li>Deploy apps, pipelines</li>
<li><strong>Ansible, Fabric</strong></li>
</ul>
</div>
<div class="card card-tf">
<h3>🏗️ Infrastructure<br>Provisioning</h3>
<ul>
<li>Create VMs, networks, DNS…</li>
<li>Cloud-agnostic</li>
<li><strong>Terraform, Pulumi, OpenTofu</strong></li>
</ul>
</div>
</div>
</section>
<!-- ─── SLIDE 5 : Puppet overview ─────────────────────────────── -->
<section>
<h2>🐾 Puppet <span class="tag tag-puppet">Configuration Management</span></h2>
<ul>
<li><strong>Born:</strong> 2005 — one of the oldest IaC tools</li>
<li><strong>Language:</strong> Puppet DSL (Ruby-based) or YAML (Hiera)</li>
<li><strong>Model:</strong> <em>Pull</em> — agents poll a central Puppet Server every 30 min</li>
<li><strong>Approach:</strong> <em>Declarative</em> — you describe the desired state</li>
<li><strong>Agent required:</strong> Yes (puppet-agent on each node)</li>
</ul>
<div class="highlight-box" style="margin-top:0.8em;">
💡 Great for large fleets where <strong>continuous compliance</strong> and drift detection matter.
</div>
</section>
<!-- ─── SLIDE 6 : Puppet code ─────────────────────────────────── -->
<section>
<h2>🐾 Puppet — Example</h2>
<pre><code class="language-puppet" data-trim>
# manifests/webserver.pp
class webserver {
package { 'nginx':
ensure => installed,
}
file { '/etc/nginx/nginx.conf':
ensure => file,
content => template('webserver/nginx.conf.erb'),
notify => Service['nginx'],
}
service { 'nginx':
ensure => running,
enable => true,
}
}
</code></pre>
<p>🔁 Run again → <strong>idempotent</strong>: only changes what diverged from the desired state</p>
</section>
<!-- ─── SLIDE 7 : Ansible overview ───────────────────────────── -->
<section>
<h2>⚡ Ansible <span class="tag tag-ansible">Automation &amp; Orchestration</span></h2>
<ul>
<li><strong>Born:</strong> 2012, acquired by Red Hat in 2015</li>
<li><strong>Language:</strong> YAML (Playbooks)</li>
<li><strong>Model:</strong> <em>Push</em> — the control node connects via SSH</li>
<li><strong>Approach:</strong> <em>Procedural</em> (tasks run in order) with idempotent modules</li>
<li><strong>Agent required:</strong> <strong>No</strong> — agentless, just Python + SSH</li>
</ul>
<div class="highlight-box" style="margin-top:0.8em;">
💡 Great for <strong>ad-hoc tasks</strong>, app deployments, and quick automation without setup overhead.
</div>
</section>
<!-- ─── SLIDE 8 : Ansible code ───────────────────────────────── -->
<section>
<h2>⚡ Ansible — Example</h2>
<pre><code class="language-yaml" data-trim>
# playbook/webserver.yml
- name: Configure web server
hosts: webservers
become: true
tasks:
- name: Install nginx
ansible.builtin.package:
name: nginx
state: present
- name: Copy nginx config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx
- name: Ensure nginx is running
ansible.builtin.service:
name: nginx
state: started
enabled: true
handlers:
- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
</code></pre>
</section>
<!-- ─── SLIDE 9 : Terraform overview ─────────────────────────── -->
<section>
<h2>🏗️ Terraform <span class="tag tag-tf">Infrastructure Provisioning</span></h2>
<ul>
<li><strong>Born:</strong> 2014 by HashiCorp (open-source fork: <em>OpenTofu</em>)</li>
<li><strong>Language:</strong> HCL (HashiCorp Configuration Language)</li>
<li><strong>Model:</strong> <em>Plan → Apply</em> — preview changes before applying</li>
<li><strong>Approach:</strong> <em>Declarative</em> — describe your infrastructure graph</li>
<li><strong>Agent required:</strong> No — uses provider APIs (AWS, GCP, Azure, etc.)</li>
</ul>
<div class="highlight-box" style="margin-top:0.8em;">
💡 Great for <strong>creating and managing cloud resources</strong> — VMs, networks, DNS, databases…
</div>
</section>
<!-- ─── SLIDE 10 : Terraform code ────────────────────────────── -->
<section>
<h2>🏗️ Terraform — Example</h2>
<pre><code class="language-hcl" data-trim>
# main.tf
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" { region = "eu-west-3" }
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = { Name = "meetup-webserver" }
}
output "public_ip" {
value = aws_instance.web.public_ip
}
</code></pre>
<p>🗺️ <code>terraform plan</code> shows a diff · <code>terraform apply</code> creates resources · <code>terraform destroy</code> removes them</p>
</section>
<!-- ─── SLIDE 11 : Comparison table ──────────────────────────── -->
<section>
<h2>📊 Comparison at a Glance</h2>
<table class="comparison-table">
<thead>
<tr>
<th></th>
<th class="puppet-col">🐾 Puppet</th>
<th class="ansible-col">⚡ Ansible</th>
<th class="tf-col">🏗️ Terraform</th>
</tr>
</thead>
<tbody>
<tr><td>Primary focus</td><td>Config management</td><td>Automation / Orchestration</td><td>Infrastructure provisioning</td></tr>
<tr><td>Language</td><td>Puppet DSL</td><td>YAML</td><td>HCL</td></tr>
<tr><td>Approach</td><td>Declarative</td><td>Procedural + idempotent</td><td>Declarative</td></tr>
<tr><td>Push / Pull</td><td>Pull</td><td>Push</td><td>Push (via API)</td></tr>
<tr><td>Agent needed</td><td>Yes</td><td>No</td><td>No</td></tr>
<tr><td>State file</td><td>Catalog (server)</td><td>None (stateless)</td><td>Yes (.tfstate)</td></tr>
<tr><td>Cloud resources</td><td>Limited</td><td>Yes (modules)</td><td>Excellent</td></tr>
<tr><td>Learning curve</td><td>High</td><td>Low</td><td>Medium</td></tr>
</tbody>
</table>
</section>
<!-- ─── SLIDE 12 : When to use what ─────────────────────────── -->
<section>
<h2>🎯 When to Use What?</h2>
<div class="card-row">
<div class="card card-puppet">
<h3>🐾 Use Puppet when…</h3>
<ul>
<li>Large fleet (100s1000s of servers)</li>
<li>Continuous compliance / drift detection</li>
<li>Enterprise, strict governance</li>
<li>Long-running servers (pets)</li>
</ul>
</div>
<div class="card card-ansible">
<h3>⚡ Use Ansible when…</h3>
<ul>
<li>Agentless is a must</li>
<li>Quick automation or one-off tasks</li>
<li>App deployment & pipelines</li>
<li>Already using Red Hat / AWX</li>
</ul>
</div>
<div class="card card-tf">
<h3>🏗️ Use Terraform when…</h3>
<ul>
<li>Creating cloud infrastructure</li>
<li>Multi-cloud or hybrid environments</li>
<li>Preview changes before applying</li>
<li>Immutable infra (cattle, not pets)</li>
</ul>
</div>
</div>
</section>
<!-- ─── SLIDE 13 : They work together ───────────────────────── -->
<section>
<h2>🤝 They Work Together!</h2>
<div class="highlight-box">
These tools are <strong>complementary</strong>, not mutually exclusive.
</div>
<p>A common real-world stack:</p>
<ol>
<li class="fragment"><strong class="tf-col">Terraform</strong> provisions the VM on AWS/Azure/GCP</li>
<li class="fragment"><strong class="ansible-col">Ansible</strong> bootstraps the OS, installs base packages, deploys the app</li>
<li class="fragment"><strong class="puppet-col">Puppet</strong> continuously enforces compliance and manages config drift</li>
</ol>
<p class="fragment" style="margin-top:0.8em; font-style:italic; color:#aaa;">
→ Right tool for the right layer of the stack
</p>
</section>
<!-- ─── SLIDE 14 : Key Takeaways ────────────────────────────── -->
<section>
<h2>💡 Key Takeaways</h2>
<ul>
<li class="fragment">Configuration as Code → <strong>reproducible, auditable, scalable</strong> infrastructure</li>
<li class="fragment"><strong class="puppet-col">Puppet</strong> — continuous compliance on large server fleets (pull, agent)</li>
<li class="fragment"><strong class="ansible-col">Ansible</strong> — agentless automation & orchestration (push, YAML)</li>
<li class="fragment"><strong class="tf-col">Terraform</strong> — cloud infrastructure provisioning (plan/apply, HCL)</li>
<li class="fragment">They <strong>complement each other</strong> — choose based on the layer of your stack</li>
</ul>
</section>
<!-- ─── SLIDE 15 : Q&A ──────────────────────────────────────── -->
<section class="title-slide">
<h1>🙋 Questions?</h1>
<p class="subtitle">Thank you!</p>
<p class="meta" style="margin-top:2em;">
Slides made with <a href="https://revealjs.com" target="_blank">Reveal.js</a><br>
Finistère Dev Meetup · 2026
</p>
</section>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.js"></script>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/notes/notes.js"></script>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/highlight.js"></script>
<script>
Reveal.initialize({
hash: true,
slideNumber: 'c/t',
transition: 'slide',
backgroundTransition: 'fade',
controls: true,
progress: true,
center: false,
plugins: [ RevealNotes, RevealHighlight ]
});
</script>
</body>
</html>