Skip to content

Instantly share code, notes, and snippets.

@mhutter
Created January 17, 2024 12:56
Show Gist options
  • Save mhutter/5f66b1872979581ff93988e6b2016685 to your computer and use it in GitHub Desktop.
Save mhutter/5f66b1872979581ff93988e6b2016685 to your computer and use it in GitHub Desktop.
HA Kubernetes Deployments
# In Kubernetes clusters, it is common that Pods are being evicted from a node.
# Reasons include maintenance, out-of-resource situations (OOM), or failure of
# a node.
#
# This YAML document describes how to set up your Kubernetes Deployment in a
# way that your application will stay available even if this happens.
#
# Unlike during rollouts, during an eviction Kubernetes will NOT first start a
# "replacement" Pod and then stop the old one, but instead just check
# PodDisruptionBudgets and then terminate the Pod (unless the PDB would be
# violated). This means that we have to make sure a failover is in place, and
# no two pods are evicted at the same time.
#
# Only the commented parts are important, the rest is left in for context.
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
# Make note of this, we need it below
app: myapp
name: myapp
spec:
# At least two replicas are required. During an eviction, there will not be a
# "replacement" pod started before the old pod is terminated, so WE have to
# make sure the "replacement" is already running.
# More replicas only makes sense if you need to further scale your
# application horizontally
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
creationTimestamp: null
labels:
app: myapp
spec:
# Pod Anti-Affinity prevents two pods of your deployment running on the
# same node.
#
# In essence, a podAntiAffinity rule says "Ensure that all pods matching
# `labelSelector` are placed on nodes where the `topologyKey` is
# different".
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
# The labelSelector lets you select which pods match your
# Anti-Affinity rule. You're not limited to pods in the same
# Deployment.
matchExpressions:
- key: app
operator: In
values:
- myapp
# The "topologyKey" describes which label of the nodes must be
# different for each matching pod
topologyKey: kubernetes.io/hostname
containers:
- name: myapp
image: "your-registry.example.com/myorg/myapp:tag"
# A readiness probe ensures that Kubernetes only thinks of your Pod
# as "ready" once it has fully started. Without it, Kubernetes will
# immediately after start mark it as ready, and delete the old pod!
readinessProbe:
httpGet:
path: /-/healthz
port: 8080
# Proper resource requests help Kubernetes to schedule workloads
# appropriately, and avoid evictions caused by out-of-resource
# situations on a node.
resources:
# As a rule of thumb, the requests should be what your app consumes while IDLE.
requests:
cpu: "10m"
memory: "64Mi"
limits:
cpu: "2"
memory: "512Mi"
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
# IMPORTANT: Make sure you don't accidentially create a PDB that prevents
# _ANY_ pods from being evicted (eg `minAvailable: 1` for a Deployment that
# only has `replicas: 1`). Cluster Operators WILL be pissed and WILL delete
# your PDB to unblock maintenance.
minAvailable: 1
selector:
# Match your application
matchLabels:
app: myapp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment