This document explains how to migrate your admission policies from Policy Controller to reduce the risk of gaps in policy enforcement. Policy Controller is deprecated as of November 12, 2026, and reaches end of support on December 31, 2027. In version 1.39 and later, Google Kubernetes Engine (GKE) clusters don't support Policy Controller.
You can migrate the admission policies that you enforce by using Policy Controller to Kubernetes ValidatingAdmissionPolicies or to self-managed Open Policy Agent (OPA) Gatekeeper. Migrating doesn't affect workloads that are already running. Policy Controller evaluates requests to create or update resources, so removing it doesn't restart or change running workloads.
This document is for operators and security specialists who manage Policy Controller across a fleet. To learn more about common roles and example tasks that we reference in Google Cloud content, see Common GKE user roles and tasks.
Blocked upgrades to GKE version 1.39
GKE blocks upgrades to version 1.39 and later for clusters that have Policy Controller installed. Before you upgrade a cluster to version 1.39, migrate your policies and remove Policy Controller from that cluster. Don't remove Policy Controller just to unblock the upgrade before you migrate your policies, because doing so leaves the cluster without policy enforcement.
Choose a replacement
Evaluate each admission policy in Policy Controller and choose a replacement option for that policy from the following table. You don't have to choose one replacement for an entire cluster. You can combine options on the same cluster based on what each policy requires:
| Option | When to use | Operation and support |
|---|---|---|
| ValidatingAdmissionPolicy (recommended) | Policies that check a single resource when it's created or updated. Most templates in the Policy Controller template library work this way. | ValidatingAdmissionPolicies are built into Kubernetes and available in GKE version 1.30 and later at no additional cost. Cloud Customer Care supports ValidatingAdmissionPolicies as part of GKE. |
| Pod Security Admission (recommended for Pod security bundles) | Predefined Pod security controls from the
pss-baseline-v2022, pss-restricted-v2022, or
psp-v2022 bundle. For more information, see
Use Pod Security Admission for Pod security
bundles. |
Pod Security Admission is built into Kubernetes and enabled by default in GKE at no additional cost. Customer Care supports Pod Security Admission as part of GKE. |
| Self-managed OPA Gatekeeper | Policies that ValidatingAdmissionPolicies can't express, such as referential policies that read other resources in the cluster, policies that you want to keep in Rego, and audits of existing resources. You can also add Common Expression Language (CEL) rules to Gatekeeper ConstraintTemplates so that Gatekeeper generates ValidatingAdmissionPolicies for API server enforcement, and its audit controller checks existing resources. | You install, upgrade, and operate Gatekeeper. Customer Care doesn't support open source Gatekeeper. The Gatekeeper community provides support through GitHub. |
Inventory and classify your policies
By default, the Policy Controller template library installs every template, and
policy bundles install their constraints with the dryrun enforcement action.
As a result, the templates and constraints on a cluster don't necessarily match
the policies that you enforce. To find out what you enforce, follow these
steps:
Identify the clusters in your fleet that run Policy Controller:
gcloud container fleet policycontroller describe \ --project=PROJECT_IDReplace
PROJECT_IDwith the ID of your fleet host project.On each cluster that you identified, list your constraints:
kubectl get constraints \ -o custom-columns='KIND:.kind,NAME:.metadata.name,'\ 'ACTION:.spec.enforcementAction,VIOLATIONS:.status.totalViolations,'\ 'BUNDLE:.metadata.labels.policycontroller\.gke\.io/bundleName'The output shows each constraint's enforcement action, its violation count from the most recent audit, and any bundle that installed it. A constraint that has no value in the
ACTIONcolumn uses the defaultdenyenforcement action.Back up your ConstraintTemplates and constraints to separate files:
kubectl get constrainttemplates -o yaml \ > policy-controller-templates-backup.yaml kubectl get constraints -o yaml \ > policy-controller-constraints-backup.yamlOptional: Perform the following additional backup operations:
If you enabled referential rules in Policy Controller, then back up your sync configuration:
kubectl get config.config.gatekeeper.sh -n gatekeeper-system -o yaml \ > policy-controller-config-backup.yamlIf you enabled mutation in Policy Controller, then back up your mutators:
kubectl get assign,assignmetadata,assignimage,modifyset -o yaml \ > policy-controller-mutators-backup.yaml
Keep these backup files in a safe place. Removing Policy Controller deletes every ConstraintTemplate, constraint, sync configuration, and mutator on the cluster, including the ones that you created. You need the backups to translate or re-create your policies.
After you back up your policies, determine your migration path for each constraint by checking the constraint type in the following table:
| Constraint type | Migration path |
|---|---|
| Single-resource constraint | If a constraint evaluates fields on only the incoming resource
without reading data.inventory or belonging to a Pod
security bundle, then use a ValidatingAdmissionPolicy. |
Unenforced dryrun constraint |
If a constraint uses the dryrun enforcement action and
you don't plan to enforce it, delete the constraint. |
| Pod security bundle constraint | If a constraint comes from the pss-baseline-v2022,
pss-restricted-v2022, or psp-v2022 bundle, then
use Pod Security Admission. Use ValidatingAdmissionPolicies for any
controls that Pod Security Admission doesn't cover. |
| Referential constraint | If a constraint uses a referential template that reads other
resources in the cluster, then use self-managed Gatekeeper. To find
referential templates, search your backup file for the
data.inventory reference. |
| Cloud Service Mesh, Istio, or Google Cloud constraint | Review the constraint individually to check whether a built-in
GKE feature replaces the policy, or whether the
ConstraintTemplate in your backup file reads
data.inventory. Most of these templates check only the
incoming resource and work in ValidatingAdmissionPolicies, except the
referential AsmAuthzPolicyDefaultDeny and
AsmPeerAuthnMeshStrictMtls templates, which require
self-managed Gatekeeper. For built-in replacements, enable
Binary Authorization instead of using the K8sRequireBinAuthZ
ConstraintTemplate, and configure the node image of your node pools
instead of using the K8sRequireCosNodeImage
ConstraintTemplate. |
Migrate to ValidatingAdmissionPolicy
A ValidatingAdmissionPolicy contains the policy logic, like a ConstraintTemplate. A ValidatingAdmissionPolicyBinding applies the policy, like a constraint. A ValidatingAdmissionPolicy uses CEL expressions instead of Rego, and the API server evaluates the expressions directly, without a webhook.
Example: allowed image repositories
The following Policy Controller constraint requires Pods to use images from one
Artifact Registry repository. It excludes the kube-system namespace:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: allowed-repos
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces: ["kube-system"]
parameters:
repos:
- "us-docker.pkg.dev/example-project/example-repo/"
The following ValidatingAdmissionPolicy and ValidatingAdmissionPolicyBinding
enforce the same rule. The ValidatingAdmissionPolicyBinding uses the Warn and
Audit actions so that you can compare results before you enforce the
ValidatingAdmissionPolicy:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: allowed-repos
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods", "pods/ephemeralcontainers"]
variables:
- name: repos
expression: "['us-docker.pkg.dev/example-project/example-repo/']"
- name: images
expression: >-
object.spec.containers.map(c, c.image) +
(has(object.spec.initContainers) ?
object.spec.initContainers.map(c, c.image) : []) +
(has(object.spec.ephemeralContainers) ?
object.spec.ephemeralContainers.map(c, c.image) : [])
validations:
- expression: >-
variables.images.all(image,
variables.repos.exists(repo, image.startsWith(repo)))
messageExpression: >-
'container images must come from one of these repositories: ' +
variables.repos.join(', ')
reason: Forbidden
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: allowed-repos
spec:
policyName: allowed-repos
validationActions: ["Warn", "Audit"]
matchResources:
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values: ["kube-system", "gatekeeper-system"]
In this example, the repos variable holds the value from the constraint's
parameters field. The validation expression returns a true value for Pods
that comply with the ValidatingAdmissionPolicy, which is the opposite of a Rego
violation rule. To reuse one ValidatingAdmissionPolicy across multiple
ValidatingAdmissionPolicyBindings that supply different values, use a parameter
resource instead of a variable. For more information about parameter resources,
see
Parameter resources
in the Kubernetes documentation.
The following table shows how constraint fields map to ValidatingAdmissionPolicy and ValidatingAdmissionPolicyBinding fields:
| Constraint field | ValidatingAdmissionPolicy or ValidatingAdmissionPolicyBinding field |
|---|---|
spec.enforcementAction |
The validationActions field in the
ValidatingAdmissionPolicyBinding, which maps the deny,
warn, and dryrun actions to the
["Deny"], ["Warn"], and ["Audit"]
values |
spec.parameters |
The variables field in the ValidatingAdmissionPolicy, or
a parameter resource that the ValidatingAdmissionPolicyBinding references
in the paramRef field |
spec.match.kinds |
The matchConstraints.resourceRules field in the
ValidatingAdmissionPolicy, which uses API groups and resource names, such
as the pods resource, instead of kinds |
spec.match.namespaces and
spec.match.excludedNamespaces |
The matchResources.namespaceSelector field in the
ValidatingAdmissionPolicyBinding, using the In or
NotIn operator on the
kubernetes.io/metadata.name label |
spec.match.labelSelector |
The matchResources.objectSelector field in the
ValidatingAdmissionPolicyBinding |
spec.match.namespaceSelector |
The matchResources.namespaceSelector field in the
ValidatingAdmissionPolicyBinding |
spec.match.scope |
The scope field of each resource rule |
For more information about how to write expressions, see CEL in Kubernetes in the Kubernetes documentation.
Test policies alongside Policy Controller
To replace a constraint without a gap in enforcement, run the ValidatingAdmissionPolicy next to the constraint before you enforce the ValidatingAdmissionPolicy:
- Apply the ValidatingAdmissionPolicy and a ValidatingAdmissionPolicyBinding
that has the
validationActions: ["Warn", "Audit"]setting. Leave the Policy Controller constraint in place. - Compare the results by using the audit log query in Replace violation reporting. If the ValidatingAdmissionPolicy flags requests that Policy Controller allows, or the reverse, then fix the ValidatingAdmissionPolicy. For ValidatingAdmissionPolicies that match Pods, don't rely on warnings. Controllers create the Pods for Deployments and other workloads, so the controller receives the warning.
- After the results match, change the ValidatingAdmissionPolicyBinding to use
the
validationActions: ["Deny"]setting. - Delete the Policy Controller constraint.
Plan for behavior differences
ValidatingAdmissionPolicies behave differently from Policy Controller in the following ways, which can block requests or leave gaps in enforcement:
- Failure policy: the Policy Controller webhook fails open, which means
that the API server admits a request if Policy Controller doesn't respond.
A ValidatingAdmissionPolicy that has the
failurePolicy: Failsetting denies a request if an expression returns an error or exceeds the CEL cost limit. The ValidatingAdmissionPolicy also denies a request if a referenced parameter resource doesn't exist and the value of theparamRef.parameterNotFoundActionfield in the ValidatingAdmissionPolicyBinding isDeny. If the value isAllow, then the API server skips a missing parameter resource regardless of thefailurePolicysetting. Test each ValidatingAdmissionPolicy and choose values for both fields. - Missing fields: Rego treats a missing field as no violation, but CEL
returns an error. Before you read an optional field, use the
has()macro to check whether the field exists. - Exemptions: a ValidatingAdmissionPolicy doesn't exempt namespaces by
default or use the
admission.gatekeeper.sh/ignorelabel. On GKE Standard clusters, a ValidatingAdmissionPolicyBinding applies to every namespace in the cluster, including system namespaces such as thekube-systemnamespace, unless you exclude them in thematchResources.namespaceSelectorfield on the ValidatingAdmissionPolicyBinding or in thematchConstraints.namespaceSelectorormatchConditionsfields on the ValidatingAdmissionPolicy. On Autopilot clusters, GKE excludes managed namespaces automatically and rejects ValidatingAdmissionPolicies that match thenodes,persistentVolumes,certificatesigningrequests, ortokenreviewsresources. For more information, see GKE Autopilot security measures. - Subresources: Policy Controller checks Pod updates that add ephemeral
containers. To keep that coverage, include the
pods/ephemeralcontainerssubresource in your resource rules, as the example does. - No audit of existing resources: a ValidatingAdmissionPolicy evaluates only incoming API server requests. It doesn't report existing resources that violate a ValidatingAdmissionPolicy.
- One message for each request: a ValidatingAdmissionPolicy reports the first validation that fails, not every violation.
Use Pod Security Admission for Pod security bundles
If you use the pss-baseline-v2022 or pss-restricted-v2022 bundles, then
replace the bundle with Pod Security Admission instead of translating each
constraint. Pod Security Admission uses the built-in Kubernetes PodSecurity
admission controller to enforce predefined rules from the
Kubernetes Pod Security Standards
based on namespace labels. The pss-baseline-v2022 bundle corresponds to the
baseline level, and the pss-restricted-v2022 bundle corresponds to the
restricted level.
Pod Security Admission doesn't cover every control in the psp-v2022 bundle,
such as allowlists for host paths, users, capabilities, and sysctls. Use
ValidatingAdmissionPolicies for those controls. Pod Security Admission also
can't exempt specific images, like Policy Controller constraints that use the
exemptImages parameter. GKE doesn't support configuring Pod
Security Admission exemptions. If you need exceptions, then use
ValidatingAdmissionPolicies for the affected policies.
For more information about how to configure Pod Security Admission, see Apply predefined Pod-level security policies using PodSecurity.
Migrate to self-managed OPA Gatekeeper
Choose Gatekeeper for the policies that ValidatingAdmissionPolicies can't express. Policy Controller is based on Gatekeeper, so your ConstraintTemplates and constraints use the same APIs in Gatekeeper. All templates in the Policy Controller template library work in Gatekeeper without changes to their logic. However, Gatekeeper uses a newer Rego engine and stricter validation that can reject a custom ConstraintTemplate.
When you use self-managed Gatekeeper, you become responsible for the tasks that Google Cloud performs for Policy Controller, such as installing, upgrading, scaling, and monitoring Gatekeeper on each cluster. Customer Care doesn't support open source Gatekeeper. For help, use the Gatekeeper GitHub issue tracker.
Gatekeeper doesn't include the Policy Controller template library or policy bundles. Your backup files contain the ConstraintTemplates and constraints from your clusters. For templates that originated in the open source Gatekeeper library, you can use the templates in the Gatekeeper policy library. Template names stay the same, but parameters and messages can differ between versions.
To move policies to Gatekeeper, follow these steps:
- Optional: If you can't accept a gap in enforcement while you replace
Policy Controller, then migrate your most important policies to
ValidatingAdmissionPolicies first. Make sure that those
ValidatingAdmissionPolicyBindings exclude the
gatekeeper-systemnamespace so that they don't block the Gatekeeper installation Jobs. After you remove Policy Controller, your cluster stops enforcing Gatekeeper policies until you apply the corresponding Gatekeeper constraints. ValidatingAdmissionPolicies keep enforcing because they don't depend on Policy Controller or Gatekeeper. If you use custom ConstraintTemplates, then test each custom template manifest by using the
gatorcommand-line tool from the Gatekeeper version that you plan to install:gator test --filename=TEMPLATE_FILEReplace
TEMPLATE_FILEwith the path to your ConstraintTemplate manifest file. Before you remove Policy Controller, fix any custom ConstraintTemplate that Gatekeeper rejects.If you deploy constraints from a Git repository by using a GitOps tool, then prepare the ConstraintTemplates that your constraints use and add them to the repository when you install Gatekeeper. Otherwise, your constraints fail to apply after you remove Policy Controller because their ConstraintTemplates no longer exist.
Remove Policy Controller by following the steps in Remove Policy Controller. Don't install Gatekeeper on a cluster that still runs Policy Controller. They both use the
gatekeeper-systemnamespace, the same CustomResourceDefinitions, and the same webhook names.Install Gatekeeper by using Helm, using the settings that you choose from the table in the next section, Gatekeeper settings that differ from Policy Controller. For more information about how to install Gatekeeper, see Installation in the Gatekeeper documentation.
On Autopilot clusters, the default Helm chart installation fails because GKE rejects wildcard rules in mutating webhooks. Set the
disableMutation: trueHelm value, or set themutatingWebhookCustomRulesHelm value to list only the specific resources that your mutators target. Don't include thenodes,persistentvolumes,certificatesigningrequests, ortokenreviewsresources.In your backup files, remove the following fields, labels, and annotations from each resource that you plan to reapply:
- The
statusfield. - The
resourceVersion,uid,creationTimestamp,generation,managedFields, andownerReferencesfields in themetadatasection. - The
kubectl.kubernetes.io/last-applied-configurationannotation. - The
app.kubernetes.io/managed-by: anthospolicycontroller.googleapis.comlabel. If Policy Controller is enabled on the cluster again, such as by a fleet-level default configuration, then it manages resources that have this label and can modify or delete them. - Labels and annotations whose keys have the
policycontroller.prefix.
- The
Apply the ConstraintTemplates that your constraints use, and then check that Gatekeeper created a CustomResourceDefinition for each template:
kubectl get constrainttemplates \ -o custom-columns='NAME:.metadata.name,CREATED:.status.created'When every template shows a
truevalue in theCREATEDcolumn, apply your constraints.
Gatekeeper settings that differ from Policy Controller
Before you install Gatekeeper, review the settings in the following table where the Gatekeeper Helm chart defaults differ from Policy Controller:
| Setting | Policy Controller default | Gatekeeper Helm chart default | Recommendation |
|---|---|---|---|
| Mutation | Off unless you turned it on | On | If you don't use mutation, then set the
disableMutation: true Helm value. On Autopilot
clusters, you must either set the disableMutation: true Helm
value or configure the mutatingWebhookCustomRules Helm value
without wildcards or restricted resources. If you don't specify one of
these values, then GKE rejects the installation. |
| Exempt namespaces | The gatekeeper-system namespace and the namespaces in
your exemptableNamespaces list |
The namespace where Gatekeeper is installed | Add your exempt namespaces to the
controllerManager.exemptNamespaces Helm value. Gatekeeper
rejects changes to namespaces that have the
admission.gatekeeper.sh/ignore label unless those namespaces
are exempt. |
| Referential data | Synced automatically for referential bundles | Not synced | Create a Gatekeeper Config or SyncSet that lists the kinds that your
referential templates read. Until those kinds sync into the
data.inventory object, conflict checks allow violating
requests, and existence checks, such as the
K8sRequireNamespaceNetworkPolicies ConstraintTemplate, deny
every matching request even when the required resource exists. |
| ValidatingAdmissionPolicy generation | Not available | On for templates that contain CEL code | Policy Controller templates contain only Rego, so Gatekeeper
generates ValidatingAdmissionPolicies only if you add CEL to your
ConstraintTemplates. To keep enforcement in the webhook, set the
defaultCreateVAPForTemplates: false and
defaultCreateVAPBindingForConstraints: false Helm values.
For more information, see
Integration with Kubernetes Validating Admission Policy in the
Gatekeeper documentation. |
| Replicas and resources | One replica for each component, with a 1,024 MiB memory limit | Three webhook replicas, with different resource limits | Configure the replica count and resource limits based on your current usage. |
| Images | Pulled from a Google-managed registry | Pulled from Docker Hub (the openpolicyagent/gatekeeper,
openpolicyagent/gatekeeper-crds, and
curlimages/curl images) |
For private clusters or clusters that enforce Binary Authorization,
mirror all three images to Artifact Registry and override their image
values in the chart. If you don't mirror the
curlimages/curl image, then disable the webhook probe
Job. |
By default, Gatekeeper exposes only Prometheus metrics, and its metric names differ from the names that Policy Controller sends to Cloud Monitoring. Update any dashboards and alerts that use Policy Controller metrics.
Migrate mutation policies
If you enabled mutation in Policy Controller, then list your mutators:
kubectl get assign,assignmetadata,assignimage,modifyset
For each mutator, choose one of the following options:
- MutatingAdmissionPolicy: you can use a MutatingAdmissionPolicy in GKE version 1.36 and later. Like a ValidatingAdmissionPolicy, a MutatingAdmissionPolicy uses CEL expressions and runs in the API server without a webhook. Kubernetes runs all MutatingAdmissionPolicies before ValidatingAdmissionPolicies, so test them together to make sure that a mutation doesn't cause a ValidatingAdmissionPolicy to reject a valid manifest. On Autopilot clusters, GKE excludes managed namespaces from MutatingAdmissionPolicies. For more information about mutating policies, see Mutating Admission Policy in the Kubernetes documentation.
- Self-managed Gatekeeper: on Standard clusters, your mutators
work without changes because Gatekeeper turns on mutation by default. On
Autopilot clusters, you must set the
mutatingWebhookCustomRulesHelm value in the Gatekeeper chart to list the specific resources that your mutators target instead of wildcard rules. For more information, see GKE Autopilot security measures. After you install Gatekeeper, remove the Policy Controller metadata from your mutator backup file and reapply your mutators, as you do for constraints.
Update policy checks in build pipelines
Your build pipeline might check manifests against your Policy Controller
constraints before deployment. For example, the pipeline might use the
gatekeeper function in kpt or the gator command-line tool. For more
information, see
Validate apps against company policies in a CI pipeline.
If your pipeline checks manifests, then update it for your replacement:
- If you use Gatekeeper, then you can keep your pipeline. Update the file or
directory paths in your
gatororkptcommand to reference the repository or directory that contains your cleaned Gatekeeper ConstraintTemplate and constraint manifests. If you use ValidatingAdmissionPolicies, then those tools don't evaluate your policies. Instead, run a server-side dry run against a test cluster that has your ValidatingAdmissionPolicies and ValidatingAdmissionPolicyBindings that use the
Denyaction:kubectl apply --dry-run=server -f MANIFEST_DIRECTORYReplace
MANIFEST_DIRECTORYwith the directory that contains your manifests. The command fails if a ValidatingAdmissionPolicy rejects a manifest.
Replace violation reporting
A ValidatingAdmissionPolicy doesn't include a dashboard, and it doesn't audit resources that already exist in your cluster. Use the following methods instead:
- Warnings: if a ValidatingAdmissionPolicyBinding uses the
Warnaction, then the API server returns a warning to the client that sent the request, such as thekubectlcommand-line tool. For Pods that a controller creates, such as the Pods in a Deployment, the controller receives the warning. Audit logs: if a ValidatingAdmissionPolicyBinding uses the
Auditaction, then the API server annotates the audit log entry for each failed validation. GKE writes create, update, and delete requests to Admin Activity audit logs in Cloud Logging. To find failed validations, run the following query in the Logs Explorer:resource.type="k8s_cluster" logName:"cloudaudit.googleapis.com%2Factivity" labels."validation.policy.admission.k8s.io/validation_failure":*
If you use constraints that have the dryrun enforcement action as a
compliance report on existing resources, then ValidatingAdmissionPolicies can't
replace that report. Keep those policies on self-managed Gatekeeper, whose
audit controller checks existing resources on a schedule.
Remove Policy Controller
Before you remove Policy Controller from a cluster, complete the following tasks:
- Confirm that any policies that you migrated to ValidatingAdmissionPolicies or Pod Security Admission are enforced and that you have a backup of your ConstraintTemplates, constraints, and mutators. Removing Policy Controller deletes its CustomResourceDefinitions, which deletes every ConstraintTemplate, constraint, and mutator on the cluster, including the ones that you created.
- If you deploy constraints from a Git repository by using a GitOps tool such as Config Sync or Argo CD, then remove the replaced constraints from the repository. Confirm that the constraints are removed from your clusters.
- Optional: To confirm that nothing depends on the Policy Controller webhook, suspend Policy Controller first. Suspending removes only the webhook configurations, and you can restore them.
To remove Policy Controller, follow these steps:
Uninstall Policy Controller from your clusters:
gcloud container fleet policycontroller disable \ --memberships=MEMBERSHIP_NAME \ --project=PROJECT_IDReplace the following:
MEMBERSHIP_NAME: the membership name of the registered cluster that you want to uninstall Policy Controller from. To uninstall Policy Controller from multiple clusters, specify a comma-separated list of membership names, or replace the--memberships=MEMBERSHIP_NAMEflag with the--all-membershipsflag.PROJECT_ID: the ID of your fleet host project.
Confirm that Policy Controller has finished uninstalling from your clusters:
gcloud container fleet policycontroller describe \ --memberships=MEMBERSHIP_NAME \ --project=PROJECT_ID \ --format="yaml(membershipStates)"Wait until the value of the top-level
policycontroller.statefield for each membership isNOT_INSTALLED, notDECOMMISSIONING. IndividualcomponentStatesentries reach theNOT_INSTALLEDstate before CustomResourceDefinition cleanup finishes.If you plan to install self-managed Gatekeeper, then confirm that the
gatekeeper-systemnamespace no longer exists:kubectl get namespace gatekeeper-systemWait until the output reports that the
gatekeeper-systemnamespace isn't found.Optional: To prevent clusters that you register later from getting Policy Controller, remove the fleet-level default configuration:
gcloud container fleet policycontroller enable \ --no-fleet-default-member-config \ --project=PROJECT_IDThis command removes only the default configuration. It doesn't install Policy Controller on any cluster.
Remove Policy Controller from clusters outside a fleet
The gcloud container fleet policycontroller disable command removes
Policy Controller only from clusters that the fleet manages. A cluster can run
Policy Controller without fleet management in the following cases:
- You installed Policy Controller by using the ConfigManagement Operator.
- You unregistered the cluster from its fleet, or ran the
gcloud container fleet policycontroller detachcommand, before Policy Controller finished uninstalling.
To remove Policy Controller from these clusters, bring the cluster under fleet management, and then uninstall Policy Controller:
- Back up your ConstraintTemplates, constraints, sync configuration, and
mutators, as described in
Inventory and classify your policies. When you
clean metadata from backups taken from a ConfigManagement Operator
installation, also remove the
configmanagement.gke.io/*andk8s-app: kubernetes-config-managementlabels in addition to theownerReferencesfield andpolicycontroller.*metadata. If you installed Policy Controller by using the ConfigManagement Operator, then remove the
policyControllerfield from the ConfigManagement custom resource on the cluster. Wait until reconciliation completes. Reconciliation can take about two minutes. Then, check whether thegatekeeper-systemnamespace still exists:kubectl get namespace gatekeeper-systemIn ConfigManagement Operator version 1.17 and earlier, removing the
policyControllerfield uninstalls Policy Controller automatically. If thegatekeeper-systemnamespace isn't found, then skip the remaining steps in this section. In ConfigManagement Operator version 1.18 and later, thegatekeeper-systemnamespace remains on the cluster, so continue to the next step.If the cluster isn't registered to a fleet, then register it. For more information, see Register a cluster on Google Cloud to your fleet.
Check whether mutation is enabled on the cluster:
kubectl get mutatingwebhookconfiguration \ gatekeeper-mutating-webhook-configurationEnable Policy Controller on the cluster's membership so that the fleet takes over management of the existing installation. If the preceding command returned the
gatekeeper-mutating-webhook-configurationresource, then include the--mutationflag so that the fleet adopts and later removes cluster-scoped mutation resources:gcloud container fleet policycontroller enable \ --memberships=MEMBERSHIP_NAME \ --project=PROJECT_IDReplace the following:
MEMBERSHIP_NAME: the membership name of your registered cluster.PROJECT_ID: the ID of your fleet host project.
Wait until the value of the
policycontroller.statefield for the membership isACTIVE:gcloud container fleet policycontroller describe \ --memberships=MEMBERSHIP_NAME \ --project=PROJECT_ID \ --format="yaml(membershipStates)"Uninstall Policy Controller by following the steps in Remove Policy Controller. If you aren't installing self-managed Gatekeeper, then delete any remaining constraint CustomResourceDefinitions after the
gatekeeper-systemnamespace is removed:kubectl get crd -o name \ | grep '\.constraints\.gatekeeper\.sh$' \ | xargs -r kubectl deleteOptional: If you registered the cluster only to complete this procedure, then unregister it after the
describecommand shows theNOT_INSTALLEDstate for the membership. For clusters that you registered by using the--enable-fleetflag, run thegcloud container clusters updatecommand with the--clear-fleet-projectflag instead of thegcloud container fleet memberships unregistercommand. For more information, see Unregistering a cluster.
What's next
- Read about Validating Admission Policy in the Kubernetes documentation.
- Learn how to apply predefined Pod-level security policies using PodSecurity.
- Read the Gatekeeper documentation.