# Hugo generates the complete site at image-build time. SWS serves only those # immutable files, with no writable content volume or Kubernetes API access. apiVersion: apps/v1 kind: Deployment metadata: name: blog namespace: blog-ahmza-com spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: # Keep the existing site available while replacement Pods become ready. maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app: blog template: metadata: labels: app: blog spec: automountServiceAccountToken: false topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname # Ignore tainted control-plane nodes when balancing the two workers; # otherwise a surge Pod could be blocked by an unusable third node. nodeTaintsPolicy: Honor whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: blog securityContext: seccompProfile: type: RuntimeDefault containers: - name: blog # Bootstrap with the verified published amd64/arm64 index. CI updates # this line to each build's digest, never a mutable latest tag. # yamllint disable-line rule:line-length image: tea.ahmza.com/ahmza/blog-ahmza-com@sha256:2f54eb65def2bc2c8932ed8560f918b975769b13ba3922c038fe5cfbffc9262a imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 protocol: TCP securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true # SWS does not declare USER in the image. An explicit unprivileged # identity lets Kubernetes enforce runAsNonRoot safely. runAsUser: 10001 runAsGroup: 10001 capabilities: drop: - ALL readinessProbe: httpGet: path: /health port: http initialDelaySeconds: 2 periodSeconds: 10 livenessProbe: httpGet: path: /health port: http initialDelaySeconds: 5 periodSeconds: 30 resources: requests: cpu: 10m memory: 16Mi limits: cpu: 250m memory: 128Mi