Kubernetes core objects and a production-ready Deployment for ASP.NET Core (Kubernetes YAML)

Pod: the smallest unit: one or more containers sharing a network.

yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# ======================================================================
# Q: Explain the core Kubernetes objects and show a production-ready Deployment.
#
# - Pod: the smallest unit: one or more containers sharing a network. It is
#   ephemeral.
# - Deployment: keeps N replicas of a Pod, performs rolling updates and
#   rollbacks.
# - Service: a stable DNS name and load balancing to the Pods (Pods change IPs).
# - Ingress / Gateway API: HTTP routing from outside (host, path, TLS) to the
#   Services.
# - ConfigMap / Secret: configuration and sensitive data, as env vars or files.
# - Job / CronJob: tasks that run to completion: migrations (Q8), nightly
#   imports.
# - HPA: automatic scaling of the number of replicas.
# The liveness probe does not check the database or the ERP. If the database
# goes down, all pods would be restarted at the same time for no reason (restart
# storm). Dependencies are checked only in readiness.
# ======================================================================

# Deployment and Service for the API
apiVersion: apps/v1
kind: Deployment
metadata: { name: shop-api }
spec:
  replicas: 3
  selector: { matchLabels: { app: shop-api } }
  strategy:
    rollingUpdate: { maxUnavailable: 0, maxSurge: 1 }        # zero-downtime deploy
  template:
    metadata: { labels: { app: shop-api } }
    spec:
      containers:
        - name: api
          image: myregistry.azurecr.io/shop-api:3f2a9c1        # commit SHA
          ports: [{ containerPort: 8080 }]
          envFrom:
            - configMapRef: { name: shop-api-config }
          resources:
            requests: { cpu: 250m, memory: 256Mi }             # used for scheduling
            limits:   { memory: 512Mi }                        # above this: OOMKilled
          startupProbe:                                        # gives the app time to start
            httpGet: { path: /health/live, port: 8080 }
            periodSeconds: 2
            failureThreshold: 30
          readinessProbe:                                      # on failure: receives no traffic
            httpGet: { path: /health/ready, port: 8080 }
            periodSeconds: 5
          livenessProbe:                                       # on failure: container restart
            httpGet: { path: /health/live, port: 8080 }
            periodSeconds: 10
          securityContext:
            runAsNonRoot: true
            readOnlyRootFilesystem: true
            allowPrivilegeEscalation: false
          volumeMounts: [{ name: tmp, mountPath: /tmp }]       # .NET needs a writable /tmp
      volumes: [{ name: tmp, emptyDir: {} }]
---
apiVersion: v1
kind: Service
metadata: { name: shop-api }
spec:
  selector: { app: shop-api }
  ports: [{ port: 80, targetPort: 8080 }]