2

On an Azure AKS cluster with the Calico network policies plugin enabled, I want to:

  1. by default block all incoming traffic.
  2. allow all traffic within a namespace (from a pod in a namespace, to another pod in the same namespace.

I tried something like:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny.all
  namespace: test
spec:
  podSelector: {}
  policyTypes:
  - Ingress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow.same.namespace
  namespace: test
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector: {}
  policyTypes:
  - Ingress

But is seems to block traffic between two deployments/pods in the same namespace. What am I doing wrong, am I misreading the documentation?

Perhaps it is good to mention that the above setup seems to work on an AWS EKS based Kubernetes cluster.

Wouter
  • 1,290
  • 2
  • 16
  • 24
  • As soon as you have a specific allow rule matching a resource, everything else will be denied for that resource anyway. So you don't need to add deny all here. – The Fool Jan 19 '22 at 14:36
  • I removed the deny all rule, it results in traffic within the same namespace to be blocked. – Wouter Jan 19 '22 at 15:39
  • Are you sure there are no additional network policies that may couse the issue? You can check with `kubectl get networkpolicies.networking.k8s.io -n `. Did you enable Calico network policy feature on AKS? More [here](https://learn.microsoft.com/en-us/azure/aks/use-network-policies#create-an-aks-cluster-for-calico-network-policies) –  Jan 20 '22 at 08:35
  • I did remove the other network policies in the namespace. Calico is enabled on AKS. – Wouter Jan 20 '22 at 08:45
  • There is a similar issue on SO already, with accepted answer [here](https://stackoverflow.com/a/67804399/10347794), does this help with your issue? –  Jan 20 '22 at 13:13
  • Yes, I found part of the reason why it was not working. See my accepted answer. – Wouter Feb 01 '22 at 11:37

3 Answers3

1

After investigation it turned out that:

  1. I used terraform to create a k8s cluster with two node pools. System, and worker. (Note: that this is (not yet) possible in the GUI).
  2. Both node pools are in different subnets (system subnet, and worker subnet).
  3. AKS configures kubeproxy to masquerade traffic that goes outside the system subnet.
  4. Pods are deployed on the worker node, and thus use the worker subnet. All traffic that they send outside the node they are running on, is masqueraded.
  5. Calico managed iptables drop the masqueraded traffic. I did not look into more details here.
  6. However, if I change the kubeproxy masquerade setting to either a larger CIDR range, or remove it all together, it works. Azure however resets this setting after a while.

In conclusion. I tried to use something that is not yet supported by Azure. I now use a single (larger) subnet for both node pools.

Wouter
  • 1,290
  • 2
  • 16
  • 24
  • this answer pointed me to good direction, in my case netpol was not correctly supported by kube-router, when pods were not on same node, they was not allowed to communicate when there was netpol configured, after switched to calico all network-policies rules was working as expected – DevTheJo May 28 '23 at 16:05
0

You can label the Namespace first like

kubectl label ns <Namespace name> env: test

and apply the policy like

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-labled-namespace
spec:
  podSelector: {} 
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          env: test
    ports:
    - protocol: TCP
      port: 80

so this network policy will allow traffic only from that namespace which has a specific label test.

Harsh Manvar
  • 27,020
  • 6
  • 48
  • 102
  • I tried to remove the deny all rule, and replaced the same.namespace rule with yours. I changed the matchLabels to kubernetes.io/metadata.name: test. Traffic within the namespace seems to be blocked. – Wouter Jan 19 '22 at 15:40
0

If you are using Calico, you can apply one GlobalNetworkPolicy to deny Ingress that is valid for all existing and future Namespaces:

apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
  name: default-global-deny-all-ingress
spec:
  namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system", "calico-system", "tigera-operator"}
  order: 3000 # normal NPs (order: 1000) should have higher order
  types:
    - Ingress
  ingress:
    # allow collect metrics from Kubernetes Metrics Server
    - action: Allow
      protocol: TCP
      destination:
        selector: 'k8s-app == "metrics-server"'
        ports:
          - 443
    # Deny all ingress
    - action: Deny
      source:
        nets:
          - 0.0.0.0/0

Important is that the order is above 1000 as this is the default order for NetworkPolicies. Now you can use Kuberentes 1.21 default Namespaces labels for your policy per Namespace(Example for ingress-nginx) :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ingress-allow-ingress-nginx
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ingress-nginx
          podSelector: {}
Philip Welz
  • 2,449
  • 5
  • 12