<p>In the past I've tried <code>NodePort</code> service and if I add a firewall rule to the corresponding Node, it works like a charm:</p>
<pre><code>  type: NodePort
  ports:
    - nodePort: 30000
      port: 80
      targetPort: 5000
</code></pre>
<p>I can access my service from outside and long as the node has an external IP(which it does by default in GKE).
However, the service can only be assigned to 30000+ range ports, which is not very convenient.
By the way, the Service looks as follows:</p>
<pre><code> kubectl get service -o=wide
NAME                     TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE   SELECTOR
web-engine-service   NodePort   10.43.244.110   &lt;none&gt;        80:30000/TCP   11m   app=web-engine-pod
</code></pre>
<p>Recently, I've come across a different configuration option that is documented <a href="https://kubernetes.io/docs/concepts/services-networking/service/#external-ips" rel="nofollow noreferrer">here</a>.
I've tried is as it seems quite promising and should allow to expose my service on any port I want.<br />
The configuration is as follows:</p>
<pre><code>  ports:
    - name: web-port
      port: 80
      targetPort: 5000
  externalIPs:
    - 35.198.163.215
</code></pre>
<p>After the service updated, I can see that External IP is indeed assigned to it:</p>
<pre><code>$ kubectl get service -o=wide
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP      PORT(S)   AGE   SELECTOR
web-engine-service   ClusterIP   10.43.244.110   35.198.163.215   80/TCP    19m   app=web-engine-pod
</code></pre>
<p>(where <code>35.198.163.215</code> - Node's external IP in GKE)</p>
<p>And yet, my app is not available on the Node's IP, unlike in the first scenario(I did add firewall rules for all ports I'm working with including <code>80</code>, <code>5000</code>, <code>30000</code>).</p>
<p>What's the point of <code>externalIPs</code> configuration then? What does it actually do?</p>
<p><strong>Note:</strong> I'm creating a demo project, so please don't tell me about <code>LoabBalancer</code> type, I'm well aware of that and will get to that a bit later.</p>

yuranos
<p>I wanted to give you more insight on:</p>
<ul>
<li>How you can manage to make it work.</li>
<li>Why it's not working in your example.</li>
<li>More information about exposing traffic on <code>GKE</code>.</li>
</ul>
<hr />
<h3>How you can manage to make it work?</h3>
<p>You will need to enter <strong>internal IP</strong> of your node/nodes to the service definition where <code>externalIP</code> resides.</p>
<p>Example:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Service
metadata:
  name: hello-external
spec:
  selector:
    app: hello
    version: 2.0.0
  ports:
    - name: http
      protocol: TCP
      port: 80 # port to send the traffic to
      targetPort: 50001 # port that pod responds to 
  externalIPs:
    - 10.156.0.47
    - 10.156.0.48
    - 10.156.0.49
</code></pre>
<hr />
<h3>Why it's not working in your example?</h3>
<p>I've prepared an example to show you why it doesn't work.</p>
<p>Assuming that you have:</p>
<ul>
<li>VM in GCP with:
<ul>
<li>any operating system that allows to run <code>tcpdump</code></li>
<li>internal IP of: <code>10.156.0.51</code></li>
<li>external IP of: <code>35.246.207.189</code></li>
<li>allowed the traffic to enter on port: <code>1111</code> to this VM</li>
</ul>
</li>
</ul>
<p>You can run below command <strong>(on VM)</strong> to capture the traffic coming to the port: <code>1111</code>:</p>
<ul>
<li><code>$ tcpdump port 1111 -nnvvS</code></li>
</ul>
<blockquote>
<ul>
<li>-nnvvS - don't resolve DNS or Port names, be more verbose when printing info, print the absolute sequence numbers</li>
</ul>
</blockquote>
<p>You will need to send a request to external IP: <code>35.246.207.189</code> of your VM with a port of: <code>1111</code></p>
<ul>
<li><code>$ curl 35.246.207.189:1111</code></li>
</ul>
<p>You will get a connection refused message but the packet will be captured. You will get an output similar to this:</p>
<pre class="lang-sh prettyprint-override"><code>tcpdump: listening on ens4, link-type EN10MB (Ethernet), capture size 262144 bytes
12:04:25.704299 IP OMMITED 
    YOUR_IP &gt; 10.156.0.51.1111: Flags [S], cksum 0xd9a8 (correct), seq 585328262, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 1282380791 ecr 0,sackOK,eol], length 0
12:04:25.704337 IP OMMITED
    10.156.0.51.1111 &gt; YOUR_IP: Flags [R.], cksum 0x32e3 (correct), seq 0, ack 585328263, win 0, length 0
</code></pre>
<p>By that example you can see the destination IP address for your packet coming to the VM. As shown above it's the <strong>internal IP</strong> of your VM and not external. That's why putting external IP in your <code>YAML</code> definition is not working.</p>
<blockquote>
<p>This example also works on <code>GKE</code>. For simplicity purposes you can create a <code>GKE</code> cluster with Ubuntu as base image and do the same as shown above.</p>
</blockquote>
<p>You can read more about IP addresses by following link below:</p>
<ul>
<li><em><a href="https://cloud.google.com/vpc/docs/ip-addresses" rel="nofollow noreferrer">Cloud.google.com: VPC: Docs: IP addresses</a></em></li>
</ul>
<hr />
<h3>More about exposing traffic on <code>GKE</code></h3>
<blockquote>
<p>What's the point of  <code>externalIPs</code>  configuration then? What does it actually do?</p>
</blockquote>
<p>In simple terms it will allow the traffic to enter your cluster. Request sent to your cluster will need to have destination IP the same as in the <code>externalIP</code> parameter in your service definition to be routed to the corresponding service.</p>
<p>This method requires you to track the IP addresses of your nodes and could be prone to issues when the IP address of your node will not be available (nodes autoscaling for example).</p>
<p>I recommend you to expose your services/applications by following official <code>GKE</code> documentation:</p>
<ul>
<li><a href="https://cloud.google.com/kubernetes-engine/docs/how-to/exposing-apps" rel="nofollow noreferrer">Cloud.google.com: Kubernetes Engine: Docs: How to: Exposing apps</a></li>
</ul>
<p>As mentioned before, <code>LoadBalancer</code> type of service will automatically take into consideration changes that were made to the cluster. Things like autoscaling which increase/decrease count of your nodes. With the service shown above (with <code>externalIP</code>) this would require manual changes.</p>
<p>Please let me know if you have any questions to that.</p>
