Table of Contents
Foreword xiii
Preface xvii
1 Introduction 1
Serverless Applications 1
A Simple Developer Experience 2
Autoscalable Out of the Box 3
A Different Cost Model 4
Serverless Is Not Functions as a Service 5
Google Cloud 5
Serverless on Google Cloud 7
Cloud Run 8
Service 8
Container Image 8
Scalability and Self-Healing 9
HTTPS Serving 9
Microservices Support 9
Identity, Authentication, and Access Management 9
Monitoring and Logging 10
Transparent Deployments 10
Pay-Per-Use 10
Concerns About Serverless 10
Unpredictable Costs 11
Hyper-Scalability 11
When Things Go Really Wrong 11
Separation of Compute and Storage 11
Open Source Compatibility 12
Summary 12
2 Understanding Cloud Run 13
Getting Started with Google Cloud 13
Costs 14
Interacting with Google Cloud 14
Google Cloud Projects 15
Installing and Authenticating the SDK 15
Installing Beta Components 16
Deploying Your First Service 16
Deploying the Sample Container 16
Region 17
Structure of the HTTPS Endpoint 18
Viewing Your Service in the Web Console 18
Deploying a New Version 19
Revision 20
Understanding Cloud Run 22
Container Life Cycle 22
CPU Throttling 24
Task Scheduling and Throttling 24
Load Balancer and Autoscaler 24
Concurrent Request Limit 26
Autoscaler 26
Tuning the Concurrency Setting 27
Cold Starts 27
Disposable Containers 27
In-Memory Filesystem 28
Ready for Requests 28
Cloud Run Key Points 28
Choosing a Serverless Compute Product on Google Cloud 29
Cloud Functions: Glue Code 29
App Engine: Platform as a Service 30
Key Differences 30
What Will the Future Look Like? 31
Summary 32
3 Building Containers 33
Containers: A Hands-On Exploration 34
Running an Interactive Shell 34
Overriding the Default Command 35
Running a Server 35
Containers from First Principles 36
Inside a Container Image 36
The Linux Kernel 37
Container Isolation 38
Starting a Container 39
Building a Container with Docker 40
Dockerfile Instructions 41
Installing Additional Tooling 42
Smaller Is Better When Deploying to Production 43
Creating Small Containers with Distroless 43
Artifact Registry 44
Building and Tagging the Container Image 45
Authenticating and Pushing the Container Image 46
Building a Container Without a Dockerfile 46
Go Containers with ko 47
Java Containers with Jib 49
Cloud Native Buildpacks 49
Cloud Build 50
Remote Docker Build 51
Advanced Builds 51
Running Arbitrary Programs 53
Connecting with Version Control 53
Shutting Down 54
Summary 54
4 Working with a Relational Database 55
Introducing the Demo Application 55
Creating the Cloud SQL Instance 57
Understanding Cloud SQL Proxy 58
Connecting and Loading the Schema 59
Securing the Default User 60
Connecting Cloud Run to Cloud SQL 61
Disabling the Direct Connection 62
Deploying the Demo Application 63
Connection String 64
Public and Private IP 64
Limiting Concurrency 65
Transaction Concurrency 66
Resource Contention 67
Scaling Boundaries and Connection Pooling 67
External Connection Pool 68
A Real-World Example 69
Cloud SQL in Production 69
Monitoring 69
Automatic Storage Increase 69
High Availability 69
Making Your Application Resilient Against Short Downtime 70
Shutting Down 70
Summary 70
5 Working with HTTP Sessions 71
How HTTP Sessions Work 72
Storing Sessions in Memorystore: A Hands-On Exploration 73
Creating a Memorystore Instance 73
What Is a VPC Connector? 74
Creating a VPC Connector 76
Deploying the Demo App 77
Alternative Session Stores 77
Session Affinity 78
Use Cases 79
Session Affinity Is Not for Session Data 79
Shutting Down 80
Summary 80
6 Service Identity and Authentication 81
Cloud IAM Fundamentals 81
Roles 81
Policy Binding 82
Service Accounts 85
Creating and Using a New Service Account 87
Sending Authenticated Requests to Cloud Run 88
Deploying a Private Service 88
Using an ID Token to Send Authenticated Requests 89
When Is an ID Token Valid? 90
Programmatically Calling Private Cloud Run Services 90
Google Frontend Server 91
A Story About Inter-Service Latency 92
Demo Application 92
Embedded Read-Only SQL Database 93
Running Locally 93
Edit, Compile, Reload 94
Deploying to Cloud Run 95
Update the Frontend Configuration 96
Add Custom Service Accounts 96
Add IAM Policy Binding 96
Summary 97
7 Task Scheduling 99
Cloud Tasks 99
Hands-On Learning: A Demo Application 101
Building the Container Images 101
Creating a Cloud Tasks Queue 102
Creating Service Accounts 102
Deploying the Worker Service 102
Deploying the Task App Service 103
Connecting the Task Queue 103
Scheduling a Task with the Cloud Tasks Client Library 103
Automatic ID Token 104
Connecting the Worker 105
Test the App 105
Queue Configuration 105
Retry Configuration 105
Rate Limiting 106
Viewing and Updating Queue Configuration 107
Considerations 107
Cloud Tasks Might Deliver Your Request Twice 107
Local Development 108
Alternatives 108
Summary 109
8 Infrastructure as Code Using Terraform 111
What Is Infrastructure as Code? 111
Why Infrastructure as Code? 112
Serverless Infrastructure 113
How It Works 113
When Not to Use Infrastructure as Code 114
Terraform 115
Installing Terraform 115
Getting Started with a Minimal Example 116
The Terraform Workflow 122
Change with Terraform: Adding the Access Policy 124
Expressing Dependencies with References 125
Supplemental Resources 126
Summary 127
9 Structured Logging and Tracing 129
Logging on Cloud Run 129
Viewing Logs in the Web Console 130
Viewing Logs in the Terminal 130
Finding Invisible Logs 131
Plain-Text Logs Leave You Wanting More 132
Demo Application 132
Structured Logging 132
Client Libraries 134
Structured Logging in Other Languages 134
How to Use Log Levels 134
Capturing Panics 135
Local Development 137
Request Context 137
Trace Context 139
Forwarding Trace ID 139
Preparing All Incoming Requests with the Trace ID 141
Passing Request Context to Outgoing Requests 141
Viewing Trace Context in Cloud Logging 143
Additional Resources About Tracing 143
Log-Based Metrics with Cloud Monitoring 143
Summary 144
10 Cloud Run and Knative Serving 147
What Is Knative Serving? 148
Cloud Run Is Not Managed Knative Serving 148
Knative Serving on Google Cloud 148
Understanding Kubernetes 149
API Server 150
Kubernetes Resources 151
Database 151
Controllers 151
Adding Extensions to Kubernetes 152
Running Knative Serving Locally 152
Running a Local Kubernetes Cluster 152
Installing Minikube and kubectl 153
Starting Your Local Cluster 153
Install the Knative Operator 154
Starting Minikube Tunnel 155
Installing an HTTP Load Balancer 156
Configuring DNS 157
Deploying a Service 157
Deploying the Same Service to Cloud Run 158
Alternative API Clients 158
Shutting Down 159
Discussion 159
Serving 159
Moving from Kubernetes to Cloud Run Is Harder 159
Service Identity and Authentication 159
Proprietary Managed Services 160
Summary 160
Index 161