Whitelist "kube-system" namespace using NetworkPolicy
apiVersion: networking.k8s.io/v1
The namespaceSelector is designed to match namespaces by labels only. There is no way to select namespace by name.
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.
Here is an example of Kubernetes Network Policy implementation:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: test-network-policy namespace: defaultspec: 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
Follow this link to read a good explanation of the whole concept of Network policy, or this link to watch the lecture.
apiVersion: projectcalico.org/v3
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.
For example, using Calico implementation of Network Policy you can:
- set action for the rule (Allow, Deny, Log, Pass),
- use negative matching (protocol, notProtocol, selector, notSelector),
- apply more complex label selectors(has(k), k not in { ‘v1’, ‘v2’ }),
- combine selectors with operator &&,
- use port range (ports: [8080, "1234:5678", "named-port"]),
- match pods in other namespaces.
But still, you can match namespaces only by labels.
Consider reading Calico documentation for the details.
Here is an example of Calico Network Policy implementation:
apiVersion: projectcalico.org/v3kind: NetworkPolicymetadata: name: allow-tcp-6379 namespace: productionspec: selector: role == 'database' types: - Ingress - Egress ingress: - action: Allow protocol: TCP source: selector: role == 'frontend' destination: ports: - 6379 egress: - action: Allow
Indeed, tenant1
pods will need access to kube-dns
in the kube-system
namespace specifically.
One approach without requiring kube-system
namespace to be labelled is the following policy. Although kube-dns
could be in any namespace with this approach so it may not be suitable for you.
--- # Default deny all ingress & egress policy, except allow kube-dns # All traffic except this must be explicity allowed. kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: default-deny-all-except-kube-dns namespace: tenant1 spec: podSelector: {} egress: - to: - podSelector: matchLabels: k8s-app: kube-dns - ports: - protocol: TCP port: 53 - protocol: UDP port: 53 policyTypes: - Ingress - Egress
Then, you would need also need an 'allow all within namespace policy' as follows:
--- # Allow intra namespace traffic for development purposes only. kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-intra-namespace namespace: tenant1 spec: podSelector: matchLabels: ingress: - from: - podSelector: {} egress: - to: - podSelector: {} policyTypes: - Ingress - Egress
Lastly, you will want to add specific policies such as an ingress rule. It would be better to replace the allow-intra-namespace
policy with specific rules to suit individual pods, which your tenant1
could do.
These have been adapted from this website: https://github.com/ahmetb/kubernetes-network-policy-recipes
If i understood correctly you are using calico. Just use their example on how to implement default-deny without breaking kube-dns communication.Found here
apiVersion: projectcalico.org/v3kind: GlobalNetworkPolicymetadata: name: deny-app-policyspec: namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system", "calico-system"} types: - Ingress - Egress egress: # allow all namespaces to communicate to DNS pods - action: Allow protocol: UDP destination: selector: 'k8s-app == "kube-dns"' ports: - 53