📄 Page
1
Bilgin Ibryam & Roland Huß Foreword by Brendan Burns Kubernetes Patterns Reusable Elements for Designing Cloud Native Applications Second EditionSECOND EDITION Compliments of
📄 Page
2
KUBERNETES “Bilgin and Roland have written a wonderful, incredibly informative, and intensely useful book.” —Grady Booch Chief Scientist for Software Engineering, IBM; Coauthor, Unified Modeling Language “An updated set of patterns to enable developers to take full advantage of the capabilities and features found in Kubernetes.” —Andrew Block Distinguished Architect, Red Hat Kubernetes Patterns Twitter: @oreillymedia linkedin.com/company/oreilly-media youtube.com/oreillymedia The way developers design, build, and run software has changed significantly with the evolution of microservices and containers. These modern architectures offer new distributed primitives that require a different set of practices than many developers, tech leads, and architects are accustomed to. With this focused guide, Bilgin Ibryam and Roland Huß provide common reusable patterns and principles for designing and implementing cloud native applications on Kubernetes. Each pattern includes a description of the problem and a Kubernetes-specific solution. All patterns are backed by and demonstrated with concrete code examples. This updated edition is ideal for developers and architects who are familiar with basic Kubernetes concepts but want to learn how to solve common cloud native challenges with proven design patterns. You’ll explore: • Foundational patterns covering core principles and practices for building and running container-based cloud native applications • Behavioral patterns for managing various types of container and platform interactions • Structural patterns for organizing containers to address specific use cases • Configuration patterns that provide insight into how application configurations can be handled in Kubernetes • Security patterns for hardening applications running on Kubernetes and making them more secure • Advanced patterns covering more complex topics such as operators, autoscaling, and in-cluster image builds Bilgin Ibryam is a principal product manager at Diagrid, where he leads the company’s product strategy. Dr. Roland Huß is a senior principal software engineer at Red Hat and the architect of OpenShift Serverless. US $65.99 CAN $82.99 ISBN: 978-1-098-13168-5 SECOND EDITION 522 4
📄 Page
3
(This page has no text content)
📄 Page
4
(This page has no text content)
📄 Page
5
Bilgin Ibryam and Roland Huß Kubernetes Patterns Reusable Elements for Designing Cloud Native Applications SECOND EDITION Boston Farnham Sebastopol TokyoBeijing
📄 Page
6
978-1-098-15228-4 [LSI] Kubernetes Patterns by Bilgin Ibryam and Roland Huß Copyright © 2023 Bilgin Ibryam and Roland Huß. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Acquisitions Editor: John Devins Development Editor: Rita Fernando Production Editor: Beth Kelly Copyeditor: Piper Editorial Consulting, LLC Proofreader: Sharon Wilkey Indexer: Judy McConville Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Kate Dullea April 2019: First Edition March 2023: Second Edition Revision History for the Second Edition 2023-03-25: First Release See http://oreilly.com/catalog/errata.csp?isbn=9781098131685 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Kubernetes Patterns, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. The views expressed in this work are those of the authors and do not represent the publisher’s views. While the publisher and the authors have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the authors disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights. This work is part of a collaboration between O’Reilly and Red Hat. See our statement of editorial independence.
📄 Page
7
Table of Contents Foreword. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 The Path to Cloud Native 1 Distributed Primitives 3 Containers 5 Pods 6 Services 7 Labels 8 Namespaces 10 Discussion 11 More Information 12 Part I. Foundational Patterns 2. Predictable Demands. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Problem 15 Solution 15 Runtime Dependencies 16 Resource Profiles 18 Pod Priority 21 Project Resources 23 Capacity Planning 25 Discussion 26 More Information 26 v
📄 Page
8
3. Declarative Deployment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Problem 29 Solution 29 Rolling Deployment 31 Fixed Deployment 34 Blue-Green Release 34 Canary Release 35 Discussion 36 More Information 38 4. Health Probe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Problem 41 Solution 41 Process Health Checks 42 Liveness Probes 42 Readiness Probes 44 Startup Probes 46 Discussion 48 More Information 49 5. Managed Lifecycle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Problem 51 Solution 51 SIGTERM Signal 52 SIGKILL Signal 52 PostStart Hook 53 PreStop Hook 54 Other Lifecycle Controls 55 Discussion 58 More Information 59 6. Automated Placement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Problem 61 Solution 61 Available Node Resources 62 Container Resource Demands 63 Scheduler Configurations 63 Scheduling Process 64 Node Affinity 66 Pod Affinity and Anti-Affinity 67 Topology Spread Constraints 68 Taints and Tolerations 70 vi | Table of Contents
📄 Page
9
Discussion 72 More Information 75 Part II. Behavioral Patterns 7. Batch Job. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Problem 79 Solution 80 Discussion 85 More Information 86 8. Periodic Job. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Problem 87 Solution 88 Discussion 89 More Information 90 9. Daemon Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 Problem 91 Solution 92 Discussion 95 More Information 95 10. Singleton Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Problem 97 Solution 98 Out-of-Application Locking 98 In-Application Locking 100 Pod Disruption Budget 103 Discussion 104 More Information 105 11. Stateless Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Problem 107 Solution 108 Instances 108 Networking 110 Storage 111 Discussion 113 More Information 114 Table of Contents | vii
📄 Page
10
12. Stateful Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Problem 115 Storage 116 Networking 116 Identity 117 Ordinality 117 Other Requirements 117 Solution 118 Storage 119 Networking 120 Identity 121 Ordinality 122 Other Features 122 Discussion 124 More Information 125 13. Service Discovery. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Problem 127 Solution 128 Internal Service Discovery 129 Manual Service Discovery 133 Service Discovery from Outside the Cluster 135 Application Layer Service Discovery 139 Discussion 142 More Information 143 14. Self Awareness. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Problem 145 Solution 146 Discussion 149 More Information 149 Part III. Structural Patterns 15. Init Container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Problem 153 Solution 154 Discussion 158 More Information 159 viii | Table of Contents
📄 Page
11
16. Sidecar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Problem 161 Solution 162 Discussion 164 More Information 164 17. Adapter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Problem 167 Solution 167 Discussion 170 More Information 170 18. Ambassador. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Problem 171 Solution 171 Discussion 173 More Information 174 Part IV. Configuration Patterns 19. EnvVar Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 Problem 177 Solution 177 Discussion 182 More Information 183 20. Configuration Resource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Problem 185 Solution 185 Discussion 191 More Information 191 21. Immutable Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Problem 193 Solution 194 Docker Volumes 194 Kubernetes Init Containers 196 OpenShift Templates 198 Discussion 199 More Information 200 Table of Contents | ix
📄 Page
12
22. Configuration Template. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Problem 201 Solution 201 Discussion 206 More Information 207 Part V. Security Patterns 23. Process Containment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Problem 211 Solution 212 Running Containers with a Non-Root User 212 Restricting Container Capabilities 213 Avoiding a Mutable Container Filesystem 215 Enforcing Security Policies 216 Discussion 218 More Information 219 24. Network Segmentation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Problem 221 Solution 222 Network Policies 223 Authentication Policies 231 Discussion 235 More Information 235 25. Secure Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Problem 237 Solution 238 Out-of-Cluster Encryption 239 Centralized Secret Management 247 Discussion 251 More Information 252 26. Access Control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Problem 253 Solution 254 Authentication 255 Authorization 256 Admission Controllers 256 Subject 257 x | Table of Contents
📄 Page
13
Role-Based Access Control 263 Discussion 274 More Information 275 Part VI. Advanced Patterns 27. Controller. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Problem 279 Solution 280 Discussion 290 More Information 291 28. Operator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Problem 293 Solution 294 Custom Resource Definitions 294 Controller and Operator Classification 297 Operator Development and Deployment 300 Example 302 Discussion 306 More Information 307 29. Elastic Scale. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Problem 309 Solution 310 Manual Horizontal Scaling 310 Horizontal Pod Autoscaling 311 Vertical Pod Autoscaling 325 Cluster Autoscaling 328 Scaling Levels 331 Discussion 333 More Information 333 30. Image Builder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 Problem 335 Solution 336 Container Image Builder 337 Build Orchestrators 341 Build Pod 342 OpenShift Build 346 Discussion 353 Table of Contents | xi
📄 Page
14
More Information 353 Afterword. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 xii | Table of Contents
📄 Page
15
Foreword When Craig, Joe, and I started Kubernetes nearly eight years ago, I think we all recog‐ nized its power to transform the way the world developed and delivered software. I don’t think we knew, or even hoped to believe, how quickly this transformation would come. Kubernetes is now the foundation for the development of portable, reliable systems spanning the major public clouds, private clouds, and bare-metal environments. However, even as Kubernetes has become ubiquitous to the point where you can spin up a cluster in the cloud in less than five minutes, it is still far less obvious to determine where to go once you have created that cluster. It is fantastic that we have seen such significant strides forward in the operationalization of Kubernetes itself, but it is only a part of the solution. It is the foundation on which applications will be built, and it provides a large library of APIs and tools for building these applications, but it does little to provide the application architect or developer with any hints or guidance for how these various pieces can be combined into a complete, reliable system that satisfies their business needs and goals. Although the necessary perspective and experience for what to do with your Kuber‐ netes cluster can be achieved through past experience with similar systems, or via trial and error, this is expensive both in terms of time and the quality of systems delivered to our end users. When you are starting to deliver mission-critical services on top of a system like Kubernetes, learning your way via trial and error simply takes too much time and results in very real problems of downtime and disruption. This then is why Bilgin and Roland’s book is so valuable. Kubernetes Patterns enables you to learn from the previous experience that we have encoded into the APIs and tools that make up Kubernetes. Kubernetes is the by-product of the community’s experience building and delivering many different, reliable distributed systems in a variety of different environments. Each object and capability added to Kubernetes represents a foundational tool that has been designed and purpose-built to solve a specific need for the software designer. This book explains how the concepts in Kubernetes solve real-world problems and how to adapt and use these concepts to build the system that you are working on today. xiii
📄 Page
16
In developing Kubernetes, we always said that our North Star was making the devel‐ opment of distributed systems a CS 101 exercise. If we have managed to achieve that goal successfully, it is books like this one that are the textbooks for such a class. Bilgin and Roland have captured the essential tools of the Kubernetes devel‐ oper and distilled them into segments that are easy to approach and consume. As you finish this book, you will become aware not just of the components available to you in Kubernetes but also the “why” and “how” of building systems with those components. — Brendan Burns Cofounder, Kubernetes xiv | Foreword
📄 Page
17
Preface With the mainstream adoption of microservices and containers in recent years, the way we design, develop, and run software has changed radically. Today’s applications are optimized for availability, scalability, and speed-to-market. Driven by these new requirements, today’s modern applications require a different set of patterns and practices. This book aims to help developers discover and learn about the most common patterns for creating cloud native applications with Kubernetes. First, let’s take a brief look at the two primary ingredients of this book: Kubernetes and design patterns. Kubernetes Kubernetes is a container orchestration platform. The origin of Kubernetes lies some‐ where in the Google data centers where Google’s internal container orchestration platform, Borg, was born. Google used Borg for many years to run its applications. In 2014, Google decided to transfer its experience with Borg into a new open source project called “Kubernetes” (Greek for “helmsman” or “pilot”). In 2015, it became the first project donated to the newly founded Cloud Native Computing Foundation (CNCF). From the start, Kubernetes gained a whole community of users, and the number of contributors grew incredibly fast. Today, Kubernetes is considered one of the most popular projects on GitHub. It is fair to claim that Kubernetes is the most commonly used and feature-rich container orchestration platform. Kubernetes also forms the foundation of other platforms built on top of it. The most prominent of those Platform-as-a-Service systems is Red Hat OpenShift, which provides various additional capabilities to Kubernetes. These are only some reasons we chose Kuber‐ netes as the reference platform for the cloud native patterns in this book. This book assumes you have some basic knowledge of Kubernetes. In Chapter 1, we recapitulate the core Kubernetes concepts and lay the foundation for the following patterns. xv
📄 Page
18
1 Alexander and his team defined the original meaning in the context of architecture as follows: “Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” (A Pattern Language, Christopher Alexander et al., 1977.) Design Patterns The concept of design patterns dates back to the 1970s and is from the field of architecture. Christopher Alexander, an architect and system theorist, and his team published the groundbreaking A Pattern Language (Oxford University Press) in 1977, which describes architectural patterns for creating towns, buildings, and other construction projects. Sometime later, this idea was adopted by the newly formed software industry. The most famous book in this area is Design Patterns—Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides—the Gang of Four (Addison-Wesley). When we talk about the famous Singleton, Factories, or Delegation patterns, it’s because of this defining work. Many other great pattern books have been written since then for various fields with different levels of granularity, like Enterprise Integration Patterns by Gregor Hohpe and Bobby Woolf (Addison-Wesley) or Patterns of Enterprise Application Architecture by Martin Fowler (Addison-Wesley). In short, a pattern describes a repeatable solution to a problem.1 This definition works for the patterns we describe in this book, except that we probably don’t have as much variability in our solutions. A pattern is different from a recipe because instead of giving step-by-step instructions to solve a problem, it provides a blueprint for solving a whole class of similar problems. For example, the Alexandrian pattern Beer Hall describes how public drinking halls should be constructed where “strangers and friends are drinking companions” and not “anchors of the lonely.” All halls built after this pattern look different but share common characteristics, such as open alcoves for groups of four to eight and a place where a hundred people can meet to enjoy beverages, music, and other activities. However, a pattern does more than provide a solution. It is also about forming a language. The patterns in this book form a dense, noun-centric language in which each pattern carries a unique name. When this language is established, these names automatically evoke similar mental representations when people speak about these patterns. For example, when we talk about a table, anyone speaking English assumes we are talking about a piece of wood with four legs and a top on which you can put things. The same thing happens in software engineering when discussing a “factory.” In an object-oriented programming language context, we immediately associate with a “factory” an object that produces other objects. Because we immediately know the solution behind the pattern, we can move on to tackle yet-unsolved problems. xvi | Preface
📄 Page
19
There are also other characteristics of a pattern language. For example, patterns are interconnected and can overlap so that they cover most of the problem space. Also, as already laid out in the original A Pattern Language, patterns have a different level of granularity and scope. More general patterns cover an extensive problem space and provide rough guidance on how to solve the problem. Granular patterns have a very concrete solution proposal but are less widely applicable. This book contains all sorts of patterns, and many patterns reference other patterns or may even include other patterns as part of the solution. Another feature of patterns is that they follow a rigid format. However, each author defines a different form; unfortunately, there is no common standard for how pat‐ terns should be laid out. Martin Fowler gives an excellent overview of the formats used for pattern languages at “Writing Software Patterns”. How This Book Is Structured We chose a simple pattern format for this book. We do not follow any particular pattern description language. For each pattern, we use the following structure: Name Each pattern carries a name, which is also the chapter’s title. The name is the center of the pattern’s language. Problem This section gives the broader context and describes the pattern space in detail. Solution This section shows how the pattern solves the problem in a Kubernetes-specific way. This section also contains cross-references to other patterns that are either related or part of the given pattern. Discussion This section includes a discussion about the advantages and disadvantages of the solution for the given context. More Information This final section contains additional information sources related to the pattern. We organized the patterns in this book as follows: • Part I, “Foundational Patterns”, covers the core concepts of Kubernetes. These are the underlying principles and practices for building container-based cloud native applications. Preface | xvii
📄 Page
20
• Part II, “Behavioral Patterns”, describes patterns that build on top of foundational patterns and add the runtime aspect concepts of managing various types of containers. • Part III, “Structural Patterns”, contains patterns related to organizing containers within a Pod, which is the atom of the Kubernetes platform. • Part IV, “Configuration Patterns”, gives insight into the various ways application configuration can be handled in Kubernetes. These are granular patterns, includ‐ ing concrete recipes for connecting applications to their configuration. • Part V, “Security Patterns”, addresses various security concerns that arise when an application is containerized and deployed on Kubernetes. • Part VI, “Advanced Patterns”, is a collection of advanced concepts, such as how the platform itself can be extended or how to build container images directly within the cluster. Depending on the context, the same pattern might fit into several categories. Every pattern chapter is self-contained; you can read chapters in isolation and in any order. Who This Book Is For This book is for developers who want to design and develop cloud native applications and use Kubernetes as the platform. It is most suitable for readers who have some basic familiarity with containers and Kubernetes concepts and want to take it to the next level. However, you don’t need to know the low-level details of Kubernetes to understand the use cases and patterns. Architects, consultants, and other technical personnel will also benefit from the repeatable patterns described here. The book is based on use cases and lessons learned from real-world projects. It is an accumulation of best practices and patterns after years of working in this space. We want to help you understand the Kubernetes-first mindset and create better cloud native applications—not reinvent the wheel. It is written in a relaxed style and is similar to a series of essays that can be read independently. Let’s briefly look at what this book is not: • This book is not an introduction to Kubernetes, nor is it a reference manual. We touch on many Kubernetes features and explain them in some detail, but we are focusing on the concepts behind those features. Chapter 1, “Introduction”, offers a brief refresher on Kubernetes basics. If you are looking for a comprehensive book on Kubernetes, we highly recommend Kubernetes in Action by Marko Lukša (Manning Publications). • This book is not a step-by-step guide on how to set up a Kubernetes cluster itself. Every example assumes you have Kubernetes up and running. You have several xviii | Preface