Microservice architecture “arranges an application as a collection of loosely coupled services.” Microservice based applications can be run using lightweight container runtimes but usually they are cloud-native as well. Cloud-native means that the applications “(are scalable and run) in modern, dynamic environments such as public, private, and hybrid clouds.” The majority of cloud-native applications are developed to run on cloud provider infrastrcuture (e.g. compute resources) and using cloud provider specific technologies (e.g. blob storage, messaging brokers, etc.). The most common platforms are Amazon AWS, Google Cloud Platform (GCP) and Microsoft Azure.
What’s the problem?
Cloud-native applications on cloud platforms usually end up beeing vendor specific. This means an application designed, developed and tested for e.g. AWS can usually not be migrated to another platform like e.g. Azure. I say “usually” cause it’s possible to run and maintain applications by using Kubernetes exclusively with e.g. Amazon Elastic Kubernetes Service (EKS), Google Kubernetes Engine or Azure Kuberneters Service (AKS). This has some implications of course. The most obvious disadvantage is that it’s not possible to deploy such applications without vendor lock in cloud environments. In addition it’s not possible to deploy cloud-native style applications into on-premise servers at all. (There are AWS Outposts, GKE on-prem and Azure Stack but again, there would be vendor lock in.) E.g. in the context of automation and gegulated domains (e.g. healthcare) this implication might be very important!
Before thinking about Kuberneter patterns one has to consider microservice patterns. The best book I’ve read so far and which I can higly recommend is Microservices patterns: With examples in Java. These patterns can be seen as equivalents to object oriented programming (OOP) design patterns on another level of abstractions. OOP design patterns are the best practice of how to design object oriented source code. Microservice patterns are the best practice of how to design microservice applications on the container level.
However when considering microservice patterns without considering Kubernetes patterns the cloud-native application will never be highly available. The perspective of how microservice patterns look at cloud-native applications has scalability not in focus. Kubernetes patterns address scalability and availablility enabling highly scalable and available cloud-native applications without cloud platform vendor lock in. The best book I’ve read so far about this topic is Kubernetes Patterns: Reusable Elements for Designing Cloud-Native Applications. An highly recommended read!
An introduction to Kubernetes patterns
This section shall give an overview of, summarize and motivate to dig into Kubernetes patterns described in the before mentioned book. As usual with design patterns, it’s possible to implement them differently (w.r.t. the general approach as well as technology used). The book is just the beginning of a non-complete pattern language! It’s impossible to shrink this whole complex and diverse topic into a blog post or post series. However it’s possible give a short summary and reference for further reading.
The book classifies the patterns corresponding to the book sections into
- Foundational patterns,
- Behavioral patterns,
- Configuration patterns,
- as well as Advanced Patterns.
Foundational patterns describe a number of fundamental principles that containerized applications must comply with in order to become good cloud-native citizens.
- “Predictable Demands explains why every container should declare its resource profile and stay confined to the indicated resource requirements.”
- “Declarative Deployment, shows the different application deployment strategies that can be performed in a declarative way.”
- “Health Probe, dictates that every container should implement specific APIs to help the platform observe and manage the application in the healthiest way possible.”
- “Managed Lifecycle, describes why a container should have a way to read the events coming from the platform and conform by reacting to those events.”
- “Automated Placement, introduces a pattern for distributing containers in a Kubernetes multinode cluster.”
The patterns under this category are focused around the communication mechanisms and interactions between the Pods and the managing platform.
- “Batch Job, describes an isolated atomic unit of work run until completion.”
- “Periodic Job, allows the execution of a unit of work to be triggered by a temporal event.“
- “Daemon Service, allows running infrastructure-focused Pods on spe‐ cific nodes, before application Pods are placed.”
- “Singleton Service, ensures only one instance of a service is active at a time and still highly available.”
- “Stateful Service, is all about how to create and manage distributed stateful applications with Kubernetes.”
- “Service Discovery, explains how clients can access and discover the instances providing application services.”
- “Self Awareness, describes mechanisms for introspection and meta‐data injection into applications.”
The patterns in this category are focused on structuring and organizing containers in a Pod to satisfy different use cases.
- “Init Container, introduces a separate lifecycle for initialization-related tasks and the main application containers.”
- “Sidecar, describes how to extend and enhance the functionality of a pre-existing container without changing it.”
- “Adapter, takes an heterogeneous system and makes it conform to a consistent unified interface that can be consumed by the outside world.”
- “Ambassador, describes a proxy that decouples access to external services.”
The patterns in the following chapters are all about customizing and adapting applications with external configurations for various environments.
- “EnvVar Configuration, uses environment variables to store configu‐ ration data.”
- “Configuration Resource, uses Kubernetes resources like ConfigMaps or Secrets to store configuration information.”
- “Immutable Configuration, brings immutability to large configuration sets by putting it into containers linked to the application at runtime.”
- “Configuration Template, is useful when large configuration files need to be managed for various environments that differ only slightly.”
The patterns in this category cover more complex topics that do not fit in any of the other categories.
- “Controller, is essential to Kubernetes itself and this pattern shows how custom controllers can extend the platform.”
- “Operator, combines a Controller with custom and domain-specific resources to encapsulate operational knowledge in an automated form.”
- “Elastic Scale, describes how Kubernetes can handle dynamic loads by scaling in various dimensions.”
- “Image Builder, moves the aspect of building application images into the cluster itself.”
Several domains requiring low latency in communication like e.g. advanced automotive, avionics or on-premise deployments of cloud-native applications like e.g. in healthcare depend on Kubernetes-native applications. With Kubernetes-native applications it’s possible to prevent from cloud platform vendor lock.
For Kubernetes-native applications Kubernetes patterns are essential. Every distributed system not designed and implemented with these patterns in mind are any other than optimal. Kubernetes patterns depend on microservice applications designed and implemented with microservice patterns in mind.
Happy reading :)