<p>I have a multi-tenant cluster, where multi-tenancy is achieved via namespaces. Every tenant has their own namespace. Pods from a tenant cannot talk to pods of other tenants. However, some pods in every tenant have to expose a service to the internet, using an Ingress.</p>

<p>This I how far I got (I am using Calico):</p>

<pre><code>apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant1-isolate-namespace
  namespace: tenant1
spec:
  policyTypes:
  - Ingress
  podSelector: {} # Select all pods in this namespace
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: tenant1 # white list current namespace
</code></pre>

<p>Deployed for each namespace (<code>tenant1</code>, <code>tenant2</code>, ... ), this limits communication between pods within their namespace. However, this prevents pods from the <code>kube-system</code> namespace to talk to pods in this namespace.</p>

<p>However, the <code>kube-system</code> namespace does not have any labels by default so I can not specifically white list this namespace.</p>

<p>I found a (dirty) workaround for this issue by manually giving it a label:</p>

<pre><code>kubectl label namespace/kube-system permission=talk-to-all
</code></pre>

<p>And adding the whitelist rule to the networkpolicy:</p>

<pre><code>...
  - from:
    - namespaceSelector:
        matchLabels:
          permission: talk-to-all # allow namespaces that have the "talk-to-all privilege"
</code></pre>

<p>Is there a better solution, without manually giving <code>kube-system</code> a label?</p>

<p><strong>Edit:</strong> I tried to additionally add an "OR" rule to specifically allow communication from pods that have the label "app=nginx-ingress", but without luck:</p>

<pre><code>  - from
    ...
    - podSelector:
        matchLabels:
          app: nginx-ingress # Allow pods that have the app=nginx-ingress label
</code></pre>

<p><strong><a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/" rel="nofollow noreferrer">apiVersion: networking.k8s.io/v1</a></strong> </p>

<p>The namespaceSelector is designed to match namespaces by labels only. There is no way to select namespace by name.</p>

<p>The podSelector can only select pods in the same namespace with NetworkPolicy object. For objects located in different namespaces, only selection of the whole namespace is possible.</p>

<p>Here is an example of Kubernetes Network Policy implementation:</p>

<pre><code>apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978
</code></pre>

<p>Follow this <a href="https://ahmet.im/blog/kubernetes-network-policy/" rel="nofollow noreferrer">link</a> to read a good explanation of the whole concept of Network policy, or this <a href="https://www.youtube.com/watch?v=3gGpMmYeEO8" rel="nofollow noreferrer">link</a> to watch the lecture.</p>

<p><strong><a href="https://docs.projectcalico.org/v3.1/reference/calicoctl/resources/networkpolicy" rel="nofollow noreferrer">apiVersion: projectcalico.org/v3</a></strong></p>

<p>Calico API gives you more options for writing NetworkPolicy rules, so, at some point, you can achieve your goal with less efforts and mind-breaking. </p>

<p>For example, using Calico implementation of Network Policy you can: </p>

<ul>
<li>set action for the rule (Allow, Deny, Log, Pass), </li>
<li>use negative matching (protocol, notProtocol, selector, notSelector), </li>
<li>apply more complex label selectors(has(k), k not in { ‘v1’, ‘v2’ }),</li>
<li>combine selectors with operator &amp;&amp;,</li>
<li>use port range (ports: [8080, "1234:5678", "named-port"]),</li>
<li>match pods in other namespaces.</li>
</ul>

<p>But still, you can match namespaces only by labels.</p>

<p>Consider reading Calico <a href="https://docs.projectcalico.org/v3.1/reference/calicoctl/resources/networkpolicy" rel="nofollow noreferrer">documentation</a> for the details.</p>

<p>Here is an example of Calico Network Policy implementation:</p>

<pre><code>apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-tcp-6379
  namespace: production
spec:
  selector: role == 'database'
  types:
  - Ingress
  - Egress
  ingress:
  - action: Allow
    protocol: TCP
    source:
      selector: role == 'frontend'
    destination:
      ports:
      - 6379
  egress:
  - action: Allow
</code></pre>
