# Example deployment compliant with RESTRICTED Pod Security Standard # This is the gold standard for secure workloads apiVersion: apps/v1 kind: Deployment metadata: name: secure-app namespace: restricted-apps labels: app: secure-app security.kubernetes.io/compliant: "restricted" spec: replicas: 2 selector: matchLabels: app: secure-app template: metadata: labels: app: secure-app spec: # Pod-level security context securityContext: runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 fsGroup: 65534 seccompProfile: type: RuntimeDefault # Prevent service account token auto-mount unless needed automountServiceAccountToken: false containers: - name: app image: nginx:1.27-alpine ports: - containerPort: 8080 protocol: TCP # Container-level security context securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65534 capabilities: drop: - ALL # Only add NET_BIND_SERVICE if binding to ports < 1024 # add: # - NET_BIND_SERVICE # Resource limits (required for production) resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi # Probes for reliability livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 # Volume mounts for writable paths (since root is read-only) volumeMounts: - name: tmp mountPath: /tmp - name: cache mountPath: /var/cache/nginx - name: run mountPath: /var/run volumes: # EmptyDir for ephemeral writable storage - name: tmp emptyDir: sizeLimit: 100Mi - name: cache emptyDir: sizeLimit: 100Mi - name: run emptyDir: sizeLimit: 10Mi # Topology spread for high availability topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app: secure-app