You can’t actually isolate Dev and Prod workloads in Rancher by simply putting them in different projects.
Here’s what that looks like in practice:
apiVersion: v1
kind: Pod
metadata:
name: dev-app-pod
namespace: dev-ns
labels:
app: my-dev-app
spec:
containers:
- name: main
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: prod-app-pod
namespace: prod-ns
labels:
app: my-prod-app
spec:
containers:
- name: main
image: nginx:latest
ports:
- containerPort: 80
In Rancher, projects are a logical grouping mechanism, not a hard security boundary. They help organize resources and apply RBAC within a cluster. But by default, all projects within the same cluster share the same underlying Kubernetes API server, etcd, and node resources. This means a misconfiguration, a resource exhaustion event, or even a compromised pod in your "dev" project can absolutely impact your "prod" project if they reside on the same cluster.
The core problem is that "isolation" implies a strong boundary, and Rancher’s project abstraction, while useful for organization and access control, doesn’t provide that inherent environmental separation at the cluster level.
So, how do you actually achieve meaningful separation? You need to leverage Kubernetes primitives that create distinct environments. The most straightforward and common way is to use separate Kubernetes clusters.
Method 1: Separate Clusters
This is the gold standard for true isolation. Each cluster is an independent Kubernetes control plane and node pool.
- Diagnosis: Check your Rancher UI. If your "dev" and "prod" projects are listed under the same cluster, they are not isolated.
- Fix:
- In Rancher, navigate to
Cluster Management. - Click
Create Cluster. - Choose your infrastructure provider (e.g., RKE1, RKE2, K3s, cloud provider) and configure it for your dev environment.
- Repeat steps 2-3 for your prod environment.
- Once both clusters are provisioned, create a "dev" project in the dev cluster and a "prod" project in the prod cluster.
- In Rancher, navigate to
- Why it works: Each cluster has its own distinct API server, etcd, and scheduler. A runaway process or resource leak in the dev cluster cannot affect the prod cluster because they are entirely separate Kubernetes control planes. Node resources are also segregated.
Method 2: Namespaces with Resource Quotas and Network Policies (Less Isolation)
If separate clusters are cost-prohibitive, you can achieve some level of separation within a single cluster using namespaces, combined with strict resource management and network controls. This is not true isolation, but it’s a significant improvement over just using Rancher projects.
- Diagnosis: You’re using different namespaces for dev and prod, but you don’t have
ResourceQuotaorNetworkPolicyobjects defined for these namespaces. You can also check if pods fromdev-nscancurlpods inprod-nsdirectly. - Fix:
- Namespaces: Ensure you have distinct namespaces, e.g.,
dev-nsandprod-ns. Rancher projects map to these namespaces. - Resource Quotas: Apply
ResourceQuotaobjects to each namespace to limit CPU, memory, storage, and object counts.- Example for
dev-ns:apiVersion: v1 kind: ResourceQuota metadata: name: dev-quota namespace: dev-ns spec: hard: requests.cpu: "10" # Max 10 CPU cores requested across all pods requests.memory: 20Gi # Max 20Gi RAM requested limits.cpu: "20" # Max 20 CPU cores allowed limits.memory: 40Gi # Max 40Gi RAM allowed pods: "50" # Max 50 pods services: "20" # Max 20 services - Example for
prod-ns:apiVersion: v1 kind: ResourceQuota metadata: name: prod-quota namespace: prod-ns spec: hard: requests.cpu: "50" # More resources for prod requests.memory: 100Gi limits.cpu: "100" limits.memory: 200Gi pods: "100" services: "50" - Why it works:
ResourceQuotaprevents a single namespace (and its pods) from consuming all cluster resources, thereby starving other namespaces. It enforces a hard cap on what can be requested and limited.
- Example for
- Network Policies: Implement
NetworkPolicyto restrict pod-to-pod communication.- Example: Deny all ingress to
prod-nsexcept from specifickube-systempods andprod-ingress-controller:apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-ingress-to-prod namespace: prod-ns spec: podSelector: {} # Selects all pods in the namespace policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system # Allow core K8s components - podSelector: matchLabels: app: prod-ingress-controller # Allow traffic from your prod ingress - Example: Deny all egress from
dev-nsexcept to specific external IPs or allowed internal services:apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-egress-from-dev namespace: dev-ns spec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 10.0.0.0/8 # Example: Allow access to internal cluster CIDR - podSelector: matchLabels: app: dev-database # Allow access to dev database - to: - ipBlock: cidr: 8.8.8.8/32 # Example: Allow access to specific external IP (e.g., DNS) - Why it works:
NetworkPolicyacts like a firewall within the cluster, controlling which pods can communicate with each other. By default, if no policies are applied, all pods can talk to all other pods. Applying restrictive policies ensures dev pods cannot accidentally (or maliciously) reach prod services, and vice-versa.
- Example: Deny all ingress to
- Limit Ranges: While
ResourceQuotasets namespace-wide limits,LimitRangecan set default resource requests/limits for containers within a namespace and enforce minimums/maximums per pod.- Example for
dev-ns:apiVersion: v1 kind: LimitRange metadata: name: dev-limits namespace: dev-ns spec: limits: - type: Container default: cpu: "200m" memory: "256Mi" defaultRequest: cpu: "100m" memory: "128Mi" max: cpu: "1" memory: "1Gi" min: cpu: "50m" memory: "64Mi" - Why it works: This ensures that even if a developer forgets to set resource requests/limits on their pod spec, reasonable defaults are applied, and they can’t request absurd amounts of resources for a single container.
- Example for
- Namespaces: Ensure you have distinct namespaces, e.g.,
The One Thing Most People Don’t Know
Even with separate clusters, if you’re using Rancher’s multi-cluster management features to view and manage both dev and prod clusters from a single pane of glass, you’re still interacting with a single Rancher API. A compromise of your Rancher instance itself could potentially expose access to both environments. The true isolation is at the Kubernetes cluster level, but the management layer introduces its own potential blast radius.
The next hurdle you’ll face is managing secrets and configurations consistently across these isolated environments without introducing duplication or drift.