<p>How to connect <code>graphql</code> api which is on private network and accessible through private ip address. My frontend server and api is on the <code>VNET</code>.</p>

<pre><code>import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { createUploadLink } from 'apollo-upload-client'

const uploadLink = createUploadLink({
    uri: 'http://10.0.0.10:3000'+'/api'
})

const client = new ApolloClient({
    link: uploadLink,
    cache: new InMemoryCache()
})
export default client
</code></pre>

<p>Both applications are running on <code>kubernetes</code> same cluster different pods. Private services are accessible within cluster and when I <code>exec</code> into the frontend pod I am able to access <code>graphql</code> end point with private ip address.</p>

<p>But, On the browser, it's not connecting and giving this error: <code>ERR_CONNECTION_REFUSED</code></p>

<blockquote>
  <p>frontend (public ip) --> graphql (private ip)</p>
</blockquote>

<p>The 3 main methods for accessing an internal kubernetes service from outside are: <strong>NodePort</strong>, <strong>LoadBalancer</strong>, and <strong>Ingress</strong>.</p>
<p>You can read about some of the main differences between them here <a href="https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0" rel="nofollow noreferrer">https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0</a></p>
<hr />
<h1>NodePort</h1>
<h2>Map a randomly or manually selected high port from a certain range to a service on a 1 to 1 basis.</h2>
<p>Either allow kubernetes to randomly select a high port, or manually define a high port from a predefined range which is by default 30000–32767 (but can be changed), and map it to an internal service port on a 1 to 1 basis.</p>
<p>Warning: Although it is possible to manually define a NodePort port number per service, it is generally not recommended due to possible issues such as port conflicts. So in most cases, you should let the cluster randomly select a NodePort port number for you.</p>
<p>From official docs: <a href="https://kubernetes.io/docs/concepts/services-networking/service/#nodeport" rel="nofollow noreferrer">https://kubernetes.io/docs/concepts/services-networking/service/#nodeport</a></p>
<blockquote>
<p>If you set the type field to NodePort, the Kubernetes master will
allocate a port from a range specified by --service-node-port-range
flag (default: 30000-32767), and each Node will proxy that port (the
same port number on every Node) into your Service.</p>
</blockquote>
<hr />
<h1>LoadBalancer</h1>
<h2>Attach a service to an external ip provided by an IP Provider service such as a cloud provider Public IP Service.</h2>
<p>The functionality of this service type depends on external drivers/plugins. Most modern clouds offer support to supply public IPs for LoadBalancer definitions. But if you are spinning a custom cluster with no means to assign public IPs (such as with Rancher with no IP provider plugins), the best you can probably do with this is assign an IP of a host machine to a single service.</p>
<p>From the official docs: <a href="https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer" rel="nofollow noreferrer">https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer</a></p>
<blockquote>
<p>On cloud providers which support external load
balancers, setting the type field to LoadBalancer will provision a
load balancer for your Service. The actual creation of the load
balancer happens asynchronously, and information about the provisioned
balancer will be published in the Service’s .status.loadBalancer
field.</p>
</blockquote>
<hr />
<h1>Ingress</h1>
<h2>Run a central application router service which receives all traffic on a certain port (or ports) and routes it to services based on parameters like the requested domain and path.</h2>
<p>To install it you must create an application router service (such as nginx) which runs in your cluster and analyzes every new resource of type Ingress that is created. Then you create Ingress resource that define the routing rules you would like such as which DNS request to listen to and which service to forward the request to.</p>
<p>Although multiple solutions exist for this purpose, I recommend Nginx Ingress</p>
<p><a href="https://github.com/helm/charts/tree/master/stable/nginx-ingress" rel="nofollow noreferrer">https://github.com/helm/charts/tree/master/stable/nginx-ingress</a> <a href="https://github.com/kubernetes/ingress-nginx" rel="nofollow noreferrer">https://github.com/kubernetes/ingress-nginx</a></p>
<p>Official Docs:</p>
<blockquote>
<p>What is Ingress? Typically, services and pods have IPs only routable
by the cluster network. All traffic that ends up at an edge router is
either dropped or forwarded elsewhere. Conceptually, this might look
like:</p>
<pre><code>internet
    |   ------------   [ Services ] An Ingress is a collection of rules that allow inbound connections to reach the cluster services.

internet
    |    [ Ingress ]    --|-----|--    [ Services ] It can be configured to give services externally-reachable URLs, load balance
</code></pre>
<p>traffic, terminate SSL, offer name based virtual hosting, and more.
Users request ingress by POSTing the Ingress resource to the API
server. An Ingress controller is responsible for fulfilling the
Ingress, usually with a loadbalancer, though it may also configure
your edge router or additional frontends to help handle the traffic in
an HA manner.</p>
</blockquote>
