DEV Community

Cover image for Taking control of cluster security: A deep dive into GKE ClusterNetworkPolicy
Olivier Bourgeois for Google Cloud

Posted on

Taking control of cluster security: A deep dive into GKE ClusterNetworkPolicy

In Kubernetes, network security has historically been a developer-centric responsibility. Standard Kubernetes NetworkPolicy objects are namespace-scoped. While this works beautifully for isolating individual microservices within a single application boundary, it introduces major operational headaches at scale. As clusters grow to accommodate multiple teams, business units, and environments, platform administrators are left without a native mechanism to enforce global security guardrails.

If you want to ensure that every pod in your cluster is blocked from reaching the cloud metadata server, or that certain namespaces are completely isolated from all others, you are forced to rely on complex policy engines, custom admission controllers, or automating the injection of namespace-scoped policies. This approach is fragile and difficult to audit.

The introduction of the GKE ClusterNetworkPolicy (currently in Public Preview) addresses this challenge. It introduces a cluster-scoped resource that allows security and platform teams to establish non-overridable security boundaries across the entire cluster, spanning all namespaces.

Evaluation hierarchy

To understand ClusterNetworkPolicy, you must first understand how GKE evaluates network traffic. Unlike standard namespace-scoped NetworkPolicy resources, which are additive (meaning if multiple policies select a pod, the traffic is allowed if any policy permits it), ClusterNetworkPolicy uses a strict, sequential evaluation pipeline where the first matching rule wins.

Traffic flows through three distinct policy tiers in order:

  1. Admin tier: Policies in this tier are evaluated first. This is where administrators define mandatory guardrails that developers cannot bypass. If a rule in this tier matches a traffic flow with an Accept or Deny verdict, evaluation stops immediately.
  2. NetworkPolicy tier: If traffic is not explicitly allowed or blocked by the Admin tier, it falls through to standard namespace-scoped NetworkPolicy resources configured by DevOps teams and developers.
  3. Baseline tier: If no namespace-scoped policies match the traffic, it falls through to the Baseline tier. Here, administrators can define fallback policies, such as a default-deny posture, which developers can choose to override in their respective namespaces.
  4. Default GKE behavior: If a packet matches no rules in any tier, it falls back to GKE's default behavior, which is an implicit allow.

Within each tier, policies are evaluated based on an explicit numeric priority (0 to 1000, where lower numbers indicate higher precedence). Inside a single policy object, rules are evaluated from top to bottom.

Verdict actions: Accept, deny, pass

Every rule in a ClusterNetworkPolicy must trigger one of three actions:

  • Deny: Blocks the traffic immediately. This action short-circuits the evaluation pipeline.
  • Accept: Permits the traffic immediately. This also short-circuits the pipeline.
  • Pass: Transfers the evaluation to the next tier in the hierarchy.

The Pass action is particularly powerful. It enables platform administrators to target specific traffic flows—for example, web traffic on port 8080—and delegate the final decision to namespace owners. The traffic will bypass any remaining rules in the Admin tier and be evaluated against standard namespace-scoped network policies. If the namespace owners configure a policy to accept the traffic, it is allowed; if they have no policy, the traffic proceeds to the Baseline tier. This strikes a balance between centralized compliance and developer agility.

YAML examples

Let's examine how to write these policies. Consider a scenario where you want to isolate a sensitive namespace from all internal cluster traffic. By placing this policy in the Admin tier, you guarantee that namespace-scoped policies cannot override it.

Here is a manifest for a global deny policy targeting a sensitive namespace:

apiVersion: policy.networking.k8s.io/v1alpha2
kind: ClusterNetworkPolicy
metadata:
  name: cluster-wide-deny-sensitive
spec:
  tier: Admin
  priority: 10
  subject:
    namespaces:
      matchLabels:
        kubernetes.io/metadata.name: sensitive-ns
  ingress:
  - action: Deny
    name: deny-all-ingress
    from:
    - namespaces:
        matchLabels: {}
  egress:
  - action: Deny
    name: deny-all-egress
    to:
    - namespaces:
        matchLabels: {}
Enter fullscreen mode Exit fullscreen mode

Now, consider a different scenario: you want to establish a default-deny posture across the cluster, but you want to allow developers to open up traffic as needed for their applications. For this, you use the Baseline tier.

Here is a baseline default-deny policy:

apiVersion: policy.networking.k8s.io/v1alpha2
kind: ClusterNetworkPolicy
metadata:
  name: default-deny-baseline
spec:
  tier: Baseline
  priority: 100
  subject:
    namespaces: {}
  ingress:
  - action: Deny
    name: baseline-deny-all
    from:
    - namespaces: {}
Enter fullscreen mode Exit fullscreen mode

If a developer in the namespace my-app-ns needs to allow ingress traffic to their frontend service from an external ingress controller, they can simply deploy a standard namespace-scoped NetworkPolicy that permits that traffic. Because the standard policy is evaluated in the NetworkPolicy tier (which runs before the Baseline tier), GKE will permit the traffic without needing platform admin intervention.

Under the hood

The GKE implementation of ClusterNetworkPolicy is built entirely on open-source Cilium, reinforcing a commitment to community-driven foundations. GKE backported this support to Cilium 1.19 for GKE clusters, and the upstream capability will be generally available to the broader open-source ecosystem starting with Cilium 1.20.

To use this feature, your GKE clusters must meet the following requirements:

  • Run GKE version 1.36.0-gke.4447000 or later.
  • Use GKE Dataplane V2.

As this feature is in Public Preview, there are a few scale limits to keep in mind. Specifically, a single ClusterNetworkPolicy object can contain a maximum of 100 ingress rules and 100 egress rules. You can monitor traffic flow verdicts and troubleshoot your policies using GKE Dataplane V2 Observability tools.

By decoupling cluster-wide guardrails from namespace-level configurations, ClusterNetworkPolicy gives security teams the control they need without hindering developer speed.

To get started with configuring cluster-wide security policies on your clusters, check out the official GKE ClusterNetworkPolicy documentation for step-by-step guides and YAML examples.

Top comments (0)