Choosing a Pod Security Strategy for Talos: PSA vs. Gatekeeper
Decide between Pod Security Admission (PSA) and OPA Gatekeeper for your Talos cluster. Learn how to implement native PSA enforcement to harden workloads with minimal overhead.
21 Nov 2025, 03:00 UTC

The Challenge: Enforcing Pod Security Standards
Securing a Talos-managed cluster requires a mechanism to prevent privileged containers or root-access pods from compromising the node. With the deprecation of Pod Security Policies (PSP), engineers must choose between the native Pod Security Admission (PSA) controller and external policy engines like OPA Gatekeeper.
The primary takeaway: For most Talos users, PSA is the optimal choice due to its zero-overhead integration and alignment with Kubernetes standards. Use Gatekeeper only if your compliance requirements demand custom logic that exceeds the built-in "Privileged," "Baseline," and "Restricted" profiles.
Decision Matrix: PSA vs. Gatekeeper
When selecting a security enforcement tool, evaluate your needs based on the following constraints:
| Feature | Pod Security Admission (PSA) | OPA Gatekeeper |
|---|---|---|
| Operational Cost | Negligible (Built-in) | Moderate (Requires Controller/CRDs) |
| Policy Granularity | Coarse (3 Standard Levels) | Fine-grained (Rego Language) |
| Configuration | Namespace Labels | ConstraintTemplates & Constraints |
| Talos Integration | Native / Declarative | External Deployment |
Trade-off Analysis
- PSA is a "set and forget" solution. It uses the Kubernetes API to enforce standards without adding new components to the cluster. However, it cannot enforce specific rules like "all images must come from a private registry."
- Gatekeeper provides a powerful policy-as-code framework. This is necessary for complex organizations but introduces a new point of failure and requires managing a separate set of Custom Resource Definitions (CRDs).
Implementing PSA in Talos
This implementation assumes you are running a Talos cluster with Kubernetes v1.25 or later. PSA is enforced at the namespace level via labels.
1. Validation of Prerequisites
Run this command on your local workstation with kubectl configured for the cluster to ensure version compatibility:
kubectl version --short | grep 'Server Version:'
# Expected: Server Version: v1.25.x or higher
2. Configuring the Admission Plugin
To enable the PodSecurity admission plugin, modify your Talos machine configuration (e.g., controlplane.yaml). This ensures the controller is active across the control plane.
# In the cluster configuration spec
spec:
admissionPlugins:
- name: PodSecurity
configuration:
defaults:
policyTemplate: "restricted"
Apply the configuration using talosctl with administrative permissions:
talosctl apply-config --insecure -n <node-ip> --config controlplane.yaml
Risk: Applying a global default of "restricted" may block existing system pods. It is safer to leave the global default as "privileged" and label specific namespaces.
3. Applying Namespace Enforcement
To secure a specific workload, apply the enforce label to the target namespace. This tells the API server to reject any pod that doesn't meet the "Restricted" standard (e.g., pods requiring root or hostNetwork).
kubectl label namespace production podsecurity.kubernetes.io/enforce=restricted
4. Verifying the Result
Test the enforcement by attempting to deploy a privileged pod into the restricted namespace. Run this as a standard user with namespace permissions:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: security-test
namespace: production
spec:
containers:
- name: alpine
image: alpine
securityContext:
privileged: true
EOF
Expected Result: The command should return a Forbidden error stating that the pod violates the PodSecurity restricted policy.
Limitations and Rollback
PSA cannot be used to create "hybrid" policies; you must choose one of the three standard levels. If you find that PSA is blocking critical system services, you can roll back the namespace enforcement immediately:
kubectl label namespace production podsecurity.kubernetes.io/enforce-
To verify the current state of a namespace, use the following check:
kubectl get ns production -o jsonpath='{.metadata.labels.podsecurity\.kubernetes\.io\.enforce}'0 replies
A thoughtful contribution can make all the difference. Be the first to share one.