Closing the Bootstrap Gap in Kubernetes Policy Enforcement
If you've managed security policies across multiple Kubernetes clusters, you know the pain of the bootstrap window. Admission policies are API objects—they don't exist until created, and any user with sufficient permissions can delete them. This creates a chicken-and-egg scenario: during cluster initialization, policies aren't active, and there's no way to prevent privileged users from removing critical guardrails. Kubernetes v1.36 addresses this with an alpha feature: manifest-based admission control. It allows you to define admission webhooks and CEL-based policies as files on disk, loaded by the API server at startup—before it serves any requests.
The Problem: Gaps and Self-Protection Limits
Most current Kubernetes policy enforcement relies on the API. You create a ValidatingAdmissionPolicy or a webhook configuration as an API object, and the admission controller applies it. This works fine in steady state, but has fundamental limitations:
Bootstrap Gap
When a cluster first starts, there's a delay between the API server beginning to serve requests and your policies being created and activated. This gap can be significant during etcd recovery or backup restoration, leaving the cluster exposed.
Self-Protection Blind Spot
Admission webhooks and policies cannot intercept operations on their own configuration resources. Kubernetes skips invoking webhooks on types like ValidatingWebhookConfiguration to avoid circular dependencies. This means a user with high privileges can delete your essential admission policies, and the admission chain cannot stop them.
The Kubernetes SIG API Machinery set out to create a mechanism where certain policies are always on, full stop—immune to deletion and active from the moment the API server starts.
Solution: Manifest-Based Admission Control
This new feature lets you specify a directory of YAML files containing policy definitions. The API server loads these files at startup, before serving any requests, ensuring policies are in place immediately. Configuration is straightforward:
- Add a
staticManifestsDirfield to theAdmissionConfigurationfile (already passed to the API server via the--admission-control-config-fileflag). - Place your policy YAML files in that directory.
- The API server loads them before serving any requests.
Here's an example of the configuration snippet:
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: ValidatingAdmissionPolicy
configuration:
apiVersion: apiserver.config.k8s.io/v1
kind: ValidatingAdmissionPolicyConfiguration
staticManifestsDir: "/etc/kubernetes/admission/validating-policies/"
Naming Convention and Collision Prevention
Manifest files are standard Kubernetes resource definitions, but they must have names ending in .static.k8s.io. This reserved suffix prevents collisions with API-based configurations and makes it easy to trace the source of an admission decision in metrics or audit logs.
Complete Example: Deny Privileged Containers Outside kube-system
Here's a policy that denies privileged containers in any namespace except kube-system:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "deny-privileged.static.k8s.io"
annotations:
kubernetes.io/description: "Deny launching privileged pods, anywhere this policy is applied"
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
- expression: "object.spec.containers.all(c, !c.securityContext.privileged || namespace == 'kube-system')"
message: "Privileged containers are not allowed outside kube-system."
Benefits and Use Cases
- Boot-time protection: Policies are active before any API requests, closing the window of vulnerability during cluster initialization.
- Tamper resistance: Manifest-based policies cannot be deleted or modified through the API, preventing privilege escalation.
- Clear provenance: The
.static.k8s.iosuffix distinguishes file-sourced policies from API-created ones. - Simplified recovery: After etcd restore, policies are reloaded from disk automatically.
Next Steps and Considerations
As an alpha feature in Kubernetes v1.36, manifest-based admission control requires explicit opt-in. Operators should test its behavior, especially regarding ordering of static vs. dynamic policies. The feature paves the way for more robust platform security, allowing cluster administrators to define immutable guardrails that survive cluster resets or malicious actions.
For a deeper dive, see the official documentation on manifest-based admission.