With the evolution of microservices and containers in recent years, the way we design, develop, and run software has changed significantly. Today’s applications are optimized for scalability, elasticity, failure, and speed of change. Driven by new principles, these modern architectures require a different set of patterns and practices. This book aims to help developers create cloud-native applications with Kubernetes as a runtime platform. First, let’s take a brief look at the two primary ingredients of this book: Kubernetes and design patterns.
Kubernetes is a container orchestration platform. The origin of Kubernetes lies somewhere 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”), and in 2015, it became the first project donated to the newly founded Cloud Native Computing Foundation (CNCF).
Right from the start, Kubernetes gained a whole community of users, and the number of contributors grew at an incredibly fast pace. Today, Kubernetes is considered one of the most active projects on GitHub. It is probably fair to claim that at the time of this writing, 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, including ways to build applications within the platform. These are only some of the reasons we chose Kubernetes 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 out the foundation for the following patterns.
The concept of design patterns dates back to the 1970s and 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 It is different from a recipe because instead of giving step-by-step instructions to solving a problem, a pattern 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 with beverages, music, and other activities.
However, a pattern does more than provide a solution. It is also about forming a language. The unique pattern names 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 we talk about 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.
There are also other characteristics of a pattern language. Patterns are interconnected and can overlap so that together, they cover most of the problem space. Also, as already laid out in the original A Pattern Language, patterns do not have the same 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 not as widely applicable. This book contains all sort 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 format, and unfortunately there is no common standard for the way patterns should be laid out. Martin Fowler gives an excellent overview of the formats used for pattern languages in Writing Software Patterns.
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:
Each pattern carries a name, which is also the chapter’s title. The name is the center of the pattern’s language.
This section gives the broader context and describes the pattern space in detail.
This section is about 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.
A discussion about the advantages and disadvantages of the solution for the given context follows.
This final section contains additional information sources related to the pattern.
We organized the patterns of 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.
Part II, Behavioral Patterns, describes patterns that sit on top of the foundational patterns and add finer-grained concepts for managing various types of container and platform interactions.
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 very granular patterns, including concrete recipes for connecting applications to their configuration.
Part V, 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.
A pattern might not always fit into one category alone. Depending on the context, the same pattern might fit into several categories. Every pattern chapter is self-contained, and you can read chapters in isolation and in any order.
This book is for developers who want to design and develop cloud-native applications for the Kubernetes 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, technical consultants, and developers will all benefit from the repeatable patterns described here.
This book is based on use cases and lessons learned from real-world projects. We want to help you create better cloud-native applications—not reinvent the wheel.
There’s a lot to discover in this book. Some of the patterns may read like excerpts from a Kubernetes manual at first glance, but upon closer look you’ll see the patterns are presented from a conceptual angle not found in other books on the topic. Other patterns are explained with a different approach, with detailed guidelines for very concrete problems, as in “Configuration Patterns” in Part IV.
Regardless of the pattern granularity, you will learn everything Kubernetes offers for each particular pattern, with plenty of examples to illustrate the concepts. All these examples have been tested, and we tell you how to get the full source code in “Using Code Examples”.
Before we start to dive in, let’s briefly look at what this book is not:
This book is not a guide on how to set up a Kubernetes cluster itself. Every pattern and every example assumes you have Kubernetes up and running. You have several options for trying out the examples. If you are interested in learning how to set up a Kubernetes cluster, we recommend Managing Kubernetes by Brendan Burns and Craig Tracey (O’Reilly). Also, the Kubernetes Cookbook by Michael Hausenblas and Sébastien Goasguen (O’Reilly) has recipes for setting up a Kubernetes cluster from scratch.
This book is not an introduction to Kubernetes, nor 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 how to use Kubernetes, we highly recommend Kubernetes in Action by Marko Lukša (Manning Publications).
The book is written in a relaxed style, and is similar to a series of essays that can be read independently.
As mentioned, patterns form a kind of simple, interconnected language. To emphasize this web of patterns, each pattern is capitalized in italics, (e.g., Sidecar). When a pattern is named like a Kubernetes core concept (like Init Container or Controller), we use this specific formatting only when we directly reference the pattern itself. Where it makes sense, we also interlink pattern chapters for ease of navigation.
We also use the following conventions:
Everything you can type in a shell or editor is rendered in
fixed font width.
Kubernetes resource names are always rendered in uppercase (e.g., Pod). If the resource is a combined name like ConfigMap, we keep it like this in favor of the more natural “config map” for clarity and to make it clear that it refers to a Kubernetes concept.
Sometimes a Kubernetes resource name is identical to a common concept like “service” or “node”. In these cases we use the resource name format only when referring to the resource itself.
Every pattern is backed with fully executable examples, which you can find on the accompanying web page. You can find the link to each pattern’s example in the “More Information” section of each chapter.
The “More Information” section also contains many links to further information related to the pattern. We keep these lists updated in the example repository. Changes to the link collections will also be posted on Twitter.
The source code for all examples in this book is available at GitHub. The repository and the website also have pointers and instructions on how to get a Kubernetes cluster to try out the examples. When you go through the examples, please also have a look into the provided resource files. They contain many useful comments that help further in understanding the example code.
Many examples use a REST service called random-generator that returns random numbers when called. It is uniquely crafted for playing well with the examples of this book. Its source can be found at GitHub as well, and its container image
k8spatterns/random-generator is hosted on Docker Hub.
For describing resource fields, we use a JSON path notation. For example,
.spec.replicas points to the
replicas field of the resource’s
If you find an issue in the example code or documentation or if you have a question, don’t hesitate to open a ticket in the GitHub issue tracker. We monitor these GitHub issues and are happy to answer any questions over there.
All example code is distributed under the Creative Commons Attribution 4.0 (CC BY 4.0) license. The code is free to use, and you are free to share and adapt it for commercial and noncommercial projects. However, you should give attribution back to this book if you copy or redistribute the material.
This attribution can be either a reference to the book including title, author, publisher, and ISBN, as in “Kubernetes Patterns by Bilgin Ibryam and Roland Huß (O’Reilly). Copyright 2019 Bilgin Ibryam and Roland Huß, 978-1-492-05028-5.” Alternatively, add a link back to the accompanying website along with a copyright notice and link to the license.
We love code contributions, too! If you think we can improve our examples, we are happy to hear from you. Just open a GitHub issue or create a pull request, and let’s start a conversation.
For almost 40 years, O’Reilly Media has provided technology and business training, knowledge, and insight to help companies succeed.
Our unique network of experts and innovators share their knowledge and expertise through books, articles, conferences, and our online learning platform. O’Reilly’s online learning platform gives you on-demand access to live training courses, in-depth learning paths, interactive coding environments, and a vast collection of text and video from O’Reilly and 200+ other publishers. For more information, please visit http://oreilly.com.
Please address comments and questions concerning this book to the publisher:
We have a web page for this book where we list errata, examples, and additional information. You can access this page at https://oreil.ly/kubernetes_patterns.
To comment or ask technical questions about this book, email email@example.com.
For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia
Creating this book was a long journey spanning over two years, and we want to thank all of our reviewers who kept us on the right track. Special kudos go out to Paolo Antinori and Andrea Tarocchi for helping us through the whole journey. Big thanks also to Marko Lukša, Brandon Philips, Michael Hüttermann, Brian Gracely, Andrew Block, Jiri Kremser, Tobias Schneck, and Rick Wagner, who supported us with their expertise and advices. Last, but not least, big thanks to our editors Virginia Wilson, John Devins, Katherine Tozer, Christina Edwards and all the awesome folks at O’Reilly for helping us push this book over the finish line.
1 Christopher 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, p. x). We think this definition works for the patterns we describe in this book, except that we probably don’t have as much variability in our solutions.