<p>Do I still need to expose pod via <code>clusterip</code> service?</p>
<p>There are 3 pods - main, front, api. I need to allow ingress+egress connection to main pod only from the pods- api and frontend. I also created service-main - service that exposes main pod on <code>port:80</code>.</p>
<p>I don't know how to test it, tried:</p>
<pre><code>k exec main -it -- sh
netcan -z -v -w 5 service-main 80
</code></pre>
<p>and</p>
<pre><code>k exec main -it -- sh
curl front:80
</code></pre>
<p>The main.yaml pod:</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  labels:
    app: main
    item: c18
  name: main
spec:
  containers:
  - image: busybox
    name: main
    command:
    - /bin/sh
    - -c
    - sleep 1d
</code></pre>
<p>The front.yaml:</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  labels:
    app: front
  name: front
spec:
  containers:
  - image: busybox
    name: front
    command:
    - /bin/sh
    - -c
    - sleep 1d
</code></pre>
<p>The api.yaml</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  labels:
    app: api
  name: api
spec:
  containers:
  - image: busybox
    name: api
    command:
    - /bin/sh
    - -c
    - sleep 1d  
</code></pre>
<p>The main-to-front-networkpolicy.yaml</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: front-end-policy
spec:
  podSelector:
    matchLabels:
      app: main
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: front
    ports:
    - port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
           app: front
    ports:
    - port: 8080
</code></pre>
<p>What am I doing wrong? Do I still need to expose main pod via service? But should not network policy take care of this already?</p>
<p>Also, do I need to write <code>containerPort:80</code> in main pod? How to test connectivity and ensure ingress-egress works only for main pod to api, front pods?</p>
<p>I tried the lab from ckad prep course, it had 2 pods: secure-pod and web-pod. There was issue with connectivity, the solution was to create network policy and test using netcat from inside the web-pod's container:</p>
<pre><code>k exec web-pod -it -- sh
nc -z -v -w 1 secure-service 80
connection open
</code></pre>
<p>UPDATE: ideally I want answers to these:</p>
<ul>
<li><p>a clear explanation of the diff btw <code>service</code> and <code>networkpolicy</code>.
If both service and netpol exist - what is the order of evaluation that the traffic/request goes thru? It first goes thru netpol then service? Or vice versa?</p>
</li>
<li><p>if I want front and api pods to send/receive traffic to main - do I need separate services exposing front and api pods?</p>
</li>
</ul>

<p>Network policies and services are two different and independent Kubernetes resources.</p>
<p><a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="nofollow noreferrer">Service is</a>:</p>
<blockquote>
<p>An abstract way to expose an application running on a set of <a href="https://kubernetes.io/docs/concepts/workloads/pods/" rel="nofollow noreferrer">Pods</a> as a network service.</p>
</blockquote>
<p>Good explanation <a href="https://kubernetes.io/docs/concepts/services-networking/service/#motivation" rel="nofollow noreferrer">from the Kubernetes docs</a>:</p>
<blockquote>
<p>Kubernetes  <a href="https://kubernetes.io/docs/concepts/workloads/pods/" rel="nofollow noreferrer">Pods</a>  are created and destroyed to match the state of your cluster. Pods are nonpermanent resources. If you use a  <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="nofollow noreferrer">Deployment</a>  to run your app, it can create and destroy Pods dynamically.</p>
<p>Each Pod gets its own IP address, however in a Deployment, the set of Pods running in one moment in time could be different from the set of Pods running that application a moment later.</p>
<p>This leads to a problem: if some set of Pods (call them &quot;backends&quot;) provides functionality to other Pods (call them &quot;frontends&quot;) inside your cluster, how do the frontends find out and keep track of which IP address to connect to, so that the frontend can use the backend part of the workload?</p>
<p>Enter  <em>Services</em>.</p>
</blockquote>
<p>Also another good explanation <a href="https://stackoverflow.com/questions/56896490/what-exactly-kubernetes-services-are-and-how-they-are-different-from-deployments/56896662#56896662">in this answer</a>.</p>
<p><a href="https://kubernetes.io/docs/concepts/workloads/pods/#using-pods" rel="nofollow noreferrer">For production you should use</a> a <a href="https://kubernetes.io/docs/concepts/workloads/" rel="nofollow noreferrer">workload resources</a> instead of creating pods directly:</p>
<blockquote>
<p>Pods are generally not created directly and are created using workload resources. See  <a href="https://kubernetes.io/docs/concepts/workloads/pods/#working-with-pods" rel="nofollow noreferrer">Working with Pods</a>  for more information on how Pods are used with workload resources.
Here are some examples of workload resources that manage one or more Pods:</p>
<ul>
<li><a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="nofollow noreferrer">Deployment</a></li>
<li><a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/" rel="nofollow noreferrer">StatefulSet</a></li>
<li><a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset" rel="nofollow noreferrer">DaemonSet</a></li>
</ul>
</blockquote>
<p>And use services to make requests to your application.</p>
<p>Network policies <a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/" rel="nofollow noreferrer">are used to control traffic flow</a>:</p>
<blockquote>
<p>If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), then you might consider using Kubernetes NetworkPolicies for particular applications in your cluster.</p>
</blockquote>
<p>Network policies target pods, not services (an abstraction). Check <a href="https://stackoverflow.com/questions/66423222/kubernetes-networkpolicy-limit-egress-traffic-to-service">this answer</a> and <a href="https://stackoverflow.com/a/55527331/16391991">this one</a>.</p>
<p>Regarding your examples - your network policy is correct (as I tested it below). The problem is that your cluster <a href="https://stackoverflow.com/questions/65017380/kubernetes-network-policy-deny-all-policy-not-blocking-basic-communication/65022827#65022827">may not be compatible</a>:</p>
<blockquote>
<p>For Network Policies to take effect, your cluster needs to run a network plugin which also enforces them. <a href="https://docs.projectcalico.org/getting-started/kubernetes/" rel="nofollow noreferrer">Project Calico</a> or <a href="https://cilium.io/" rel="nofollow noreferrer">Cilium</a> are plugins that do so. This is not the default when creating a cluster!</p>
</blockquote>
<p>Test on kubeadm cluster with Calico plugin -&gt; I created similar pods as you did, but I changed <code>container</code> part:</p>
<pre><code>spec:
  containers:
    - name: main
      image: nginx
      command: [&quot;/bin/sh&quot;,&quot;-c&quot;]
      args: [&quot;sed -i 's/listen  .*/listen 8080;/g' /etc/nginx/conf.d/default.conf &amp;&amp; exec nginx -g 'daemon off;'&quot;]
      ports:
      - containerPort: 8080
</code></pre>
<p>So NGINX app is available at the <code>8080</code> port.</p>
<p>Let's check pods IP:</p>
<pre><code>user@shell:~$ kubectl get pods -o wide
NAME     READY   STATUS      RESTARTS        AGE   IP               NODE                                NOMINATED NODE   READINESS GATES
api      1/1     Running     0               48m   192.168.156.61   example-ubuntu-kubeadm-template-2   &lt;none&gt;           &lt;none&gt;
front    1/1     Running     0               48m   192.168.156.56   example-ubuntu-kubeadm-template-2   &lt;none&gt;           &lt;none&gt;
main     1/1     Running     0               48m   192.168.156.52   example-ubuntu-kubeadm-template-2   &lt;none&gt;           &lt;none&gt;
</code></pre>
<p>Let's <a href="https://kubernetes.io/docs/tasks/debug-application-cluster/get-shell-running-container/" rel="nofollow noreferrer">exec into running <code>main</code> pod</a> and try to make request to the <code>front</code> pod:</p>
<pre class="lang-sh prettyprint-override"><code>root@main:/# curl 192.168.156.61:8080
&lt;!DOCTYPE html&gt;
...
&lt;title&gt;Welcome to nginx!&lt;/title&gt;
</code></pre>
<p>It is working.</p>
<p>After applying your network policy:</p>
<pre class="lang-sh prettyprint-override"><code>user@shell:~$ kubectl apply -f main-to-front.yaml 
networkpolicy.networking.k8s.io/front-end-policy created
user@shell:~$ kubectl exec -it main -- bash
root@main:/# curl 192.168.156.61:8080
...
</code></pre>
<p>Not working anymore, so it means that network policy is applied successfully.</p>
<p>Nice option to get more information about applied network policy is to run <code>kubectl describe</code> command:</p>
<pre><code>user@shell:~$ kubectl describe networkpolicy front-end-policy
Name:         front-end-policy
Namespace:    default
Created on:   2022-01-26 15:17:58 +0000 UTC
Labels:       &lt;none&gt;
Annotations:  &lt;none&gt;
Spec:
  PodSelector:     app=main
  Allowing ingress traffic:
    To Port: 8080/TCP
    From:
      PodSelector: app=front
  Allowing egress traffic:
    To Port: 8080/TCP
    To:
      PodSelector: app=front
  Policy Types: Ingress, Egress
</code></pre>
