Copyright
Table of Contents
Preface
How I Learned to Stop Worrying and to Love the Cloud
My First Virtual Server Farm
The Sorcerer’s Apprentice
Cloud from Scratch
Why I’m Writing This Book
Who This Book Is For
What Tools Are Covered
How to Read This Book
Conventions Used in This Book
Safari® Books Online
How to Contact Us
Acknowledgments
Part I. Foundations
Chapter 1. Challenges and Principles
Why Infrastructure as Code?
What Is Infrastructure as Code?
Goals of Infrastructure as Code
Challenges with Dynamic Infrastructure
Server Sprawl
Configuration Drift
Snowflake Servers
Fragile Infrastructure
Automation Fear
Erosion
Principles of Infrastructure as Code
Systems Can Be Easily Reproduced
Systems Are Disposable
Systems Are Consistent
Processes Are Repeatable
Design Is Always Changing
Practices
Use Definition Files
Self-Documented Systems and Processes
Version All the Things
Continuously Test Systems and Processes
Small Changes Rather Than Batches
Keep Services Available Continuously
Antifragility: Beyond “Robust”
The Secret Ingredient of Antifragile IT Systems
Conclusion
What’s Next?
Chapter 2. Dynamic Infrastructure Platforms
What Is a Dynamic Infrastructure Platform?
Requirements for a Dynamic Infrastructure Platform
Programmable
On-Demand
Self-Service
Infrastructure Resources Provided by the Platform
Compute Resources
Storage Resources
Network Resources
Types of Dynamic Infrastructure Platforms
Public IaaS Cloud
Community IaaS Cloud
Private IaaS Cloud
Antipattern: Hand-Cranked Cloud
Hybrid and Mixed Cloud Options
Bare-Metal Clouds
Deciding on a Dynamic Infrastructure Platform
Public or Private?
Cloud Portability
Mechanical Sympathy with the Cloud and Virtualization
Conclusion
Chapter 3. Infrastructure Definition Tools
Choosing Tools for Infrastructure as Code
Requirement: Scriptable Interface
Requirement: Unattended Mode for Command-Line Tools
Requirement: Support for Unattended Execution
Requirement: Externalized Configuration
Configuration Definition Files
Reusability with Configuration Definitions
Working with Infrastructure Definition Tools
Provisioning Infrastructure with Procedural Scripts
Defining Infrastructure Declaratively
Using Infrastructure Definition Tools
Configuring Servers
Configuration Registries
Lightweight Configuration Registries
Is a Configuration Registry a CMDB?
The CMDB Audit and Fix Antipattern
The Infrastructure-as-Code Approach to CMDB
Conclusion
Chapter 4. Server Configuration Tools
Goals for Automated Server Management
Tools for Different Server Management Functions
Tools for Creating Servers
Tools for Configuring Servers
Tools for Packaging Server Templates
Tools for Running Commands on Servers
Using Configuration from a Central Registry
Server Change Management Models
Ad Hoc Change Management
Configuration Synchronization
Immutable Infrastructure
Containerized Services
Containers
Managing Ruby Applications with and without Containers
Are Containers Virtual Machines?
Using Containers Rather than Virtual Machines
Running Containers
Security and Containers
Conclusion
Chapter 5. General Infrastructure Services
Considerations for Infrastructure Services and Tools
Prefer Tools with Externalized Configuration
Prefer Tools That Assume Infrastructure Is Dynamic
Prefer Products with Cloud-Compatible Licensing
Prefer Products That Support Loose Coupling
Sharing a Service Between Teams
Service Instance Templates
Monitoring: Alerting, Metrics, and Logging
Alerting: Tell Me When Something Is Wrong
Metrics: Collect and Analyze Data
Log Aggregation and Analysis
Service Discovery
Server-Side Service Discovery Pattern
Client-Side Service Discovery Pattern
Distributed Process Management
Orchestrating Processes with Server Roles
Orchestrating Processes with Containers
Scheduling Short Jobs
Container Orchestration Tools
Software Deployment
Deployment Pipeline Software
Packaging Software
Conclusion
Part II. Patterns
Chapter 6. Patterns for Provisioning Servers
Server Provisioning
A Server’s Life
What Goes onto a Server
Types of Things on a Server
Server Roles
Patterns for Creating Servers
Antipattern: Handcrafted Server
Practice: Wrap Server Creation Options in a Script
Antipattern: Hot Cloned Server
Pattern: Server Template
Antipattern: Snowflake Factory
Patterns for Bootstrapping New Servers
Pushing to Bootstrap
Pulling to Bootstrap
Practice: Smoke Test Every New Server Instance
Conclusion
Chapter 7. Patterns for Managing Server Templates
Stock Templates: Can’t Someone Else Do It?
Provisioning Servers Using Templates
Provisioning at Creation Time
Provisioning in the Template
Balancing Provisioning Across Template and Creation
The Process for Building a Server Template
Creating Templates for Multiple Platforms
Origin Images
Antipattern: Hot Cloned Server Template
Baking a Template from an OS Installation Image
Baking a Template from a Stock Image
Building a Template from a Unikernel
Customizing a Server Template without Booting It
Updating Server Templates
Reheating a Template
Baking a Fresh Template
Versioning Server Templates
Building Templates for Roles
Pattern: Layered Template
Sharing Base Scripts for Templates
Automating Server Template Management
Customizing Servers Before Baking
Practice: Automatically Test Server Templates
Conclusion
Chapter 8. Patterns for Updating and Changing Servers
Models for Server Change Management
Ad Hoc Change Management
Continuous Configuration Synchronization
Immutable Servers
Containerized Servers
General Patterns and Practices
Practice: Minimize Server Templates
Practice: Replace Servers When the Server Template Changes
Pattern: Phoenix Servers
Patterns and Practices for Continuous Deployment
Pattern: Masterless Configuration Management
Practice: Apply Cron
Continuous Synchronization Flow
The Unconfigured Country
Patterns and Practices for Immutable Servers
Server Image as Artifact
Simplifying Confirmation Management Tooling with Immutable Servers
Immutable Server Flow
Bootstrap Configuration with Immutable Servers
Transactional Server Updates
Practices for Managing Configuration Definitions
Practice: Keep Configuration Definitions Minimal
Organizing Definitions
Practice: Use Test-Driven Development (TDD) to Drive Good Design
Conclusion
Chapter 9. Patterns for Defining Infrastructure
Environments
Antipattern: Handcrafted Infrastructure
Defining Infrastructure Stacks as Code
Antipattern: Per-Environment Definition Files
Pattern: Reusable Definition Files
Practice: Test and Promote Stack Definitions
Self-Service Environments
Organizing Infrastructure
Antipattern: Monolithic Stack
Avoid “Lift and Shift” When Migrating Infrastructure
Dividing an Application Environment into Multiple Stacks
Managing Configuration Parameters Between Stacks
Sharing Infrastructure Elements
Practice: Manage Application Code and Infrastructure Code Together
Approaches to Sharing Definitions
Practice: Align Infrastructure Design with the Scope of Change
Example: An Infrastructure Design for Microservices
Running Definition Tools
Conclusion
Part III. Practices
Chapter 10. Software Engineering Practices for Infrastructure
System Quality
Poor-Quality Systems Are Difficult to Change
High-Quality Systems Are Easier and Safer to Change
Infrastructure Quality Through Code
Fast Feedback
VCS for Infrastructure Management
What to Manage in a VCS
Continuous Integration (CI)
Continuously Testing Branches Is Not Continuous Integration
Who Broke the Build?
Ignoring Tests That Fail
CI for Infrastructure
Continuous Delivery (CD)
The Problem with the Integration Phase
Deployment Pipelines and Change Pipelines
Continuous Delivery Is Not Continuous Deployment
Code Quality
Clean Code
Practice: Manage Technical Debt
Managing Major Infrastructure Changes
Feature Toggles
Conclusion
Chapter 11. Testing Infrastructure Changes
The Agile Approach to Testing
Automating Tests for Fast Feedback
Organically Building a Test Suite
Structuring the Test Suite: The Test Pyramid
Avoiding an Unbalanced Test Suite
Practice: Test at the Lowest Level Possible
Practice: Only Implement the Layers You Need
Practice: Prune the Test Suite Often
Practice: Continuously Review Testing Effectiveness
Implementing a Balanced Test Suite
Low-Level Testing
Mid-Level Testing
Higher-Level Tests
Testing Operational Quality
Managing Test Code
Practice: Keep Test Code with the Code It Tests
Anti-Pattern: Reflective Tests
Techniques to Isolate Components for Testing
Refactoring Components so They Can Be Isolated
Managing External Dependencies
Test Setup
Roles and Workflow for Testing
Principle: People Should Write Tests for What They Build
The Test-Writing Habit
Principle: Everyone Should Have Access to the Testing Tools
The Value of a Quality Analyst
Test-Driven Development (TDD)
Conclusion
Chapter 12. Change Management Pipelines for Infrastructure
Benefits of a Change Management Pipeline
Guidelines for Designing Pipelines
Ensure Consistency Across Stages
Get Immediate Feedback for Every Change
Run Automated Stages Before Manual Stages
Get Production-Like Sooner Rather Than Later
Basic Pipeline Designs
The Local Development Stage
The Build Stage
Publishing a Configuration Artifact
Automated Testing Stages
Manual Validation Stages
Apply to Live
The Rhythm of the Pipeline
Practices for Using a Pipeline
Practice: Prove Production Readiness for Every Change
Practice: Start Every Change from the Beginning of the Pipeline
Practice: Stop the Line on Any Failure
Scaling Pipelines to More Complex Systems
Pattern: Fan-In Pipelines
Practice: Keep Pipelines Short
Practice: Decouple Pipelines
Integration Models
Techniques for Handling Dependencies Between Components
Pattern: Library Dependency
Pattern: Self-Provisioned Service Instance
Providing Pre-Release Library Builds
Providing Test Instances of a Service to Consumers
Using Test Instances of a Service as a Consumer
Practices for Managing Interfaces Between Components
Practice: Ensure Backward Compatibility of Interfaces
Practice: Decouple Deploying from Releasing
Practice: Use Version Tolerance
Practice: Provide Test Doubles
Practice: Test the Provider with Contract Tests
Practice: Test with a Reference Consumer
Practice: Smoke Test the Provider Interface
Practice: Run Consumer-Driven Contract (CDC) Tests
Conclusion
Chapter 13. Workflow for the Infrastructure Team
Automate Anything That Moves
Make the Change Manually
Ad Hoc Automation
Autonomic Automation
Autonomic Automation Workflow
Using a Local Sandbox
Using Local Virtualization for a Sandbox
Example Workflow with Local Testing
Using the Virtualization Platform for Sandboxes
Codebase Organization Patterns
Antipattern: Branch-Based Codebases
Pattern: One Trunk per Component
Pattern: Single Trunk
Workflow Effectiveness
Expediting Changes
Code Reviews
Fitting Governance into the Workflow
Conclusion
Chapter 14. Continuity with Dynamic Infrastructure
Service Continuity
True Availability
Using Dynamic Server Pools for Recovery
Software Design for Dynamic Infrastructure
Compartmentalizing for Continuity
Zero-Downtime Changes
Pattern: Blue-Green Replacement
Pattern: Phoenix Replacement
Practice: Reduce the Scope of Replacement
Pattern: Canary Replacement
Routing Traffic for Zero-Downtime Replacements
Zero-Downtime Changes with Data
Data Continuity
Replicating Data Redundantly
Regenerating Data
Delegating Data Persistence
Backing Up to Persistent Storage
Disaster Recovery
Continuous Disaster Recovery
The DR Plan: Planning for Disaster
Practice: Prefer Rebuilding Things over Cold Standby
Continuous Monitoring through the Pipeline
Security
Automatically Papering over Compromises
Reliable Updates as a Defense
Provenance of Packages
Automated Hardening
Automating Security Validation in the Pipeline
The Change Pipeline as a Vulnerability
Managing Security Risks with Cloud Accounts
Conclusion
Chapter 15. Organizing for Infrastructure as Code
Evolutionary Architecture
Learning under Fire
Start with a Trailblazer Pipeline
Measuring Effectiveness
Agree on Desired Outcomes First
Choose Metrics that Help the Team
Track and Improve Cycle Time
Use Kanban to Make Work Visible
Retrospectives and Post-Mortems
Organize to Empower Users
Pitfalls of the Divided Function Model
Adopt a Self-Service Model
Take Full Responsibility: You Build It, You Run It
Organizing into Cross-Functional Teams
Governance through Continuous Change Management
Provide Solid Building Blocks
Prove Operational Readiness in the Pipeline
Sharing Ownership of Operational Quality
Review and Audit Automated Processes
Optimize for Time to Detect and Fix Problems
Conclusion: It’s Never Finished
Index
About the Author
Colophon