How can I isolate pods in namespace using NetworkPolicy without disabling external traffic to Kubernetes pods

Cluster information:

Kubernetes version:1.14.10
Cloud being used: (put bare-metal if not on a public cloud)
Installation method:kubeadm
Host OS: centos
CNI and version:calico 3.7
CRI and version: 18.06.3-ce

I am trying to isolate my pods in namespace from other namespaces. I have tried to create a NetworkPolicy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-from-other-namespaces
  namespace: dev-ns
spec:
  podSelector:
    matchLabels:
  ingress:
  - from:
    - podSelector: {}

This NetworkPolicy successfully isolating pods in my namespace from another namespace. But this policy, once applied, disables all external traffic to these pods.
For example when i request the service by its <EXTERNAL_IP>:<PORT> , then the network policy will deny the ingress traffic from the service and the request will time out

Is there any method for only block traffic from other namespaces and allow all external traffic to the pods.

I think you have to use namespaceSelector instead of podSelector to block other namespaces traffic.

@tej-singh-rana ,Yes we can do this using namespace selector in ingress field ,and this block traffic from another namespace,which is fine . But the issue is both methods will block traffic from outside the cluster via NodePort

I think it’s blocked dns service too so not able to resolv. Open port for dns (53).

@tej-singh-rana . No port 53 is open and working fine without Network Policy …

Here’s an example Scenario: allow requests from ns2 to ns1 only, on port 80

create namespace ns1 and ns2

kubectl create ns ns1
kubectl create ns ns2

label namespace ns2

kubectl label ns ns2 ns=ns2

apply network policy on ns1

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

Test this,

create busybox on ns2

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: bb
  name: bb
spec:
  containers:
  - name: bb
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello; sleep 3600;done"]
    name: bb
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

create nginx on ns1

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    ports:
    - containerPort: 80
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

expose this service,

kubectl expose svc nginx --port=80 --type=NodePort -n ns1

Now try to do wget from ns2 to ns1

kubectl exec -it bb -n ns2 -- sh 
wget http://nginx.ns1

You can try to deploy the busybox on default namespace and test it to see if it allows the request or not.

a perfect soluction if you can use Calico

  1. namespace have tag tianbao=“dev” , can not ping each other
  2. able ping public traffic
  3. public able to access pod
  4. nodePort is working fine.
  5. remember to add tag (tianbao=“dev”) to new namespace
kubectl label namespaces test1 tianbao="dev"

kubectl label namespaces test2 tianbao="dev"

cat <<EOF | kubectl apply -f -
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
  name: deny-dev-namesapce-to-test
spec:
  namespaceSelector: env == "test1"
  ingress:
  - action: Allow
  egress:
  - action: Allow
    destination:
      namespaceSelector: env == "test1"
  - action: Deny
    destination:
      namespaceSelector: tianbao == "dev"
  - action: Allow
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
  name: deny-dev-namesapce-to-test
spec:
  namespaceSelector: env == "test2"
  ingress:
  - action: Allow
  egress:
  - action: Allow
    destination:
      namespaceSelector: env == "test2"
  - action: Deny
    destination:
      namespaceSelector: tianbao == "dev"
  - action: Allow
EOF