Rancher projects are designed to provide a logical grouping of Kubernetes resources within a cluster, and by default, network traffic between pods in different projects is allowed. This article explains how to enforce network isolation between Rancher projects, preventing cross-project communication.

Let’s see this in action by setting up two projects, project-a and project-b, and deploying pods that attempt to communicate.

First, we’ll create a simple nginx deployment in project-a and a similar one in project-b.

project-a deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-a
  namespace: project-a
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-a
  template:
    metadata:
      labels:
        app: nginx-a
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

project-b deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-b
  namespace: project-b
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-b
  template:
    metadata:
      labels:
        app: nginx-b
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

After deploying these, if you try to curl from a pod in project-a to the ClusterIP of the nginx-b service (assuming you have services created for these deployments), it will succeed by default.

The core mechanism for controlling network traffic in Kubernetes is Network Policies. Rancher leverages these underlying Kubernetes objects to provide project-level network isolation. When you enable network isolation for a project, Rancher automatically creates and manages NetworkPolicy resources.

The problem Rancher Projects network isolation solves is one of security and multi-tenancy. In environments where multiple teams or applications share a Kubernetes cluster, it’s crucial to prevent them from interfering with each other or accessing sensitive data unintentionally. By default, Kubernetes’ CNI plugins allow all pod-to-pod communication. Network Policies allow you to define granular rules for which pods can communicate with which other pods, and on which ports.

When you enable "Project Network Isolation" in Rancher for a specific project, Rancher essentially applies a default NetworkPolicy to all pods within that project’s namespace. This default policy typically denies all ingress traffic unless it’s explicitly allowed. It also often allows all egress traffic by default, but this can be configured.

Let’s say you want to allow pods in project-a to communicate with pods in project-b on port 80. You would need to create a NetworkPolicy in project-b that explicitly permits ingress from project-a.

Here’s an example NetworkPolicy that would be applied to project-b to allow ingress from project-a:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-project-a
  namespace: project-b # This policy is applied to the 'project-b' namespace
spec:
  podSelector: {} # Selects all pods in the namespace
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          # Rancher adds this label to namespaces belonging to a project
          # The exact label might vary slightly based on Rancher version
          # or cluster configuration, but 'project-id' is common.
          # You can verify by 'kubectl get namespace --show-labels'
          project-id: <project-a-id>
    ports:
    - protocol: TCP
      port: 80

To find the <project-a-id>, you would typically look at the labels on the project-a namespace: kubectl get namespace project-a --show-labels. You’ll see labels like field.cattle.io/projectId=<project-a-id>.

The surprising truth about Network Policies is that they are deny-by-default if no policy selects a pod. However, if any NetworkPolicy selects a pod, then all ingress traffic to that pod is denied unless explicitly allowed by a policy. This means you can start with broad isolation and then selectively open up specific communication channels.

The "Project Network Isolation" feature in Rancher simplifies this by managing these policies for you at the project level. When you enable it, Rancher creates a "deny-all" ingress policy for the project’s namespace. Then, for any application that needs to receive traffic, you would create specific NetworkPolicies within that project’s namespace to allow ingress from desired sources (other projects, specific pods, or external IPs).

The most critical lever you control is the podSelector and namespaceSelector. By carefully defining these, you can sculpt very precise network traffic flows. A podSelector: {} combined with an ingress rule means "allow ingress to all pods in this namespace from the specified sources." If you wanted to restrict it to only pods with a specific label, say app: webserver, you’d change podSelector: {} to podSelector: { matchLabels: { app: webserver } }.

Conversely, if you want to allow egress from project-a to project-b, you would create a NetworkPolicy in project-a that specifies egress rules.

The next concept you’ll encounter is managing egress traffic more restrictively, which involves creating NetworkPolicies that define allowed outbound connections for pods within a project.

Want structured learning?

Take the full Rancher course →