Infrastructure as Code: Dynamic Systems for the Cloud Age [2 ed.] 9781098114671

Six years ago, Infrastructure as Code was a new concept. Today, as even banks and other conservative organizations plan

735 182 1MB

English Pages [430] Year 2021

Report DMCA / Copyright

DOWNLOAD FILE

Infrastructure as Code: Dynamic Systems for the Cloud Age [2 ed.]
 9781098114671

Table of contents :
Cover
Copyright
Table of Contents
Preface
Why I Wrote This Book
What’s New and Different in This Edition
What’s Next
What This Book Is and Isn’t
Some History of Infrastructure as Code
Who This Book Is For
Principles, Practices, and Patterns
The ShopSpinner Examples
Conventions Used in This Book
O’Reilly Online Learning
How to Contact Us
Acknowledgments
Part I. Foundations
Chapter 1. What Is Infrastructure as Code?
From the Iron Age to the Cloud Age
Infrastructure as Code
Benefits of Infrastructure as Code
Use Infrastructure as Code to Optimize for Change
Objection: “We don’t make changes often enough to justify automating them”
Objection: “We should build first and automate later”
Objection: “We must choose between speed and quality”
The Four Key Metrics
Three Core Practices for Infrastructure as Code
Core Practice: Define Everything as Code
Core Practice: Continuously Test and Deliver All Work in Progress
Core Practice: Build Small, Simple Pieces That You Can Change Independently
Conclusion
Chapter 2. Principles of Cloud Age Infrastructure
Principle: Assume Systems Are Unreliable
Principle: Make Everything Reproducible
Pitfall: Snowflake Systems
Principle: Create Disposable Things
Principle: Minimize Variation
Configuration Drift
Principle: Ensure That You Can Repeat Any Process
Conclusion
Chapter 3. Infrastructure Platforms
The Parts of an Infrastructure System
Infrastructure Platforms
Infrastructure Resources
Compute Resources
Storage Resources
Network Resources
Conclusion
Chapter 4. Core Practice: Define Everything as Code
Why You Should Define Your Infrastructure as Code
What You Can Define as Code
Choose Tools with Externalized Configuration
Manage Your Code in a Version Control System
Infrastructure Coding Languages
Infrastructure Scripting
Declarative Infrastructure Languages
Programmable, Imperative Infrastructure Languages
Declarative Versus Imperative Languages for Infrastructure
Domain-Specific Infrastructure Languages
General-Purpose Languages Versus DSLs for Infrastructure
Implementation Principles for Defining Infrastructure as Code
Separate Declarative and Imperative Code
Treat Infrastructure Code Like Real Code
Conclusion
Part II. Working with Infrastructure Stacks
Chapter 5. Building Infrastructure Stacks as Code
What Is an Infrastructure Stack?
Stack Code
Stack Instance
Configuring Servers in a Stack
Low-Level Infrastructure Languages
High-Level Infrastructure Languages
Patterns and Antipatterns for Structuring Stacks
Antipattern: Monolithic Stack
Pattern: Application Group Stack
Pattern: Service Stack
Pattern: Micro Stack
Conclusion
Chapter 6. Building Environments with Stacks
What Environments Are All About
Delivery Environments
Multiple Production Environments
Environments, Consistency, and Configuration
Patterns for Building Environments
Antipattern: Multiple-Environment Stack
Antipattern: Copy-Paste Environments
Pattern: Reusable Stack
Building Environments with Multiple Stacks
Conclusion
Chapter 7. Configuring Stack Instances
Using Stack Parameters to Create Unique Identifiers
Example Stack Parameters
Patterns for Configuring Stacks
Antipattern: Manual Stack Parameters
Pattern: Stack Environment Variables
Pattern: Scripted Parameters
Pattern: Stack Configuration Files
Pattern: Wrapper Stack
Pattern: Pipeline Stack Parameters
Pattern: Stack Parameter Registry
Configuration Registry
Implementing a Configuration Registry
Single or Multiple Configuration Registries
Handling Secrets as Parameters
Encrypting Secrets
Secretless Authorization
Injecting Secrets at Runtime
Disposable Secrets
Conclusion
Chapter 8. Core Practice: Continuously Test and Deliver
Why Continuously Test Infrastructure Code?
What Continuous Testing Means
What Should We Test with Infrastructure?
Challenges with Testing Infrastructure Code
Challenge: Tests for Declarative Code Often Have Low Value
Challenge: Testing Infrastructure Code Is Slow
Challenge: Dependencies Complicate Testing Infrastructure
Progressive Testing
Test Pyramid
Swiss Cheese Testing Model
Infrastructure Delivery Pipelines
Pipeline Stages
Scope of Components Tested in a Stage
Scope of Dependencies Used for a Stage
Platform Elements Needed for a Stage
Delivery Pipeline Software and Services
Testing in Production
What You Can’t Replicate Outside Production
Managing the Risks of Testing in Production
Conclusion
Chapter 9. Testing Infrastructure Stacks
Example Infrastructure
The Example Stack
Pipeline for the Example Stack
Offline Testing Stages for Stacks
Syntax Checking
Offline Static Code Analysis
Static Code Analysis with API
Testing with a Mock API
Online Testing Stages for Stacks
Preview: Seeing What Changes Will Be Made
Verification: Making Assertions About Infrastructure Resources
Outcomes: Proving Infrastructure Works Correctly
Using Test Fixtures to Handle Dependencies
Test Doubles for Upstream Dependencies
Test Fixtures for Downstream Dependencies
Refactor Components So They Can Be Isolated
Life Cycle Patterns for Test Instances of Stacks
Pattern: Persistent Test Stack
Pattern: Ephemeral Test Stack
Antipattern: Dual Persistent and Ephemeral Stack Stages
Pattern: Periodic Stack Rebuild
Pattern: Continuous Stack Reset
Test Orchestration
Support Local Testing
Avoid Tight Coupling with Pipeline Tools
Test Orchestration Tools
Conclusion
Part III. Working with Servers and Other Application Runtime Platforms
Chapter 10. Application Runtimes
Cloud Native and Application-Driven Infrastructure
Application Runtime Targets
Deployable Parts of an Application
Deployment Packages
Deploying Applications to Servers
Packaging Applications in Containers
Deploying Applications to Server Clusters
Deploying Applications to Application Clusters
Packages for Deploying Applications to Clusters
Deploying FaaS Serverless Applications
Application Data
Data Schemas and Structures
Cloud Native Application Storage Infrastructure
Application Connectivity
Service Discovery
Conclusion
Chapter 11. Building Servers as Code
What’s on a Server
Where Things Come From
Server Configuration Code
Server Configuration Code Modules
Designing Server Configuration Code Modules
Versioning and Promoting Server Code
Server Roles
Testing Server Code
Progressively Testing Server Code
What to Test with Server Code
How to Test Server Code
Creating a New Server Instance
Hand-Building a New Server Instance
Using a Script to Create a Server
Using a Stack Management Tool to Create a Server
Configuring the Platform to Automatically Create Servers
Using a Networked Provisioning Tool to Build a Server
Prebuilding Servers
Hot-Cloning a Server
Using a Server Snapshot
Creating a Clean Server Image
Configuring a New Server Instance
Frying a Server Instance
Baking Server Images
Combining Baking and Frying
Applying Server Configuration When Creating a Server
Conclusion
Chapter 12. Managing Changes to Servers
Change Management Patterns: When to Apply Changes
Antipattern: Apply On Change
Pattern: Continuous Configuration Synchronization
Pattern: Immutable Server
How to Apply Server Configuration Code
Pattern: Push Server Configuration
Pattern: Pull Server Configuration
Other Server Life Cycle Events
Stopping and Restarting a Server Instance
Replacing a Server Instance
Recovering a Failed Server
Conclusion
Chapter 13. Server Images as Code
Building a Server Image
Why Build a Server Image?
How to Build a Server Image
Tools for Building Server Images
Online Image Building Process
Offline Image Building Process
Origin Content for a Server Image
Building from a Stock Server Image
Building a Server Image from Scratch
Provenance of a Server Image and its Content
Changing a Server Image
Reheating or Baking a Fresh Image
Versioning a Server Image
Updating Server Instances When an Image Changes
Providing and Using a Server Image Across Teams
Handling Major Changes to an Image
Using a Pipeline to Test and Deliver a Server Image
Build Stage for a Server Image
Test Stage for a Server Image
Delivery Stages for a Server Image
Using Multiple Server Images
Server Images for Different Infrastructure Platforms
Server Images for Different Operating Systems
Server Images for Different Hardware Architectures
Server Images for Different Roles
Layering Server Images
Sharing Code Across Server Images
Conclusion
Chapter 14. Building Clusters as Code
Application Cluster Solutions
Cluster as a Service
Packaged Cluster Distribution
Stack Topologies for Application Clusters
Monolithic Stack Using Cluster as a Service
Monolithic Stack for a Packaged Cluster Solution
Pipeline for a Monolithic Application Cluster Stack
Example of Multiple Stacks for a Cluster
Sharing Strategies for Application Clusters
One Big Cluster for Everything
Separate Clusters for Delivery Stages
Clusters for Governance
Clusters for Teams
Service Mesh
Infrastructure for FaaS Serverless
Conclusion
Part IV. Designing Infrastructure
Chapter 15. Core Practice: Small, Simple Pieces
Designing for Modularity
Characteristics of Well-Designed Components
Rules for Designing Components
Use Testing to Drive Design Decisions
Modularizing Infrastructure
Stack Components Versus Stacks as Components
Using a Server in a Stack
Drawing Boundaries Between Components
Align Boundaries with Natural Change Patterns
Align Boundaries with Component Life Cycles
Align Boundaries with Organizational Structures
Create Boundaries That Support Resilience
Create Boundaries That Support Scaling
Align Boundaries to Security and Governance Concerns
Conclusion
Chapter 16. Building Stacks from Components
Infrastructure Languages for Stack Components
Reuse Declarative Code with Modules
Dynamically Create Stack Elements with Libraries
Patterns for Stack Components
Pattern: Facade Module
Antipattern: Obfuscation Module
Antipattern: Unshared Module
Pattern: Bundle Module
Antipattern: Spaghetti Module
Pattern: Infrastructure Domain Entity
Building an Abstraction Layer
Conclusion
Chapter 17. Using Stacks as Components
Discovering Dependencies Across Stacks
Pattern: Resource Matching
Pattern: Stack Data Lookup
Pattern: Integration Registry Lookup
Dependency Injection
Conclusion
Part V. Delivering Infrastructure
Chapter 18. Organizing Infrastructure Code
Organizing Projects and Repositories
One Repository, or Many?
One Repository for Everything
A Separate Repository for Each Project (Microrepo)
Multiple Repositories with Multiple Projects
Organizing Different Types of Code
Project Support Files
Cross-Project Tests
Dedicated Integration Test Projects
Organize Code by Domain Concept
Organizing Configuration Value Files
Managing Infrastructure and Application Code
Delivering Infrastructure and Applications
Testing Applications with Infrastructure
Testing Infrastructure Before Integrating
Using Infrastructure Code to Deploy Applications
Conclusion
Chapter 19. Delivering Infrastructure Code
Delivering Infrastructure Code
Building an Infrastructure Project
Packaging Infrastructure Code as an Artifact
Using a Repository to Deliver Infrastructure Code
Integrating Projects
Pattern: Build-Time Project Integration
Pattern: Delivery-Time Project Integration
Pattern: Apply-Time Project Integration
Using Scripts to Wrap Infrastructure Tools
Assembling Configuration Values
Simplifying Wrapper Scripts
Conclusion
Chapter 20. Team Workflows
The People
Who Writes Infrastructure Code?
Applying Code to Infrastructure
Applying Code from Your Local Workstation
Applying Code from a Centralized Service
Personal Infrastructure Instances
Source Code Branches in Workflows
Preventing Configuration Drift
Minimize Automation Lag
Avoid Ad Hoc Apply
Apply Code Continuously
Immutable Infrastructure
Governance in a Pipeline-based Workflow
Reshuffling Responsibilities
Shift Left
An Example Process for Infrastructure as Code with Governance
Conclusion
Chapter 21. Safely Changing Infrastructure
Reduce the Scope of Change
Small Changes
Example of Refactoring
Pushing Incomplete Changes to Production
Parallel Instances
Backward Compatible Transformations
Feature Toggles
Changing Live Infrastructure
Infrastructure Surgery
Expand and Contract
Zero Downtime Changes
Continuity
Continuity by Preventing Errors
Continuity by Fast Recovery
Continuous Disaster Recovery
Chaos Engineering
Planning for Failure
Data Continuity in a Changing System
Lock
Segregate
Replicate
Reload
Mixing Data Continuity Approaches
Conclusion
Index
About the Author
Colophon

Polecaj historie