<p>What is the best way to define a rule that allows egress only to the kube-apiserver with a Network Policy?</p>

<p>While there's a <code>Service</code> resource for the kube-apiserver, there's not <code>Pods</code>, so as far as I know this can't be done with labels. With IP whitelisting, this isn't guaranteed to work across clusters. Is there any recommended practice here?</p>

<p>You have to use the IP address of the apiserver. You cannot use labels.<br>
To find the IP address of the apiserver run:<br>
<code>kubectl cluster-info</code>  </p>

<p>Look for a line like this in the output:<br>
<code>Kubernetes master is running at https://&lt;ip&gt;</code><br>
This is the IP address of your apiserver IP.</p>

<p>The network policy should look like this (assuming the apiserver IP is 34.76.197.27):</p>

<pre><code>apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-apiserver
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 34.76.197.27/32
    ports:
    - protocol: TCP
      port: 443
</code></pre>

<p><a href="https://orca.tufin.io/netpol/?yaml=apiVersion:%20networking.k8s.io%2Fv1%0Akind:%20NetworkPolicy%0Ametadata:%0A3name:%20egress-apiserver%0Aspec:%0A3podSelector:%20%7B%7D%0A3policyTypes:%0A3-%20Egress%0A3egress:%0A3-%20to:%0A5-%20ipBlock:%0A9cidr:%2034.76.197.27%2F32%0A5ports:%0A5-%20protocol:%20TCP%0A7port:%20443%0A" rel="nofollow noreferrer">The policy above applies to all pods in the namespaces it is applied to</a>.<br>
To select specific pods, edit the podSelector section with the tags of the pods that require apiserver access:</p>

<pre><code>  podSelector:
    matchLabels:
      app: apiserver-allowed
</code></pre>

<p>Remember that the default egress policy is ALLOW ALL which means other pods will still have access to the apiserver.<br>
<a href="https://orca.tufin.io/netpol/?yaml=apiVersion:%20networking.k8s.io%2Fv1%0Akind:%20NetworkPolicy%0Ametadata:%0A3name:%20deny-all-egress%0Aspec:%0A3podSelector:%20%7B%7D%0A3policyTypes:%0A3-%20Egress%0A" rel="nofollow noreferrer">You can change this behavior by adding a "BLOCK ALL" egress policy per namespace</a> but remember not to block access to the DNS server and other essential services.<br>
<a href="https://medium.com/@reuvenharrison/an-introduction-to-kubernetes-network-policies-for-security-people-ba92dd4c809d" rel="nofollow noreferrer">For more info see "Egress and DNS (Pitfall!)" in this post</a>.</p>

<p>Note that in some cases there may be more than one apiservers (for scalability) in which case you will need to add all the IP addresses.</p>
