Network policy understanding --> podSelector: {} vs namespaceSelector: for all pods from one ns

I came across this question in killercoda

my-app-deployment and cache-deployment deployed, and my-app-deployment deployment exposed through a service named my-app-service . Create a NetworkPolicy named my-app-network-policy to restrict incoming and outgoing traffic to my-app-deployment pods with the following specifications:

  • Allow incoming traffic only from pods within the same namespace.
  • Allow incoming traffic from a specific pod with the label app=trusted
  • Allow outgoing traffic to pods within the same namespace.
  • Deny all other incoming and outgoing traffic.

I used this netpol and it fails

apiVersion: networking.k8s.io/v1
		kind: NetworkPolicy
		metadata:
		  name: my-app-network-policy
		  namespace: default
		spec:
		  podSelector:
		    matchLabels:
		      app: my-app
		  policyTypes:
		  - Ingress
		  - Egress
		  ingress:
		  - from:
		    - namespaceSelector:
		        matchLabels:
		         kubernetes.io/metadata.name: default          
		    - podSelector:
		        matchLabels:
		          app: trusted
		  egress:
		  - to:
		    - namespaceSelector:
		        matchLabels:
         kubernetes.io/metadata.name: default

whereas the below works and I Don’t understand how, can someone pls explain?

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-app-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-app
  ingress:
    - from:
        - podSelector: {}
    - from:
        - podSelector:
            matchLabels:
              app: trusted
  egress:
    - to:
        - podSelector: {}

The first policy reads

  • Ingress
    • Allows pods in namespace default with labels app: my-app to receive traffic from all pods in namespaces with labels kubernetes.io/metadata.name: default on all ports
    • Allows pods in namespace default with labels app: my-app to receive traffic from pods in the same namespace with labels app: trusted on all ports
  • Egress
    • Allows pods in namespace default with labels app: my-app to connect to all pods in namespaces with labels kubernetes.io/metadata.name: default on all ports

The second policy reads

  • Ingress
    • Allows pods in namespace default with labels app: my-app to receive traffic from all pods in the same namespace on all ports (denies inbound traffic to pods in namespace default with labels app: my-app from other namespaces)
    • Allows pods in namespace default with labels app: my-app to receive traffic from pods in the same namespace with labels app: trusted on all ports
  • Egress
    • Allows pods in namespace default with labels app: my-app to connect to all pods in the same namespace on all ports (denies outbound traffic from pods in namespace default with labels app: my-app to other namespaces)

Compare these with the question requirements

So

  • podSelector: {} means “all pods in the same namespace”. You don’t need to know the name of the namespace, just that it means the same namespace where the netpol is deployed. This makes the policy portable to other namespaces.
  • If you use namespaceSelector to mean all pods, then you need to explicitly specify a selector for the namespace. You use this method when you want to say all pods in another known namespace.
1 Like

so can the first Ingress net pol mean the below?

  • Allows pods in namespace default with labels app: my-app to receive traffic from all pods from all namespaces with labels kubernetes.io/metadata.name: default on all ports

It could, BUT kubernetes.io/metadata.name is a system label applied when the namespace is created and its values are unique (they are the name given from kubectl create namespace), so you cannot have 2 namespaces with the same value for this label.

You could apply your own label with the same value to multiple namespaces and use that in a policy, then all the pods from all the namespaces with this label/value would be in scope.

I couldn’t figure out the correct answer for killercoda. But seems that my options were correct. In my case the question was changed:

  • Allow incoming traffic only from pods.
  • Allow incoming traffic from a specific pod with the label app=trusted
  • Allow outgoing traffic to pods.
  • Deny all other incoming and outgoing traffic.

I’ve tried a lot of variations of this:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-app-network-policy
spec:
  podSelector:
    matchLabels:
      app: my-app-deployment

  # Define ingress (incoming) rules
  ingress:
    - from:
        - podSelector: {} // Allow incoming traffic only from pods (all namespaces).
          namespaceSelector: {}
        - podSelector:
            matchLabels:
              app: trusted //Allow incoming traffic from a specific pod with the label `app=trusted` (all namespaces)
          namespaceSelector: {}

  egress:
    - to:
        - podSelector: {} // Allow outgoing traffic to pods. (all namespaces)
          namespaceSelector: {}

  policyTypes:
    - Ingress
    - Egress

I had a similar issue with the same question.

This was my first approach:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-app-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-app
  ingress:
    - from:
        - podSelector: {}
        - podSelector:
            matchLabels:
              app: trusted
  egress:
    - to:
        - podSelector: {}

I needed to modify it as follows:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-app-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-app
  ingress:
    - from:
        - podSelector: {}
    - from:
        - podSelector:
            matchLabels:
              app: trusted
  egress:
    - to:
        - podSelector: {}

It has a minimum change, so I think the reason is the use of AND vs OR when we use multiple rules, I am reviewing the documentation to understand my first issue.

I read the docs, however, I hope you can help me to clarify or confirm the following, please.

  ingress:
    - from:
        - podSelector: {}
        - podSelector:
            matchLabels:
              app: trusted

For the above case, the meaning is: allow ingress traffic from any pod in the same namespace OR only pods with the label app=trusted. Is that correct?

ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              env: prod
 
          podSelector:
            matchLabels:
              app: trusted

For the above case, the meaning is: allow ingress traffic only pods with the label app=trusted AND they live in a namespace labeled with env=prod. Is that correct?

  ingress:
    - from:
        - podSelector: {}
          podSelector:
            matchLabels:
              app: trusted

For the above case, the meaning is: allow ingress traffic only pods with the label app=trusted, this behavior is because the second element overrode the first one, so it is taken as the last one. Is that correct?

  ingress:
    - from:
        - podSelector: {}
    - from:
        - podSelector:
            matchLabels:
              app: trusted

What is the meaning of that policy, it looks like it is very similar to the first one, however, kubectl describe command generates a slightly different output, but I could not understand the meaning. Could you clarify, please?

@Philippe-Geraldeli @Emmanuel-Garcia

To help you understand policies better, you can use this resource to get an explanation of a given policy.

Just paste the policy to the editor window and it will decode it.

Thanks @Alistair_KodeKloud

According to that tool, the first one and the last one have the same policies, maybe Killercoda is waiting for a format similar to the last one.

I am going to continue investigating but in the k8s docs, I could not find an example using two “form” entries.

Still: 2 “from” blocks are OR-ed together. If one of them is “grant all”, then the second one is essentially ignored.