# Illustrative stateless API reference, not a ready-to-apply application.
# Replace the placeholder image, health endpoints and resource values.
# Assumptions: three real zone domains and >=4 eligible worker nodes for surge.
# Two surviving replicas must handle the agreed load (verify by load testing).
# Topology-spread node inclusion policies are stable since Kubernetes 1.33.
apiVersion: v1
kind: Namespace
metadata:
  name: ha-example
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: example-critical
value: 1000000
globalDefault: false
preemptionPolicy: Never
description: "Explicit application priority without preemption"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-api
  namespace: ha-example
spec:
  replicas: 3
  minReadySeconds: 10
  progressDeadlineSeconds: 600
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      app.kubernetes.io/name: example-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  template:
    metadata:
      labels:
        app.kubernetes.io/name: example-api
    spec:
      priorityClassName: example-critical
      terminationGracePeriodSeconds: 60
      securityContext:
        runAsNonRoot: true
        runAsUser: 10001
        fsGroup: 10001
        seccompProfile:
          type: RuntimeDefault
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app.kubernetes.io/name: example-api
              topologyKey: kubernetes.io/hostname
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          nodeAffinityPolicy: Honor
          nodeTaintsPolicy: Honor
          labelSelector:
            matchLabels:
              app.kubernetes.io/name: example-api
      containers:
        - name: api
          # Placeholder: replace with a reviewed, digest-pinned application image.
          image: registry.example.com/team/example-api:1.0.0
          ports:
            - name: http
              containerPort: 8080
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
          resources:
            requests:
              cpu: 250m
              memory: 256Mi
            limits:
              memory: 512Mi
          startupProbe:
            httpGet:
              path: /health/startup
              port: http
            periodSeconds: 5
            timeoutSeconds: 2
            failureThreshold: 24
          readinessProbe:
            httpGet:
              path: /health/ready
              port: http
            periodSeconds: 5
            timeoutSeconds: 2
            failureThreshold: 2
          livenessProbe:
            httpGet:
              path: /health/live
              port: http
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 3
          volumeMounts:
            - name: temporary-files
              mountPath: /tmp
      volumes:
        - name: temporary-files
          emptyDir:
            sizeLimit: 128Mi
---
apiVersion: v1
kind: Service
metadata:
  name: example-api
  namespace: ha-example
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: example-api
  ports:
    - name: http
      port: 80
      targetPort: http
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: example-api
  namespace: ha-example
spec:
  minAvailable: 2
  # Healthy pods retain the budget; unhealthy Running pods need not block drain.
  unhealthyPodEvictionPolicy: AlwaysAllow
  selector:
    matchLabels:
      app.kubernetes.io/name: example-api
