skip to Main Content

By default pods can communicate with each other in Kubernetes, which is unwanted should a pod be compromised. We want to use NetworkPolicies to control inbound (ingress) and outbound (egress) traffic to/from pods.

Specifically pods should ONLY be able to:

  • Egress: Call services on the internet
  • Ingress: Receive requests from the Nginx-ingress controller
  • Ingress: Send logs via promtail to Loki

What I have tried

1. Denying all ingress and egress

This is the default policy that we want to gradually open up. It blocks all ingress and egress.

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

2. Opening egress to internet only

We allow egress only to IP-adresses that are not reserved for private networks according to wikipedia.

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: egress-allow-internet-only
  namespace: mynamespace
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.0.0.0/8
        - 172.16.0.0/12
        - 192.168.0.0/16

3. Opening Ingress from ingress controller and loki

We have deployed the standard NginX Ingress Controller in namespace default, and it has the lable app.kubernetes.io/name=ingress-nginx. We have also deployed the standard loki-grafana stack to the default namespace, which uses promtail to transfer logs to Loki. Here I allow pods to recieve ingress from the promtail and ingress-nginx pods.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ingress-allow-ingress-controller-and-promptail
  namespace: mynamespace
spec:
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name=default
    - podSelector:
        matchLabels:
          app.kubernetes.io/name=ingress-nginx
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name=default
    - podSelector:
        matchLabels:
          app.kubernetes.io/name=promtail

So, does this configuration look right?

I am new to Kubernetes, so I hope you guys can help point me in the right direction. Does this configuration do what I intent it to do, or have I missed something? E.g. is it enough that I have just blocked egress within the private network to ensure that the pods are isolated from each other, or should I also make the ingress configuration as I have done here?

2

Answers


  1. Chosen as BEST ANSWER

    For those curious I ended with the following network policy:

    ---
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: deny-all
      namespace: <K8S_NAMESPACE> 
    spec:
      podSelector: {}
      policyTypes:
        - Ingress
        - Egress
    ---
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-internet
      namespace: <K8S_NAMESPACE>
    spec:
      podSelector: {}
      policyTypes:
      - Egress
      - Ingress
      egress:
      - to:
        - ipBlock:
            cidr: "0.0.0.0/0"
            except:
            - "10.0.0.0/8"
            - "172.16.0.0/12"
            - "192.168.0.0/16"
      - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: "kube-system"
        - podSelector:
            matchLabels:
              k8s-app: "kube-dns"
    ---
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-ingress-from-ingresscontroller
      namespace: <K8S_NAMESPACE>
    spec:
      podSelector: {}
      policyTypes:
        - Ingress
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: "default"
        - podSelector:
            matchLabels:
              app.kubernetes.io/name: "ingress-nginx"
    ---
    

    It turned out that the DNS server had to be added to allow-internet and that it was not necessary to add allow-ingress-from-promtail, as promtail gets the log in another way that through ingress.


  2. I have compared your Ingress with K8 Doc and Egress with this SO and deny Both ingress and Egress seems to be correct.The only thing we need to do is check whether all the name space is given correct or not. Seems to be correct as per your YAML file.

    But kubernetes pods use the DNS server inside Kubernetes; due to this DNS server being blocked, we need to define more specific IP ranges to allow DNS lookups. Follow this SO to define DNS config at pod levels and to get curl calls with domain names allow Egress to Core DNS from kube-system(by adding a namespace selecter (kube-system) and a pod selector (dns pods)).

    How to identify dns pod

    # Identifying DNS pod
    kubectl get pods -A | grep dns
    
    # Identifying DNS pod label
    kubectl describe pods -n kube-system coredns-64cfd66f7-rzgwk
    

    Adding DNS pod to NetworkPolicy

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: egress-allow-internet-only
      namespace: mynamespace
    spec:
      podSelector: {}
      policyTypes:
      - Egress
      egress:
      - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
            - 10.0.0.0/8
            - 172.16.0.0/12
            - 192.168.0.0/16
      - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: "kube-system"
        - podSelector:
            matchLabels:
              k8s-app: "kube-dns"
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search