How to explicitely define an Endpoint of an Kubernetes Service
Asked Answered
E

2

5

I've provisioned a kubernetes cluster on my own couple of virtual machines via kubespray. Kubespray uses project-calico as default network-plugin which fits my requirements of proxying services in the cluster network to the outer world pretty well.

Kubespray deploys the apiserver itself as a ClusterIP Service. To make it reachable from outside it defines an Endpoint of this service with the master nodes Host IP Adress, which is routed to the internal ClusterIP by Calico as far as I could figure it out by myself.

My Question is: How is it possible to define my own endpoint (for another service), as these get implicietly defined already by provisioning the service.yaml and cannot be overwritten. I would like to follow a similar approach to get my Rook/Ceph Dashboard visible from outside the cluster.

EDIT: Note that kubectl get ingresses.networking.k8s.io --all-namespaces returns No resources found. and kubectl describe service kubernete returns

Name:              kubernetes
Namespace:         default
Labels:            component=apiserver
                   provider=kubernetes
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.233.0.1
Port:              https  443/TCP
TargetPort:        6443/TCP
Endpoints:         192.168.103.254:6443
Session Affinity:  None
Events:            <none>
Estebanesteem answered 19/12, 2019 at 15:41 Comment(4)
This is more to do with the ingress controller and ingress. For your service to work with custom endpoints to have external services reach the service that is running inside kubernetes cluster you need ingress attached to your service. For more details please refer to this documentation IngressCattima
@BinaryBullet yes, I`ve already read a lot about ingress and that this is the right way to loadbalance etc... I was just wondering that in a fresh kubesprayed cluster there is actually no ingress defined... it just works with Endpoint on Master Host IP routed to the ClusterIP service by calico and I was wondering how I could define a similar setupViridissa
If you do not want to use ingress and want to pick up through master host ip, you could directly use a proxy server or service (either haproxy, nginx, etc) to route traffic from external url to the particular host ip directly. I am exactly not sure if this is what you are looking for. If I wrong about this please feel free to correct me. As you already read about the ingress, it has an upper hand in doing all the traffic routing and management. Hope this is helpful.Cattima
@BinaryBullet this also isn't exactly what I am asking, because even if there is an HAProxy this does not solve the part of routing the nodes external IP to the cluster internal network IP. Ingress solves this, and it seems that there is another approach which is used by kubespray routing the apiserver to the outside by defining an endpoint on the Host IP explicetly. I would like to know how this definition can be done.Viridissa
H
1

I am not exactly sure if what You mean but i think what You are looking for is ability to expose services externally.

You can expose Your services like Rook/Ceph Dashboard with "Publishing Services" (service types that expose internal services externally).

As quoted from kubernetes documentation:

For some parts of your application (for example, frontends) you may want to expose a Service onto an external IP address, that’s outside of your cluster.

Kubernetes ServiceTypes allow you to specify what kind of Service you want. The default is ClusterIP.

Type values and their behaviors are:

  • ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the default ServiceType.
  • NodePort: Exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You’ll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
  • LoadBalancer: Exposes the Service externally using a cloud provider’s load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
  • ExternalName: Maps the Service to the contents of the externalName field (e.g. foo.bar.example.com), by returning a CNAME record with its value. No proxying of any kind is set up.

Here is an example from documentation.


You can also define the Services with yaml manifests like this:

apiVersion: v1
kind: Service
metadata:
  name: examplelb
spec:
  type: LoadBalancer
  selector:
    app: asd
  ports:
    -
      name: koala
      port: 22223
      targetPort: 22225
      nodePort: 31913
    -
      name: grisly
      port: 22224
      targetPort: 22226
      nodePort: 31914
    -
      name: polar
      port: 22225
      targetPort: 22227
      nodePort: 31915

This makes pods with label: app: asd have following ports exposed with pattern internal port 22223 exposed on 31913.

$ kubectl get svc examplelb
NAME        TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                           AGE
examplelb   LoadBalancer   10.111.8.204   <pending>     22223:31913/TCP,22224:31914/TCP,22225:31915/TCP   7d2h

If service with type LoadBalancer has External-IP pending you can still access all those ports on each node as NodePort.

Hope this helps.

Hendel answered 19/12, 2019 at 17:26 Comment(1)
Yes, I know....See my EDIT in the question...i am specifically querying because kubernetes API is deployed AS a "ClusterIP" Service...according to the documentation, these should only be visible inside the Cluster. Nevertheless I am able to reach my apiserver from Outsider because there is some kind of "calico Hack" which Males this possible. I am interested how this hack works.Viridissa
R
14

I'll refer to your question:

How is it possible to define my own endpoint?

You'll have to:

1 ) Create a Service without a Pod selector:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 9376

(At this point, no auto-generated Endpoints will be created by K8S because it can't decide to which pods those Endpoints should be referring).

2 ) Create an Endpoints object and map it to the desired network address and port where the external resource is running:

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 192.0.2.45
    ports:
      - port: 9376

(*) Notice that there should be a match between the service name and the name of the Endpoints object.

Ringler answered 21/10, 2020 at 12:33 Comment(1)
I was looking for this answer. Also here is the detailed explanation for this: kubernetes.io/docs/concepts/services-networking/service/…Erlindaerline
H
1

I am not exactly sure if what You mean but i think what You are looking for is ability to expose services externally.

You can expose Your services like Rook/Ceph Dashboard with "Publishing Services" (service types that expose internal services externally).

As quoted from kubernetes documentation:

For some parts of your application (for example, frontends) you may want to expose a Service onto an external IP address, that’s outside of your cluster.

Kubernetes ServiceTypes allow you to specify what kind of Service you want. The default is ClusterIP.

Type values and their behaviors are:

  • ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the default ServiceType.
  • NodePort: Exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You’ll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
  • LoadBalancer: Exposes the Service externally using a cloud provider’s load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
  • ExternalName: Maps the Service to the contents of the externalName field (e.g. foo.bar.example.com), by returning a CNAME record with its value. No proxying of any kind is set up.

Here is an example from documentation.


You can also define the Services with yaml manifests like this:

apiVersion: v1
kind: Service
metadata:
  name: examplelb
spec:
  type: LoadBalancer
  selector:
    app: asd
  ports:
    -
      name: koala
      port: 22223
      targetPort: 22225
      nodePort: 31913
    -
      name: grisly
      port: 22224
      targetPort: 22226
      nodePort: 31914
    -
      name: polar
      port: 22225
      targetPort: 22227
      nodePort: 31915

This makes pods with label: app: asd have following ports exposed with pattern internal port 22223 exposed on 31913.

$ kubectl get svc examplelb
NAME        TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                           AGE
examplelb   LoadBalancer   10.111.8.204   <pending>     22223:31913/TCP,22224:31914/TCP,22225:31915/TCP   7d2h

If service with type LoadBalancer has External-IP pending you can still access all those ports on each node as NodePort.

Hope this helps.

Hendel answered 19/12, 2019 at 17:26 Comment(1)
Yes, I know....See my EDIT in the question...i am specifically querying because kubernetes API is deployed AS a "ClusterIP" Service...according to the documentation, these should only be visible inside the Cluster. Nevertheless I am able to reach my apiserver from Outsider because there is some kind of "calico Hack" which Males this possible. I am interested how this hack works.Viridissa

© 2022 - 2024 — McMap. All rights reserved.