Table of Contents
Foreword xv
Preface xvii
Acknowledgments xix
About this book xxi
About the author xxv
About the cover illustration xxvi
Part 1 The Cloud-Native Context 1
1 You keep using that word: Defining "cloud-native" 3
1.1 Today's application requirements 7
Zero downtime 7
Shortened feedback cycles 7
Mobile and multidevice support 8
Connected devices-also known as the Internet of Things 8
Data-driven 9
1.2 Introducing cloud-native software 10
Defining "cloud-native" 10
A mental model for cloud-native software 12
Cloud-native software in action 17
1.3 Cloud-native and world peace 21
Cloud and cloud-native 21
What isn't cloud-native 22
Cloud-native plays nice 23
2 Running cloud-native applications in production 26
2.1 The obstacles 27
Snowflakes 29
Risky defrayments 30
Change is the exception 34
Production instability 34
2.2 The enablers 35
Continuous delivery 36
Repeatability 40
Safe deployments 44
Change is the rule 48
3 The platform for cloud-native software 51
3.1 The cloud (-native) platform evolution 52
It started with the cloud 53
Cloud-native dial tone 54
3.2 Core tenets of the cloud-native platform 57
First, let's talk about containers 58
Support for "constantly changing" 59
Support for "highly distributed" 62
3.3 Who does what? 65
3.4 More cloud-native platform capabilities 68
The platform supports the entire SDLC 68
Security, change-control, compliance (the control functions) 71
Controlling what goes into the container 73
Upgrading and patching vulnerabilities 75
Change control 77
Part 2 Cloud-Native Patterns 81
4 Event-driven microservices: It's not just request/response 83
4.1 We're (usually) taught imperative programming 84
4.2 Reintroducing event-driven computing 86
4.3 My global cookbook 87
Request/response 88
Event-driven 94
4.4 Introducing Command Query Responsibility Segregation 103
4.5 Different styles, similar challenges 105
5 App redundancy: Scale-out and statelessness 108
5.1 Cloud-native apps have many instances deployed 110
5.2 Stateful apps in the cloud 112
Decomposing the monolith and binding to the database 112
Poorly handling session state 115
5.3 HTTP sessions and sticky sessions 129
5.4 Stateful services and stateless apps 131
Stateful services are special services 131
Making apps stateless 133
6 Application configuration: Not just environment variables 139
6.1 Why are we even talking about config? 140
Dynamic scaling-increasing and decreasing the number of app instances 141
Infrastructure changes causing configuration changes 141
Updating application configuration with zero downtime 142
6.2 The app's configuration layer 144
6.3 Injecting system/environment values 148
Let's see this in action: Using ENV variables for configuration 148
6.4 Injecting application configuration 157
Introducing the configuration server 158
Security adds more requirements 165
Let's see this in action: Application configuration using a config server 166
7 The application lifecycle: Accounting for constant change 170
7.1 Having empathy for operations 172
7.2 Single-app lifecycle, multiple-instance lifecycles 173
Blue/green upgrades 176
Rolling upgrades 178
Parallel deployments 179
7.3 Coordinating across different app lifecycles 181
7.4 Let's see this in action: Credential rotation and app lifecycle 185
7.5 Dealing with ephemeral runtime environments 194
7.6 Visibility of app lifecycle state 196
Let's see this in action: Health endpoints and probes 201
7.7 Serverless 204
8 Accessing apps: Services, routing, and service discovery 207
8.1 The service abstraction 210
Service example: Googling 211
Service example: Our blog aggregator 213
8.2 Dynamic routing 214
Sewer-side load balancing 214
Client-side load balancing 215
Route freshness 216
8.3 Service discovery 219
Service discovery on the web 222
Service discovery with client-side load balancing 223
Service discovery in Kubernetes 224
Let's see this in action: Using service discovery 226
9 Interaction redundancy: Retries and other control loops 231
9.1 Request retries 233
The basic request retry 233
Let's see this in action: Simple retries 234
Retries: what could go wrong? 238
Creating a retry storm 240
Let's see this in action: Creating a retry storm 240
Avoiding retry storms: Kind clients 250
Let's see this in action: being a kinder client 251
When not to retry 256
9.2 Fallback logic 257
Let's see this in action: Implementing fallback logic 257
9.3 Control loops 263
Understanding types of control loops 263
Controlling the control loop 264
10 Fronting services: Circuit breakers and API gateways 267
10.1 Circuit breakers 269
The software circuit breaker 269
Implementing a circuit breaker 272
10.2 API gateways 284
The case for API gateways in cloud-native software 286
API gateway topology 286
10.3 The service mesh 289
The sidecar 289
The control plane 292
11 Troubleshooting: Finding the needle in the haystack 295
11.1 Application logging 296
11.2 Application metrics 300
Pulling metrics from cloud-native applications 302
Pushing metrics from cloud-native applications 304
11.3 Distributed tracing 306
Tracer output 310
Assembling traces via Zipkin 313
Implementation details 317
12 Cloud-native data: Breaking the data monolith 320
12.1 Every microservice needs a cache 323
12.2 Moving from request/response to event driven 326
12.3 The event log 328
Let's see this in action: Implementing event-driven microservices 330
What's new with topics and queues? 343
The event payload 347
Idempotency 348
12.4 Event sourcing 349
The journey, so far 349
The source of truth 351
Let's see this in action: Implementing event sourcing 353
12.5 We're just scratching the surface 356
Index 359