2

I have a api-service with type 'ClusterIp' which is working fine and is accessible on the node with clusterip. I want to access it externally . It's a baremetal installation with kubeadm . I cannot use Loadbalancer or Nodeport.

If I use nginx-ingress that too I will use as 'ClusterIP' so how to get the service externally accessible in either api service or nginx-ingress case .

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
api                    ClusterIP   10.97.48.17      <none>        80/TCP           41s
ingress-nginx          ClusterIP   10.107.76.178    <none>        80/TCP           3h49m

Changes to solve the issue:

  1. nginx configuration on node

in /etc/nginx/sites-available

 upstream backend {
       server node1:8001;
       server node2:8001;
       server node3:8001;
        }
    server_name _;

    location / {
            proxy_pass http://backend;
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ =404;
    }
  1. Ran my two services as DaemonSet
Charvee Punia
  • 423
  • 1
  • 6
  • 17
  • did you figure this out? – Black_Bacardi Jan 15 '20 at 14:23
  • 1
    Yes I ran two of my service as DeamonSet and configured nginx on my one of node . Also one can make nginx-ingress as DeamonSet but I was facing some issue with that . Adding my nginx config above which I did on my node. – Charvee Punia Jan 16 '20 at 10:48

2 Answers2

2

ClusterIP services are accesible only within the cluster.

For bare metal clusters, you can use any of the following approaches to make a service available externally. Suggestions are from most recommended to least recommended order:

  1. Use metallb to implement LoadBalancer service type support - https://metallb.universe.tf/. You will need a pool of IP addresses for metallb to handout. It also supports IP sharing mode where you can use same IP for multiple LoadBalancer services.

  2. Use NodePort service. You can access your service from any node IP:node_port address. NodePort service selects random port in node port range by default. You can choose a custom port in node port range using spec.ports.nodePort field in the service specification.

    Disadvantage: The node port range by default is 30000-32767. So you cannot bind to any custom port that you want like 8080. Although you can change the node port range with --service-node-port-range flag of kube-api-server, it is not recommended to use it with low port ranges.

  3. Use hostPort to bind a port on the node.

    Disadvantage: You don't have fixed IP address because you don't know which node your pod gets scheduled to unless you use nodeAffinity. You can make your pod a daemonset if you want it to be accessible from all nodes on the given port.

If you are dealing with HTTP traffic, another option is installing an IngressController like nginx or Traefik and use Ingress resource. As part of their installation, they use one of the approaches mentioned above to make themselves available externally.

Shashank V
  • 10,007
  • 2
  • 25
  • 41
0

Well, as you can guess by reading the name, ClusterIp is only accessible from inside the cluster.

To make a service accessible from outside the cluster, you havec 3 options :

  1. NodePort Service type
  2. LoadBalancer Service type (you still have to manage your LoadBalancer manually though)
  3. Ingress

There is a fourth option which is hostPort (which is not a service type) but I'd rather keep it from special case when you're absolutely sure that your pod will always be located on the same node (or eventually for debug).

Having this said, then this leaves us only with one solution offered by Kubernetes : Ingress.

Marc ABOUCHACRA
  • 3,155
  • 12
  • 19
  • `Ingress` is just a L7 router. It doesn't have any mechanism to make your service available externally by itself. – Shashank V Jan 07 '20 at 13:31
  • Beside the fact that it is *just* a router, it's still another ressource type implemented in K8S. It has nothing to do with the `LoadBalancer` service and the use of `Ingress` is totaly different from `LoadBalancer`. And of course, the `Ingress` itself is not sufficient, you still have to add an `IngressController` but I felt like it was straightforward when using `Ingress`. My bad for not mentionning it. – Marc ABOUCHACRA Jan 07 '20 at 13:36
  • How are you going to expose `IngressController` externally? You still need a `LoadBalancer` or hack it around using `NodePort` service. – Shashank V Jan 07 '20 at 13:53
  • By definition an IngressController **is** a load balancer, so no you won't need any load balancer implementation in addition to your `IngressController`. Here is a [list](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#additional-controllers) of some (all?) existing IC. You'll see that they are all load balancer. – Marc ABOUCHACRA Jan 07 '20 at 14:12
  • `IngressController` also builds upon using existing LoadBalancer or NodePort or hostPort with daemonset to receive external traffic. You can see it in the installation instructions of nginx-ingress-controller. https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/installation.md – Shashank V Jan 07 '20 at 14:27
  • I understand what you are trying to get at though. What I'm trying to say is that Ingress by itself doesn't solve the issue of external connectivity. You need to solve the issue of external connectivity for ingress itself first using one of internal/external LoadBalancer or NodePort or hostPort approach. Only then you can Ingress. – Shashank V Jan 07 '20 at 14:34
  • The part with daemonset is false. You're making a generality from the specific case of Nginx. Also the original question is : *how do I access a service from outside the cluster?* And using IngressController/Ingress is a correct answer. **I** use `ClusterIp` services right now in my cluster and actually **I'm** exposing them throught an Ingress using Traefik as the IC. Of course, we're not talking about how it is *actually* implemented. This is another subject. But hey if you feel like my answer is wrong, just downvote it. – Marc ABOUCHACRA Jan 07 '20 at 14:41
  • Can you elaborate on `The part with daemonset is false`? Even Traefik uses one of NodePort or daemonset with hostPort to make itself available externally. – Shashank V Jan 07 '20 at 15:15
  • so whatever IC we use in the Service type we need to specify (Loadbalancer, NodePort or ClusterIP) . In my case I can only use ClusterIP as it's baremetal . if I'm using NodePort as type it does not return anything on curl maybe because i'm not using daemonset. I can try that once . I also don't want to use metallb and want to see if there is a work around without it . – Charvee Punia Jan 08 '20 at 04:46
  • Yes, any `IngressController` should do the job. Don't forget to create the `Ingress` to point to your service (`ClusterIP` is perfectly fine). – Marc ABOUCHACRA Jan 08 '20 at 08:11
  • So above in my question as you can see I have created ingress-nginx as clusterIp . Now my FrontEnd application is on the same node as Apache application. I want to hit api service which is registerd on ingress-nginx , so for this how will I access the nginx . Do I need to patch an external IP to the ingress-nginx svc ? – Charvee Punia Jan 08 '20 at 08:32
  • No, once you have your IC up and running, all you need to do is to create an `Ingress` that points to your `ingress-nginx` svc. However, i don't really understand why you need the ingress-nginx svc to hit your api svc. Why don't you just call the api directly ? – Marc ABOUCHACRA Jan 08 '20 at 08:52