Preface
1. Introduction to Cloud Native
Distributed Systems
Fallacies of Distributed Systems
CAP Theorem
The Twelve-Factor App
Availability and Service-Level Agreements
Summary
2. Fundamentals
Containers
Container Isolation Levels
Container Orchestration
Kubernetes Overview
Kubernetes and Containers
Serverless Computing
Functions
From VMs to Cloud Native
Lift-and-Shift
Application Modernization
Application Optimization
Microservices
Benefits of a Microservices Architecture
Challenges with a Microservices Architecture
Summary
3. Designing Cloud Native Applications
Fundamentals of Cloud Native Applications
Operational Excellence
Security
Reliability and Availability
Scalability and Cost
Cloud Native versus Traditional Architectures
Functions versus Services
Function Scenarios
Considerations for Using Functions
Composite of Functions and Services
API Design and Versioning
API Backward and Forward Compatibility
Semantic Versioning
Service Communication
Protocols
Messaging Protocols
Serialization Considerations
Idempotency
Request/Response
Publisher/Subscriber
Choosing Between Pub/Sub and Request Response
Synchronous versus Asynchronous
Gateways
Routing
Aggregation
Offloading
Implementing Gateways
Egress
Service Mesh
Example Architecture
Summary
4. Working with Data
Data Storage Systems
Objects, Files, and Disks
Databases
Streams and Queues
Blockchain
Selecting a Datastore
Data in Multiple Datastores
Change Data Capture
Write Changes as an Event to a Change Log
Transaction Supervisor
Compensating Transactions
Extract, Transform, and Load
Microservices and Data Lakes
Client Access to Data
Restricted Client Tokens (Valet-Key)
Database Services with Fine-Grained Access Control
GraphQL Data Service
Fast Scalable Data
Sharding Data
Caching Data
Content Delivery Networks
Analyzing Data
Streams
Batch
Data Lakes on Object Storage
Data Lakes and Data Warehouses
Distributed Query Engines
Databases on Kubernetes
Storage Volumes
StatefulSets
DaemonSets
Summary
5. DevOps
What Is DevOps?
Collaboration
Automation
Lean Principles and Processes
Measurement
Sharing
Testing
Test Doubles
Test Automation Pyramid
When to Run Which Types of Tests
Testing Cadence
Testing in Production
Development Environments and Tools
Development Tools
Development Environments
Local Development Environments
Local Development with a Remote Cluster
Skaffold Development Workflow
Remote Cluster Routed to Local Development
Cloud Development Environments
CI/CD
Source Code Control
Build Stage (CI)
Test Stage (CI)
Deploy Stage (CD)
Release Stage (CD)
Post-Release Stage
Monitoring
Collecting Metrics
Observable Services
Confguration Management
Single-Environment Variable
Multiple-Environment Variables
Adding ConfigMap Data to a Volume
Storing Secrets
Deployment Configuration
Sample CI/CD Flows
Summary
6. Best Practices
Moving to Cloud Native
Breaking Up the Monolith for the Right Reasons
Decouple Simple Services First
Learn to Operate on a Small Scale
Use an Anticorruption Layer Pattern
Use a Strangler Pattern
Come Up with a Data Migration Strategy
Rewrite Any Boilerplate Code
Reconsider Frameworks, Languages, Data Structures, and Datastores
Retire Code
Ensuring Resiliency
Handle Transient Failures with Retries
Use a Finite Number of Retries
Use Circuit Breakers for Nontransient Failures
Graceful Degradation
Use a Bulkhead Pattern
Implement Health Checks and Readiness Checks
Define CPU and Memory Limits for Your Containers
Implement Rate Limiting and Throttling
Ensuring Security
Treat Security Requirements the Same as Any Other Requirements
Incorporate Security in Your Designs
Grant Least-Privileged Access
Use Separate Accounts/Subscriptions/Tenants
Securely Store All Secrets
Obfuscat