Project 2: Idempotent Web Tier Bootstrap
Converge package and service state reliably so repeated runs remain stable.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 1 |
| Time Estimate | 6-10 hours |
| Main Programming Language | YAML (Ansible playbook) |
| Alternatives | Shell (for comparison only) |
| Coolness | Level 2 |
| Business Potential | 2. Micro-SaaS / Pro Tool |
| Prerequisites | P01 inventory baseline |
| Key Topics | Desired state, idempotency, service management |
1. Learning Objectives
- Build your first convergent playbook.
- Prove idempotency by comparing first and second run recaps.
- Separate package installation concerns from service lifecycle concerns.
- Document deterministic verification for web tier readiness.
2. All Theory Needed (Per-Concept Breakdown)
2.1 Desired State vs Imperative Steps
Fundamentals Imperative scripts run steps; desired-state automation asserts outcomes. Idempotent modules compute drift and apply only required changes.
Deep Dive into the concept In production, partial failures are normal. Desired-state automation makes reruns safe. Imperative scripts often cannot distinguish already-correct state from missing state, causing duplicate side effects.
How this fit on projects Core to P02, reused in P03, P06, P07.
Definitions & key terms
- Convergence
- Drift
- Changed vs ok
Mental model diagram
declared state -> compare -> mutate only if mismatch -> stable rerun
How it works
- Read package/service status.
- Apply minimal changes.
- Report
changedonly on real mutation.
Minimal concrete example
# pseudocode
- ensure package: present
- ensure service: started + enabled
Common misconceptions
- “First success means automation is done.”
Check-your-understanding questions
- Why is second-run stability the key test?
Check-your-understanding answers
- It proves drift correction rather than repeated mutation.
References
- Ansible desired state docs.
3. Project Specification
3.1 What You Will Build
A web bootstrap playbook that:
- installs web package
- ensures service enabled and running
- validates endpoint or service state
3.2 Functional Requirements
- First run converges from blank state.
- Second run shows no unnecessary change.
- Service check passes on all target hosts.
3.3 Non-Functional Requirements
- Reliability: safe reruns.
- Portability: supports at least two Linux families.
- Clarity: readable task names and outputs.
3.4 Example Usage / Output
$ ansible-playbook -i inventory.ini web_bootstrap.yml
... changed=2 failed=0
$ ansible-playbook -i inventory.ini web_bootstrap.yml
... changed=0 failed=0
3.7 Real World Outcome
3.7.1 How to Run
ansible-playbook -i inventory.ini web_bootstrap.yml --check --diff
ansible-playbook -i inventory.ini web_bootstrap.yml
ansible-playbook -i inventory.ini web_bootstrap.yml
3.7.2 Golden Path Demo
First run changes state. Second run is stable.
3.7.3 Failure Demo
If service package name is wrong, task fails with explicit package-not-found message and no hidden retries.
4. Solution Architecture
4.1 High-Level Design
inventory -> package convergence -> service convergence -> verification
4.2 Key Components
| Component | Responsibility | Decision |
|---|---|---|
| Package task | Install required package | Use module, not shell |
| Service task | Start + enable | explicit state |
| Verification | Check readiness | deterministic output |
5. Implementation Guide
5.3 The Core Question You’re Answering
“Can this baseline playbook be rerun indefinitely without operational noise?”
5.4 Concepts You Must Understand First
- Desired state semantics.
- Module idempotency model.
- Service startup/enable differences.
5.5 Questions to Guide Your Design
- Which tasks should ever be
changedafter steady state? - How do you verify readiness beyond process-up?
5.6 Thinking Exercise
Map expected recap counts for first run vs second run.
5.7 The Interview Questions They’ll Ask
- How do you prove idempotency?
- Why avoid shell wrappers for package installs?
- What is safe rollback for this change?
5.8 Hints in Layers
- Hint 1: Add
becomewhere needed. - Hint 2: Keep package names variable-driven.
- Hint 3: Validate service state after converge.
- Hint 4: Preserve both run recaps as evidence.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Ansible basics | Ansible for DevOps | playbook intro |
| Linux services | How Linux Works | service management |
5.10 Implementation Phases
- Phase 1: package convergence.
- Phase 2: service convergence.
- Phase 3: idempotency verification.
6. Testing Strategy
6.2 Critical Test Cases
- Clean host first run.
- Immediate second run.
- Host with preinstalled package and stopped service.
7. Common Pitfalls & Debugging
| Pitfall | Symptom | Solution |
|---|---|---|
| Wrong package name | package task fails | OS-family variable map |
| unconditional restart | service changes every run | handler or explicit state |
8. Extensions & Challenges
- Add distro-aware package abstraction.
- Add HTTP health endpoint verification.
- Add canary-only mode using limit/serial.
9. Real-World Connections
This pattern is the foundation for every baseline server role in production platform teams.
10. Resources
- Ansible playbook docs
- Ansible check mode docs
- Ansible package/service module docs
11. Self-Assessment Checklist
- I can explain why run two is stable.
- I can explain each changed result.
- I can recover from a partial failure safely.
12. Submission / Completion Criteria
Minimum: convergent playbook + two run recaps.
Full: includes validation and distro variance notes.
Excellence: includes measurable runtime and zero-noise steady state.